---
title: 'Function'
description: Define and use JavaScript functions in NAPI-RS.
---

# Function

Defining a JavaScript `function` is very simple in **NAPI-RS**. Just a plain Rust `fn`:

**lib.rs**

```rust
#[napi]
pub fn sum(a: u32, b: u32) -> u32 {
  a + b
}
```

The most important thing you should keep in mind is **_NAPI-RS fn does not support every Rust type_**. Here is a table to illustrate how JavaScript types map to Rust types when they are `fn` arguments and return types:

## Arguments

| Rust Type                                               | JavaScript Type                                                               |
| ------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `u32`                                                   | `number`                                                                      |
| `i32`                                                   | `number`                                                                      |
| `i64`                                                   | `number`                                                                      |
| `f64`                                                   | `number`                                                                      |
| `bool`                                                  | `boolean`                                                                     |
| `String`                                                | `string`                                                                      |
| `Latin1String`                                          | `string`                                                                      |
| `UTF16String`                                           | `string`                                                                      |
| `#[napi(object)] struct`                                | `Object`                                                                      |
| `& struct` or `&mut struct`                             | [Class](./class) instance                                                     |
| `serde_json::Map`                                       | `Object`                                                                      |
| `serde_json::Value`                                     | `unknown`                                                                     |
| `std::collections::HashMap`                             | `Object`                                                                      |
| `Array`                                                 | `unknown[]`                                                                   |
| `Vec<T>` T must be types in this table                  | T[]                                                                           |
| `Buffer`                                                | `Buffer`                                                                      |
| `External`                                              | [`External`](https://nodejs.org/api/n-api.html#napi_create_external)          |
| `Null`                                                  | `null`                                                                        |
| `Undefined` / `()`                                      | `undefined`                                                                   |
| `Option<T>`                                             | `T or null`                                                                   |
| `Fn(Arg) ->T` `Arg `and `T` must be types in this table | `(arg: Arg) => T`                                                             |
| `Promise<T>`                                            | `Promise<T>`                                                                  |
| `AbortSignal`                                           | [`AbortSignal`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal) |
| `JsSymbol`                                              | `Symbol`                                                                      |
| `Int8Array` / `Uint8Array` / `Int16Array`...            | `TypedArray`                                                                  |
| `BigInt`                                                | `BigInt`                                                                      |

## Return Type

| Rust Type                                    | JavaScript Type  |
| -------------------------------------------- | ---------------- |
| `u32`                                        | `number`         |
| `i32`                                        | `number`         |
| `i64`                                        | `number`         |
| `f64`                                        | `number`         |
| `bool`                                       | `boolean`        |
| `String`                                     | `string`         |
| `Latin1String`                               | `string`         |
| `UTF16String`                                | `string`         |
| `#[napi(object)] struct`                     | `Object`         |
| `#[napi] struct`                             | [Class](./class) |
| `serde_json::Map`                            | `Object`         |
| `serde_json::Value`                          | `unknown`        |
| `std::collections::HashMap`                  | `Object`         |
| `Array`                                      | `unknown[]`      |
| `Vec<T>` T must be types in this table       | `T[]`            |
| `Buffer`                                     | `Buffer`         |
| `External`                                   | `External`       |
| `Null`                                       | `null`           |
| `Undefined` / `()`                           | `undefined`      |
| `Option<T>`                                  | `T` or `null`    |
| `AsyncTask<Task<JsValue = T>>`               | `Promise<T>`     |
| `JsSymbol`                                   | `Symbol`         |
| `Int8Array` / `Uint8Array` / `Int16Array`... | `TypedArray`     |
| `BigInt`                                     | `BigInt`         |
| `i64n`                                       | `BigInt`         |
| `i128`                                       | `BigInt`         |
| `u128`                                       | `BigInt`         |

## `Function` as parameter

You can pass a `Function` as a parameter to a `fn`:

**lib.rs**

```rust
use napi::bindgen_prelude::*;
use napi_derive::napi;

#[napi]
pub fn call_function(callback: Function<u32, u32>) -> Result<u32> {
  callback.call(1)
}
```

⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️

**index.d.ts**

```ts
export declare function callFunction(callback: (arg: number) => number): number
```

::: info
You can also create a `Function` at the Rust side, see [`Env::create_function`](/docs/concepts/env#create_function)

:::

## `FnArgs`

When the number of parameters exceeds 1, you can use `FnArgs` to define the parameters.

::: info
The `tuple` type can be converted to `FnArgs` by calling `.into()`.

:::

**lib.rs**

```rust {6}
use napi::bindgen_prelude::*;
use napi_derive::napi;

#[napi]
pub fn call_function_with_args(callback: Function<FnArgs<(u32, u32)>, u32>) -> Result<u32> {
  callback.call((1, 2).into())
}
```

⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️ ⬇️

**index.d.ts**

```ts
export declare function callFunctionWithArgs(
  callback: (arg1: number, arg2: number) => number,
): number
```

## `apply`

Like JavaScript, you can also use `apply` to call a `Function` with the `this` value.

**lib.rs**

```rust
use napi::bindgen_prelude::*;
use napi_derive::napi;

#[napi]
pub struct RustClass {
  pub name: String,
}

#[napi]
impl RustClass {
  #[napi(constructor)]
  pub fn new(name: String) -> Self {
    Self { name }
  }
}

#[napi]
pub fn call_function_with_apply(
  this: ClassInstance<RustClass>,
  callback: Function<(), ()>,
) -> Result<()> {
  callback.apply(this, ())
}
```

**index.ts**

```ts
import { callFunctionWithApply, RustClass } from './index.js'

const rustClass = new RustClass('foo')

callFunctionWithApply(rustClass, function () {
  console.log(this.name) // foo
})
```

## `create_ref`

See [**Function Reference**](/docs/concepts/reference#functionref) for more details.

## `build_threadsafe_function`

You can build a `ThreadsafeFunction` from a `Function` by calling `build_threadsafe_function`.

The return type of the `build_threadsafe_function` is a `ThreadsafeFunctionBuilder`.

By default, the `ThreadsafeFunctionBuilder` will create a `ThreadsafeFunction` with the default options:

::: info
See [**ThreadsafeFunction**](/docs/concepts/threadsafe-function) for the details of options

:::

::: tip
Since you can pass `ThreadsafeFunction` and `Arc<ThreadsafeFunction>` directly to the `#[napi] fn`, only use the `build_threadsafe_function` when you are need to create a `ThreadsafeFunction` dynamically.

:::

- `max_queue_size` is `0`
- `weak` is `false`
- `callee_handled` is `true`
- `error_status` is `napi::Status`

**lib.rs**

```rust
use napi::{bindgen_prelude::*, threadsafe_function::ThreadsafeFunctionCallMode};
use napi_derive::napi;

#[napi]
pub fn build_threadsafe_function_from_function(
  callback: Function<FnArgs<(u32, u32)>, u32>,
) -> Result<()> {
  let tsfn = callback.build_threadsafe_function().build()?;
  let jh = std::thread::spawn(move || {
    tsfn.call((1, 2).into(), ThreadsafeFunctionCallMode::NonBlocking);
  });

  Ok(())
}
```
