-
Notifications
You must be signed in to change notification settings - Fork 115
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
Fix flatten generic by changing TS::name
#235
Conversation
match <#generic_ident>::name().as_str() { | ||
"null" => #generic_ident_str.to_owned(), | ||
|
||
// If name is not "null", a type has been provided, so we use its | ||
// name instead | ||
x => x.to_owned() | ||
x => { | ||
x.to_owned() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to re-add comments later
ts-rs/src/lib.rs
Outdated
@@ -298,7 +298,7 @@ pub trait TS { | |||
|
|||
/// Name of this type in TypeScript, with type arguments. | |||
fn name_with_type_args(args: Vec<String>) -> String { | |||
format!("{}<{}>", Self::name(), args.join(", ")) | |||
format!("{}<{}>", Self::name().split_once('<').unwrap().0, args.join(", ")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hacky approach. Need to find a better way
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have changed this to use a match
so it won't panic!
ts_name: match T::name() { | ||
x if !x.contains('<') => x, | ||
x => x.split('<').next().unwrap().to_owned() | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dependency seems to need the name without any generics, so the same hacky approach was used here
@@ -256,7 +256,7 @@ fn default() { | |||
// #[ts(inline)] | |||
// xi2: X<i32> | |||
} | |||
assert_eq!(Y::decl(), "type Y = { a1: A, a2: A<number>, }") | |||
assert_eq!(Y::decl(), "type Y = { a1: A<string>, a2: A<number>, }") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Side effect: The generic is always emitted, even when using its default
TS::name
Hey! Thanks for being on the ball on this issue, really appreciate it! However, I went quite a bit further, and re-did the generics handeling in ts-rs completely. Here's how that went:
The biggest change here is how generic types are being exported. Right now, we're expecting users to export with all generic parameters equal to Instead, generic types are not handeled specially now. However, before they get exported, I switch out which generic parameters are actually used, and use "dummy" types there instead: #[derive(TS)]
struct MyGenericType<A, B>{ .. }
// .. turns into this impl ..
impl<A: TS, B: TS> TS for MyGenericType<A, B> {
// everything the same, except
// - name() returns the full name, so `format!("MyGenericType<{}, {}>`, A::name(), B::name())`
// - name_with_type_args() is gone 🥳
// - decl() changed like this:
fn decl() -> String {
struct A;
impl TS for A {
fn name() -> String { "A".to_owned() }
fn transparent() -> bool { false }
}
struct A;
impl TS for A {
fn name() -> String { "A".to_owned() }
fn transparent() -> bool { false }
}
MyGenericType::<A, B>::old_decl()
}
} So tl;dr: I create "dummy" types "A" and "B" to represent the generics. They are then handeled like every other type. The only failing test right now is related to default parameters. If a struct contains a field (This happens since Also, all dependencies are kinda fucked right now, but I think that'll be straight-forward to fix (That was done in the The only potential problem I see is that these "dummy" types for the generics need to fullfill all trait bounds of the struct. For that, I generate them with What do you think of this? Any problems you see with that approach, which might not be covered by the test suite? |
That's awesome! I tried messing around with removing
Nice! I remember in a previous PR you mentioned not liking this function very much,
I see. Never even thought of doing that but isolating the dummy types to
Yup! I got that test failing for the same reason. I don't think it's a problem either
That's somewhat anoying, but as you mentioned in the #217 thread, shouldn't be that big a deal
Overall I think this will be a great change. Generics are currently very confusing and anything done to reduce their complexity will make maintanence much easier. As for problems not covered by the test suite, I think the only one we have is the dependencies, more specifically we currently have 2 issues about wrong |
Btw, I'm sorry for absolutely blasting you with notifications 😅, I know you con't have much time to spare this month |
No problem, I just don't want you to think I'm uninterested in what's going on 😆
I feel like these will be easy to fix once the inlining is more predictable (not recursive) again. |
I think fixing |
Closing in favor of #233 |
An attempt at fixing the problems caused by #215 by changing the name method to return the name of the generics
The reason I chose to do this is that there is no reasonable way to call
name_with_type_args
from the place where the problem showed up, so eitherinline
orname
would have to be used instead.inline
was being used, and causing problemsname
, as showed by my attempt to fix it in #215, wouldn't brring T's genericsOut of sheer luck, this fixes #70
@NyxCode despite being a small change regarding how much code changed, this is a reasonably big change in how the library works, so I'd really like your feedback on this one