Giter Site home page Giter Site logo

ts-rs's People

Contributors

aatukaj avatar arendjr avatar asv7c2 avatar aumetra avatar blackbeam avatar dr-bonez avatar dusterthefirst avatar escritorio-gustavo avatar halfvoxel avatar heliozoa avatar jadrouil avatar josema03 avatar kronsyc avatar laptou avatar marjakm avatar niedzwiedzw avatar nyxcode avatar patrickelectric avatar peter-formlogic avatar phoneticsushi avatar roms1383 avatar splittydev avatar stegabob avatar sthamman2024 avatar teenjuna avatar theduke avatar timephy avatar tymmesyde avatar varonroy avatar wilsongramer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ts-rs's Issues

Is there a reason why i64 and u64 uses number instead of bigint?

rust's i64::MAX == 9223372036854775807(2^63 - 1) while in javascript Number.MAX_SAFE_INTEGER == 9007199254740991 (2^53 - 1)

But in this library, only i128 and u128 is defined using BigInt. So I was wondering if there was some reasoning behind the decision.

Doesn't work or docs need editing

I tried this out but it doesn't work. Maybe you missed something out in the documentation but I could not get this to work in the short amount of time I wanted to. I did it manually.

In the future it would be cool if this could work straightforward.

Ordering of imports changes from time to time

Currently, ts-rs relies on the ordering of rust's TypeId to write out imports. However, the rust documentation specifies:

While TypeId implements Hash, PartialOrd, and Ord, it is worth noting that the hashes and ordering will vary between Rust releases. Beware of relying on them inside of your code!

This means that the ordering of imports may change from time to time. Especially when using version control, this causes unnecessary changes.

I would recommend sorting by name instead.

Wrong import paths in generated TS files for projects using Cargo Workspaces

This problem occurs in a project where we have put the project's Rust types into their own crate, so that these types can be shared and used both from e.g. backend and frontend crates.

Minimal repro: https://github.com/FruitieX/ts-rs-repro

Here we have two crates app and types. types contains a SharedType struct that's exported via ts-rs. app uses this type as part of it's internal AppState type, which I also want to export to TS using ts-rs.

The typings can be generated by running cargo test in the root of the repo. I've committed the generated bindings for convenience.

The TS typings get exported into app/bindings/AppState.ts and types/bindings/SharedType.ts respectively. However, app/bindings/AppState.ts tries to import from the relative path ./SharedType, which doesn't work since the actual working relative path would be ../../types/bindings/SharedType.

I'm currently working around this by manually moving the generated bindings into a shared bindings dir in the root of our project repo.

Avoiding the testcase workaround

Hello,

as you're aware, hiding the code generation in testcases is a bit of a hack and probably annoying for anyone actually using their tests for other matters. Like testing.

If you haven't seen it, https://github.com/Wulf/tsync is taking a different approach: Instead of generating a meaningful #[derive(TS)] at build time, it will parse your source code independently of the compiler. But both tsync and ts-rs use the syn crate, and will parse a syn::Item::Struct/::Enum into type information.

Their approach has a few advantages:

  • doesn't mess with test cases
  • no build overhead to generate meaningful #[derive(..)] (though that is probably minor)
  • it's easier to regenerate .d.ts files on demand (just run tsync instead of all your tests)

But let's not hide the disadvantages:

  • they currently require global installation of a tsync binary. This could be avoided by letting users add a one-liner [[bin]] or [[example]] to their project and calling that. (an example has the advantage that you can put its deps into dev-dependencies)

I was wondering if it'd be useful to better abstract the type parsing away from the type consumption. We create a function taking a syn::Item and returning a struct DerivedTS (or something more generic than it).

Using that function, we could implement both the actual #[derive(TS)] and testcase generation, but we could also implement an external parser similar to tsync for projects where that's a better fit.

Do you think that'd be useful? Am I overlooking something important? Is this something I should hack on the next slow weekend, or over the holidays?

Implement TS for usize

I'm using usize rigorously throughout my codebase and I get the following compile-time error:

error[E0277]: the trait bound `usize: TS` is not satisfied

Import statements not generated when using struct-like enums

Import statements are working for most of my components, but some reason not for this one:

Screen Shot 2021-11-21 at 3 22 28 AM

use serde::Serialize;
use ts_rs::TS;

/// A single attribute belonging to a particular component.
#[derive(Serialize, TS)]
#[ts(export)]
pub struct Attribute {
    /// The attribute name, e.g. 'position' or 'mass'.
    name: String,
    /// The width in number of f32 values.
    width: usize,
}

/// The descriptor of a game component's memory information.
#[derive(Serialize, TS)]
#[ts(export)]
#[ts(rename_all="lowercase")]
#[serde(tag="type")]
pub enum Component {
    Point {
        attributes: Vec<Attribute>
    },
    Source {
        attributes: Vec<Attribute>
    },
}
// bindings/Attribute.ts
export interface Attribute {
  name: string;
  width: number;
}

// bindings/Component.ts
export type Component = { type: "point"; attributes: Array<Attribute> } | {
  type: "source";
  attributes: Array<Attribute>;
};

Attempts at fixing

Module splitting

Splitting them into separate modules so that they are run as separate tests does not make a difference:

test memory::comps::attr::export_bindings_attribute ... ok
test memory::comps::comp::export_bindings_component ... ok

Adding bare variant

Adding a non-struct-type enum variant does do the trick:

/// The descriptor of a game component's memory information.
#[derive(Serialize, TS)]
#[ts(export)]
#[ts(rename_all="lowercase")]
#[serde(tag="type")]
pub enum Component {
    Foo(Vec<Attribute>),
    Point {
        attributes: Vec<Attribute>
    },
    Source {
        attributes: Vec<Attribute>
    },
}
import type { Attribute } from "./Attribute";

export type Component = { type: "foo" } & Array<Attribute> | {
  type: "point";
  attributes: Array<Attribute>;
} | { type: "source"; attributes: Array<Attribute> };

Skipping bare variant

Skipping this variant does not work:

// ...
    #[ts(skip)]
    Foo(Vec<Attribute>),
export type Component = { type: "point"; attributes: Array<Attribute> } | {
  type: "source";
  attributes: Array<Attribute>;
};

Removing other modifiers

Removing #[ts(rename_all="lowercase")] and #[serde(tag="type")] also makes no difference.

Adding non-vec field

Adding a non-vecetor field (i.e foo: Attribute) does not work.

New-type + inline

Creating a newtype and then inlining that does not do the trick:

#[derive(Serialize, TS)]
pub struct Attributes(Vec<Attributes>);
 
// ...
        #[ts(inline)]
        attributes: Attributes,

Separate struct + inline

Creating a separate struct with the named field does work:

#[derive(Serialize, TS)]
#[ts(export)]
pub struct Attributes {
    attributes: Vec<Attribute>,
}

/// The descriptor of a game component's memory information.
#[derive(Serialize, TS)]
#[ts(export)]
#[ts(rename_all="lowercase")]
#[serde(tag="type")]
pub enum Component {
    #[ts(inline)]
    Point(Attributes),
    Source(Attributes),
}
// bindings/Component.ts
import type { Attributes } from "./Attributes";

export type Component =
  | { type: "point" } & Attributes
  | { type: "source" } & Attributes;

//bindings/Attributes.ts
import type { Attribute } from "./Attribute";

export interface Attributes {
  attributes: Array<Attribute>;
}

And it technically works because the type is equivalentโ€ฆ but it's ugly.

#[derive(TS)] requires all generics in fields to implement TS

Hi,
Currently deriving for types that have fields like DateTime<Utc> which have TS impls that do not require the generic parameter to implement TS is broken because the derive macro generates code that requires Utc to implement TS. For example

use ts_rs::TS;

struct Generic<T> {
    t: T
}

impl<T: 'static> TS for Generic<T> {
    fn name() -> String {
        "string".to_string()
    }

    fn dependencies() -> Vec<(std::any::TypeId, String)> {
        vec![]
    }

    fn transparent() -> bool {
        false
    }
}

struct Struct;

#[derive(TS)]
struct ContainsGenerics {
    g: Generic<Struct>,
}

gives

error[E0277]: the trait bound `Struct: TS` is not satisfied
   --> src/main.rs:23:10
    |
23  | #[derive(TS)]
    |          ^^ the trait `TS` is not implemented for `Struct`
    |
note: required by `name`

As far as I can tell the problem is the special handling done in types::generics::format_type. The derive macro should rely on the TS impl of DateTime without processing the generic parameter.

Alternate representation for Option<T>

Hi, I've just tried out your crate on different definitions and it looks very promising !

There's just a question on how to alternatively handle Option<T> :

given this struct :

#[derive(Serialize, TS)]
struct CreateUser {
    first_name: Option<String>,
    last_name: Option<String>,
}

will currently generate :

export interface CreateUser {
    first_name: string | null,
    last_name: string | null,
}

would it be possible to instead generate :

export interface CreateUser {
    first_name?: string,
    last_name?: string,
}

I started looking at your lib sourcecode, but I might not have time to dig in, especially that I noticed on impl<T: TS> TS for Option that it is currently implemented on the generated type, and I'm not sure how to link it with the generated field.

Any feedback would be greatly appreciated !
Thanks :)

Duplicate imports

I have a large enum, and when this is exported as a .ts interface the imports are duplicated in multiple instances:

import type { TypedValue } from "./TypedValue";
import type { TimeUnit } from "./TimeUnit";
import type { TypedValue } from "./TypedValue";
import type { Floor } from "./Floor";
import type { UnitDivision } from "./UnitDivision";
import type { TransferFee } from "./TransferFee";
import type { AreaUnit } from "./AreaUnit";
import type { TypedValue } from "./TypedValue";
import type { EnergyUnit } from "./EnergyUnit";
import type { FloatRange } from "./FloatRange";
import type { CurrencyUnit } from "./CurrencyUnit";
import type { TypedValue } from "./TypedValue";
import type { UnitDivision } from "./UnitDivision";
import type { AssessedValue } from "./AssessedValue";

Is there any deduplication done on the imports?

Support #[serde(rename_all)] for enum variants

Example:

use ts_rs::TS;
use serde::Serialize;

#[derive(Serialize, TS)]
#[serde(tag = "type")]
pub enum Thing {
   #[serde(rename_all = "camelCase")]
   A {
       display_name: Option<String>,
   },
   B (u8),
}

resulting warning:

warning: failed to parse serde attribute
  | 
  | #[serde(rename_all = "camelCase")]
  | 
  = note: ts-rs failed to parse this attribute. It will be ignored.

so the resulting variant does not have it's field-names renamed in camel casing.

see https://serde.rs/attributes.html

Ability to export to .d.ts files

When dealing with javascript code bases, it is sometimes useful to use typescript definition files even when you are not using typescript. Currently, the way the types are declared, they are exported, meaning you must import them, like such

/** @type {import("../types/generated/ingest.js").TelemetryPacket}  */

where as if they were declared ambiently, they would not need to be imported. This is common practice in typescript declaration files for non-modules. Below are examples of exports vs declarations.

This could be achieved through an attribute to the derive macro.

Exports

image

Declaration

image
(declarations are global, exports need to be imported)

Support for generics

#[derive(TS)]
struct A<T> {
    foo: String,
}

Results in the following error:

wrong number of type arguments: expected 1, found 0
expected 1 type argument

I suspect this error is triggered somewhere in the macro implementation, though I don't see where exactly. What would it take for generics to be supported? If I had a few pointers I might try to see if I could implement it myself.

Combine exports into single file

I think that any exports within the same module should be combined into a single file, rather than splitting them up into separate files. I feel as though this should be the default, but perhaps a directive at the top of the module could indicate whether or not this happens?

Support sequence

#[derive(Serialize, TS)]
struct User {
    user_id: i32,
    first_name: String,
    last_name: String,
    role: Role,
    family: Vec<User>,
    gender: Gender,
    childrens: [User; 3],
}

Attribute for externally tagged enums or match serde by default

Hi,
currently the the TS::decl() generated for a type like

#[derive(serde::Serialize, TS)]
enum Enum {
    A(&'static str),
    B { s: &'static str },
    C
}

looks like this

type Enum = string | {
    s: string,
} | "C";

whereas serde_json generates output matching the type

type Enum = { "A": string } | { "B": { s: string } } | "C"

serde-compat allows for matching other styles of representing enums, like #[serde(tag = "tag", content = "content")], but there's no way to match the default since there's no serde attribute for it. I think matching serde's default output is preferable since it allows for differentiating between A("C") and C, but an attribute would work too.

Properly document all attributes

Currently, the documentation is pretty sparse and only lives in doc comments.
Something similar to the serde docs would be cool to properly document the various attributes.

Support serde_json::Value

I have a few free-form values that I store as serde_json::Value types (they get stored as jsonb in my database).

It would be nice to support serde_json::Value, I assume this would map to any on the typescript side.

Derive from newtype wrapper

It seems to be possible to derive e.g. serde's Serialize trait from a (newtype wrapper)[https://doc.rust-lang.org/book/ch19-04-advanced-types.html] around a struct which itself does not implement this trait.
I tried to do the same with deriving the TS trait from this library. And in this case the compiler seems to complain about a missing trait on the wrapped type.

Is there anything we can do to make this work?

Serde tags + Enum compatability

Serde allows users to specify tags for the content and the tag of an enum.

For example,

#[derive(TS, Deserialize)]
#[serde(tag = "kind", content= "data")]
enum Biz {
    Foo,
    Bar
}

generates: type Biz = "Foo" | "Bar"

When really it should generate:
type Biz = {kind: "Foo", content: null} | {kind: "Bar", content: null}
The latter type is deserializable. The former is not.

export type aliases

this would be great, so if I have type Foo = String in Rust, and I use Foo, it will also be Foo on the TS side

cannot find uuid-impl feature.

ts-rs = {version = "4", features = ["chrono-impl", "uuid-impl"]}

And it says,

depends on `ts-rs`, with features: `uuid-impl` but `ts-rs` does not have these features.

the chorono-impl is working alright by itself.

Incorrect TS types generated from types containing type aliases

Minimal repro:

use std::collections::HashMap;
use ts_rs::TS;

type TypeAlias = HashMap<String, String>;

#[derive(TS)]
#[ts(export)]
enum Enum {
    A(TypeAlias),
    B(HashMap<String, String>),
}

#[derive(TS)]
#[ts(export)]
struct Struct {
    a: TypeAlias,
    b: HashMap<String, String>
}

fn main() {}

Generates:

export type Enum = { A: Record } | { B: Record<string, string> };
export interface Struct { a: Record, b: Record<string, string>, }

Expected both generated variants/fields to be identical.

Export `enum` instead of `type` for simple C-like enums

When Rust's enums could be represented with TypeScript's enums I think they should. So for example an enum like:

#[derive(serde::Serialize, ts_rs::TS)
enum Color {
	#[serde(rename="R")
	Red,
	Blue,
	Green
}

should end up as

export enum Color {
	Red="R",
	Blue,
	Green
}

Maybe even const enum? Should probably be optional with an attribute on the enum.

Instead of currently it being: export type Color = "R" | "Blue" | "Green";

Enum with Data compatability

Currently it is not possible to generate Typescript bindings for enums that contain data.

For example:

#[derive(TS)]
enum Foo {
    Bar(String), 
    Other    
}

Produces an error: "variant has data attached. Such enums are not yet supported."
In this case, we would expect typescript bindings like:

type Foo = string | "Other"

Parse error stemming from default type param

I'm currently trying to apply the TS derive to the following:

#[derive(Clone, PartialEq, Eq, Encode)]
- #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug))]
+ #[cfg_attr(feature = "std", derive(Decode, Serialize, Debug, TS))]
#[cfg_attr(
	feature = "std",
	serde(bound(serialize = "T::Type: Serialize, T::String: Serialize"))
)]
pub struct StorageEntryMetadata<T: Form = MetaForm> {
	pub name: T::String,
	pub modifier: StorageEntryModifier,
	pub ty: StorageEntryType<T>,
	pub default: Vec<u8>,
	pub docs: Vec<T::String>,
}

The resulting error points to the = token:

expected one of `(`, `+`, `,`, `::`, `<`, or `>`, found `=`

Any advice on getting this working would be greatly appreciated. Thank you!

[Feature request] Generate strict typescript type with primitive newtype.

Hello, at first place I would like to thank you for your work.
I would like to generate a strict typescript type from a primitive newtype.

Current behavior

#[derive(TS)]
pub struct FooId(usize);

#[derive(TS)]
pub struct BarId(usize);

The above rust code generates following typescript definition.

export type FooId = number;
export type BarId = number;

So, we can write following code without error.

const fooId: FooId = 0;
let barId: BarId = 1;

barId = fooId; // <- Ok

Feature Request

I would like to generate following definitions.

type Phantom<T, U extends string> = T & { [key in U]: never };
export type FooId = Phantom<number, 'FooId'>;
export type BarId = Phantom<number, 'BarId'>;

With such a type, we can make the following assignments an error.
This is very useful if you want to strictly distinguish between ids.

const fooId: FooId = 0;
let barId: BarId = 1;

barId = fooId; // <- error

What do you think about it?

Improve support for enum variants

I noticed a few issues with enum variants. For instance:

#[derive(Serialize, TS)]
#[serde(tag = "kind", content = "data")]
enum ComplexEnum {
    A,
    B { foo: String, bar: f64 },
    W(SimpleEnum),
    F { nested: SimpleEnum },
    T(i32, SimpleEnum),
    V(Vec<Series>),
}

generates the following type:

// issue 1: there is no import for the `SimpleEnum` type

export type ComplexEnum =
  | { kind: "A"; data: null } // issue 2: IMO it would be better to omit the `data` property
  | {
    kind: "B";
    data: {
      foo: string;
      bar: number;
    };
  }
  | { kind: "W"; data: SimpleEnum }
  | {
    kind: "F";
    data: {
      nested: SimpleEnum;
    };
  }
  | { kind: "T"; data: [number, SimpleEnum] }
  | { kind: "V"; data: Array }; // issue 3: there is no type argument passed to `Array`

I have fixed this issues in my own fork with the following commit: arendjr@e7a87b1

Unfortunately, it would be a bit unwieldy to create a PR for this as this is built on top of both #15 and #18. This is just to let you know these issues are addressed and I can create a PR for it when the other PRs are merged.

Parsing raw struct properties result in panic

Hello,

I noticed that a struct with raw properties (e.g. r#type) like these:

#[derive(TS)]
struct Test {
    r#type: String,
}

results in:

thread '...::export_typescript' panicked at 'could not format output: "Line 2, column 8: Expected {, got interface\n\n  export interface Test {\n         ~~~~~~~~~"', ...\mod.rs:38:1
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Allow any fallback type

Sometimes it might not be possible or desirable to generate full typings, eg when using third party definitions.

It would be great to have a #[ts(any)] attribute that will just generate defintions with any.

Should be available on struct fields and and variants.

Generate `import type ..` where possible

The automatic imports should be import type { Foo } from ..., otherwise strict typescript settings will cause the following error: import is never used as a value.

Serde custom crate support

Hey! I've encountered the issue, that due to ts-rs does not support the serde crate feature, the program fails to compile.

Here is an example:

#[derive(BorshDeserialize, BorshSerialize, Serialize, Deserialize, TS)]
#[serde(crate = "near_sdk::serde")]
#[ts(export)]
pub struct SomeStruct {
    pub someProperty: Option<Base64VecU8>,
}

Error:

warning: failed to parse serde attribute
  | 
  | 
  | #[serde(crate = "near_sdk::serde")]
  | #[serde(crate = "near_sdk::serde")]
  | 
  = note: ts-rs failed to parse this attribute. It will be ignored.

error[E0277]: the trait bound `near_sdk::json_types::Base64VecU8: ts_rs::TS` is not satisfied

Thanks!

Raw property names with camelCase rename result in misgenerated typescript property names

Thanks for this package, I'm finding it very useful for sharing a protocol between Rust and ts. I hate to create an issue instead of a PR, but I can't spare the time to make a PR right now. So here goes:

Cargo.toml:

[package]
name = "blah"
version = "0.1.0"
edition = "2018" 

[dependencies]
ts-rs = "3.0.0"

src/main.rs:

use ts_rs::{TS, export};

#[derive(TS)]
#[ts(rename_all = "camelCase")]
struct User {
    r#type: i32,
}

export! {
    User => "bindings.ts"
}

Result bindings.ts:

export interface User {
  rType: number;
}

Specifically, rType in the output. I note that the bindings aren't generated at all without rename_all = "camelCase". The workaround I'm currently using is to use #[ts(rename = "type")] on the relevant field.

How to handle naming conflicts

Currently, having multiple types with the same name is problematic.
Firstly, with just #[ts(export)], they will just overwrite eachother. This can be worked around with #[ts(export_to = "..")].
Then, when a third type depends on two types with the same name, the generated imports for the third type will be invalid. This can be worked around with #[ts(rename = "..")].

How can we improve on this? Resolving these conflicts would require coordination between different invocations of derive(TS).
I don't like to reintroduce something like export! to which you pass each type you wish to export, since this gets really painfull when working with a deep module tree, requiring you to make everything public.

Generics dropped for newtype structs in 4.x

Hi,
I noticed that the struct

#[derive(ts_rs::TS)]
struct Wrapper(Vec<String>);

results in

export type Wrapper = Array;

in 4.x. In 3.x the result was

export type Wrapper = string[];

I think the issue is the same as in #32 (comment), which is to say there's no method to call that will return Array<string> that we could use at

None => quote!(<#inner_ty as ts_rs::TS>::name()),
. It would be possible to patch it up by handling the generics for newtypes specifically, but I think that'd break again if you tried struct Wrapper(Vec<Vec<String>>).

Feature serde-compat not found

Hi !
I followed-up the recent updates on ts-rs and was excited to give a try again (especially since the support for optional ?-annotated fields, e.g.my_field?: string, thanks @arendjr !).


I updated ts-rs like :

ts-rs = { version = "3.0", features = ["serde-compat"] }

But then I got the following issue :

the package `***` depends on `ts-rs`, with features: `serde-compat` but `ts-rs` does not have these features.

I checked on docs.rs/ts-rs in the feature flags section, couldn't find any mention of it and thought like ok no worries it's probably just pulled by ts-rs-macros internally.


So I gave a try like this :

use chrono::{DateTime, Utc};
use diesel::{Identifiable, Queryable};
use serde::Deserialize;
use ts_rs::{TS};

use crate::schema::database_table;

#[derive(TS)]
#[derive(Debug, Deserialize, Identifiable, Queryable)]
#[table_name = "database_table"]
pub struct MyStruct {
    pub id: i32,
    pub name: String,
    #[ts(type = "string")] // we deserialize to RFC-3339 string representation
    pub created_at: DateTime<Utc>,
    #[ts(type = "string")]
    #[serde(skip_serializing_if="Option::is_none")]
    pub updated_at: Option<DateTime<Utc>>,
}

omitting the export! { ... } because I do it at the root of the module

Which generated this result :

export interface MyStruct {
  id: number;
  name: string;
  created_at: string;
  updated_at: string; // please note here I was expecting updated_at?: string
}

As a side note I also found mention of a chrono-impl feature flag, but here again, the compiler told me that it couldn't be found.


Well, mistake might be on me, some help would be much appreciated :)

Add support for externally tagged unions

Externally tagged unions it the default for serde enums in e.g. JSON.

An enum like this:

pub enum Field {
    Floor,
    Wall,
    Portal { id: usize, target: MapAddress },
    Exit,
    Special { id: usize },
}

would convert to this:

export type Field =
  | "Floor"
  | "Wall"
  | {
      Portal: {
        id: number;
        target: MapAddress;
      };
    }
  | "Exit"
  | {
      Special: {
        id: number;
      };
    };

It looks kinda ugly but it's very useful to me and it's the serde default.

[Feature] export to single file?

Is it possible to add for nested structs like

struct Player {
    role: Role
}

the feature to export to one file like

export! {
    [Role, Player] => "player.ts",
}

Then it's a single file and ready to use after generation without needing to manually add import statements.

Great project btw!

What's the best practice for handling types spanning multiple files?

So let's say I have types with interdependencies spanning multiple files:

/foo.rs

#[derive(TS)]
struct Foo {}

/bar.rs

#[derive(TS)]
enum Bar {
    Foo(Foo)
}

How can I generate ts bindings such that Foo is in scope for Bar?

It looks like I can't export them to the same file, since the export! macro only works with types declared in the same file.

Run outside of test context

I could not find a way to run the binding generation outside of a test context.

Personally I don't think running it as test is a good idea. I'd rather provide a CLI flag that runs the binding generation.

Anyways, I think it would make sense if this question is up to the user.

Or do I oversee something here?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.