-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#[derive(TS)]
and associated types
#261
Comments
Alternatively, |
Hey! Besides the technical reasons we currently don't support this, it's also unclear to me what we should generate for types containing associated types of a trait. The only thing we could do is let you export a concrete instance of In this example, it's the implementation of |
If, at some point, we get const-generic trait MyTrait {
type U: TS;
}
#[derive(TS)]
struct MyStruct<T: MyTrait> {
u: T::U,
}
impl<const NAME: &'static str> MyTrait for ts_rs::Dummy<NAME> {
type U = i32;
} Then, type MyStruct<T> { u: number }; no matter what |
@NyxCode That makes sense, thank you! What do you think about an attribute to ignore a generic parameter? #[derive(TS)]
struct MyStruct<#[ts(skip)] T: MyTrait> {
#[ts(as = "i32")]
u: T::U,
} For context, my use case is a compiler whose data structures are generic over a trait Driver {
type Info;
...
}
struct Expression<D: Driver> {
info: D::Info,
kind: ExpressionKind<D>,
}
enum ExpressionKind<D: Driver> {
String(String),
Number(i32),
Call(Box<Expression<D>>, Vec<Expression<D>>),
...
} But my TypeScript interface to this compiler always uses the same driver, so Let me know what you think! |
I played with the idea of introducing trait Driver {
type Info: TS; // (1)
}
struct TsDriver;
impl Driver for TsDriver {
type Info = String;
}
#[derive(TS)]
struct Expression<#[ts(concrete = "TsDriver")] D: Driver> {
info: D::Info,
} (1): Ideally, this trait bound wouldn't be necessary, but it currently is. I've put together a proof-of-concept here. There are a lot of edge-cases this just glosses over, but it's a start. |
This comment was marked as outdated.
This comment was marked as outdated.
@NyxCode Whoops – I forgot to add the use ts_rs::TS;
trait Driver {
type Info;
}
#[derive(TS)]
struct TsInfo;
impl Driver for ts_rs::Dummy {
type Info = TsInfo;
}
#[derive(TS)]
struct Expression<#[ts(concrete = "ts_rs::Dummy")] D: Driver> {
#[ts(as = "TsInfo")]
info: D::Info,
} |
@NyxCode The only issue I'm getting now is when I add in serde — the use serde::{Deserialize, Serialize};
use ts_rs::TS;
trait Driver {
type Info: TS;
}
#[derive(TS)]
struct TsInfo;
impl Driver for ts_rs::Dummy {
type Info = TsInfo;
}
#[derive(Debug, TS, Serialize, Deserialize)]
#[ts(export)]
struct Expression<#[ts(concrete = "ts_rs::Dummy")] D: Driver> {
info: D::Info,
}
Putting |
Awesome! You could get rid of the I also just pushed an other commit, and now
Oh, that's very interesting! No clue what's going on here, will have to look into that. |
Hm. Seems like serde is copying the Unless there's some way to prevent that, we'll have to change the syntax, maybe to #[derive(TS)]
#[ts(concrete(B = TsDriver)]
struct Expression<A, B: Driver> { } |
@NyxCode Looks like changing the attribute to be on the struct instead of the generic parameters is the way to go — see dtolnay/syn#422. |
FYI @WilsonGramer: in #264, we got rid of the trait Driver {
type Info: TS;
} by generating smarter bounds on the |
In the following code,
#[derive(TS)]
generates aT: TS
bound even thoughT
is never used, only its associated types:I would expect the above example to compile because
i32
implementsTS
.It looks like the derive macro generates the following:
In general, instead of adding bounds for each type parameter,
#[derive(TS)]
could add bounds for each field:The text was updated successfully, but these errors were encountered: