#tauri #tauri-app #tauri-type-macros

macro tauri-types

Type generating macros for Tauri apps

2 releases

0.0.2 Aug 15, 2023
0.0.1 Aug 9, 2023

#357 in Procedural macros

27 downloads per month

Apache-2.0 OR MIT

21KB
502 lines

Tauri Types

A small library that translates the types from Rust to TypeScript for better integration for the invoke function from Tauri.

Check it out on:

Usage

  1. Add Tauri Types to your project.
cargo add tauri-types
  1. Add the derive to a type you want to have access to in your JavaScript program. It can be either struct or enum.
use tauri_types::TauriType;

#[derive(TauriType)]
struct User {
  name: String,
  username: String,
  password: String,
  age: u32,
}

That's going to generate this in your tauri-types.ts file.

export type User = {
  name: string;
  username: string;
  password: string;
  age: number;
};

You can use the type by importing it from the tauri-types.ts file.

import { type User } from './tauri-types';
  1. Add the tauri_types::command macro above any function you want to export.
#[tauri_types::command]
fn get_user() -> User {
  return User {
    name: "Marko".to_string(),
    username: "Maki325".to_string(),
    password: "YoullNeverGuessIt".to_string(),
    age: 20,
  }
}

(You can export it with use tauri_types::command;, but it's better to use it this way, so it doesn't collide with the command macro from tauri.)

  1. Replace tauri::generate_handler macro with tauri_types::generate_invoke.
...
// .invoke_handler(tauri::generate_handler![
.invoke_handler(tauri_types::generate_invoke![
  get_user,
])
.run(tauri::generate_context!())
.expect("error while running tauri application");
...
  1. Import invoke from the tauri-types.ts, instead of directly from tauri.
// import { invoke } from '@tauri-apps/api/tauri';
import { invoke } from './tauri-types';
  1. Enjoy your type-safe invoke.

Known dislike

You will need to always use the second argument, even if it's undefined. I'm still trying to figure out a way to disable that, but for now just set it to undefined.

Example:

import { invoke } from './tauri-types';

async function main() {
  // This **WILL** give a typescript error, for now
  // const user = await invoke('get_user');

  // This **WILL** work fine
  const user = await invoke('get_user', undefined);

  console.log('User:', user);
}

Additional features

Export types with the same name under different namespaces:
#[derive(TauriType)]
#[namespace = "db"]
struct User {
  name: String,
  username: String,
  password: String,
  age: u32,
}

That's going to generate this in your tauri-types.ts file.

export namespace db {
  export type User = {
    name: string;
    username: string;
    password: string;
    age: number;
  };
}
Use custom type path for a function argument:

If the type you want is in another namespace or you want to explicitly type it to something else, you can use this feature.

#[tauri_types::command]
fn get_username(
  #[path = "db.User"]
  user: User
) -> String {
  return user.username;
}
Use custom type path for a function return type:

If the type you want is in another namespace or you want to explicitly type it to something else, you can use this feature.

#[tauri_types::command]
#[return_path = "db.User"]
fn get_user() -> User {
  return User {
    name: "Marko".to_string(),
    username: "Maki325".to_string(),
    password: "YoullNeverGuessIt".to_string(),
    age: 20,
  }
}

Issues

If there are any issues, open one in the Issues tab on GitHub. Just be sure that there isn't one like yours already opened!

This is a very side project for me, but I'll try to keep it working.

Dependencies

~260–700KB
~17K SLoC