-
Notifications
You must be signed in to change notification settings - Fork 114
Deriving the TS trait
The TS
trait can be easily derived through its #[derive(TS)]
macro,
which will automatically handle mapping a Rust type into TypeScript type
definitions.
The #[derive(TS)]
macro provides an attribute helper macro called #[ts(...)]
which can help you control how the types will be generated
These are attributes that can be used both with structs and enums
This attribute causes the generation of a test which will create a ts file
containing the TypeScript declaration for your type, as well as any types
it depends on (as long as they implement TS
)
Allows you to change where your TypeScript file will be generated.
The default is ./bindings/TypeName.ts
, this path is relative to Cargo.toml
.
Usage:
#[derive(ts_rs::TS)]
#[ts(export)]
struct MyStruct {
foo: String
}
This must be either:
- An absolute path
- A path relative to your crate's
Cargo.toml
The given path will be treated as a directory if it ends with a /
character, in which case a file called TypeName.ts
will be created
within the given directory, otherwise the path will be treated as a
file (even without an extension).
Usage:
#[derive(ts_rs::TS)]
#[ts(export, export_to = "../ts_project/bindings/")] // Note that #[ts(export)] is still required
struct MyStruct {
foo: String
}
If you see yourself using #[ts_export = "..."]
with the same directory
for a lot (or even all) your types, there is a more convenient way to do
this.
Create a directory at the root of your project (the directory that contains
Cargo.toml
) called .cargo
. Inside the .cargo
directory, create a file
called config.toml
and type the following:
[env]
TS_RS_EXPORT_DIR = { value = "...", relative = true }
Where value
is a path to a directory (i.e. it must end with a slash /
)
relative to your Cargo.toml
file.
Now, using #[ts(export)]
without #[ts(export_to = "...")]
will result
in exporting to the directory defined in your config.toml
file.
Note that if you use #[ts(export_to = "...")]
with this config, the path
given to TS_RS_EXPORT_DIR
will be concatenated with the path given to
export_to
as if they were strings, so using ../foo/bar/
in export_to
will cause problems, due to a currently unresolved issue with parent
components in the middle of paths.
Changes the name of your type's TypeScript representation.
If the feature flag serde-compat
is enabled (default), using
#[serde(rename = "...")]
will have the same effect.
Usage:
#[derive(ts_rs::TS)]
#[ts(export, rename = "MyType")]
struct MyStruct {
foo: String
}
Generates:
export type MyType = { foo: string, };
Renames all the fields in your struct or variants in your enum to use a given inflection.
Accepted values are lowercase
, snake_case
, kebab-case
, UPPERCASE
,
camelCase
, PascalCase
and SCREAMING_SNAKE_CASE
.
If the feature flag serde-compat
is enabled (default), using
#[serde(rename_all = "...")]
will have the same effect.
Usage:
#[derive(ts_rs::TS)]
#[ts(export, rename_all = "camelCase")]
struct MyStruct {
foo_bar: String
}
Generates:
export type MyStruct = { fooBar: string, };
Adds the optional modifier (?
) to the TS type, allowing a field to be undefined
or missing
#[derive(TS)]
#[ts(export)]
struct Foo {
#[ts(optional)]
bar: u32,
}
Generates
export type Foo = { bar?: number, };
Adds both the optional modifier and | null
to the type
#[derive(TS)]
#[ts(export)]
struct Foo {
#[ts(optional = nullable)]
bar: u32,
}
Generates
export type Foo = { bar?: number | null, };
Avoids generating TS definitions to a field or variant
#[derive(TS)]
#[ts(export)]
struct Foo {
#[ts(skip)]
bar: u32,
baz: String,
}
Generates
export type Foo = { baz: string, };
By default, enum type definitions will match serde's externally tagged enums, which means
#[derive(TS)]
#[ts(export)]
enum Message {
Request { id: String, method: String, params: HashMap<String, String> },
Response { id: String, status: u8 },
}
Generates:
// Note: this code snipped has been formatted manually to facilitate readability
// The exported code is not guaranteed to match this formatting, even with the
// "format" feature flag
export type Message =
| { "Request": { id: string, method: string, params: Record<string, string>, } }
| { "Response": { id: string, status: number, } };
Generates TS types for a serde internally tagged enum (TS calls these "discriminated unions")
#[derive(TS)]
#[ts(tag = "type")]
enum Message {
Request { id: String, method: String, params: HashMap<String, String> },
Response { id: String, status: u8 },
}
Geneates
export type Message = { "type": "Request", method: string, params: Record<string, string>, } | { "type": "Response", status: number, };
Generates TS types for a serde adjacently tagged enum
#[derive(TS)]
#[ts(tag = "t", content = "c")]
enum Block {
Para(Vec<String>),
Str(String),
}
Geneates
export type Block = { "t": "Para", "c": Array<string>, } | { "t": "Str", "c": string, };
Generates TS types for a serde untagged enum
#[derive(TS)]
#[ts(untagged)]
enum Message {
Request { id: String, method: String, params: HashMap<String, String> },
Response { id: String, status: u8 },
}
Geneates
export type Message = { id: string, method: string, params: Record<string, string>, } | { id: string, status: number, };
Equivalent to adding #[ts(rename_all = "..."]
to every variant.
Accepted values are lowercase
, snake_case
, kebab-case
, UPPERCASE
,
camelCase
, PascalCase
and SCREAMING_SNAKE_CASE
.