You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Resolve a default against the parameter list it is written in
A default is read where the parameters are, so its names resolve against
the parameter list before the declarations around it. The first cut
rendered a default as a type and stopped there, which left three ways for
one to reach something other than the Rust it came from. All three are the
same missing step, so `resolve_defaults` now makes it once, next to the
`TsTypeParam` it settles, for the derive and `#[declare]` alike.
**A type whose TypeScript name a parameter has taken.** The check only
judged refs whose source is `TypeParam`, so a concrete type went through
unexamined:
struct Later<U = crate::T, T = String> // export interface Later<U = T, T = string>
struct Earlier<T, U = crate::T> // export interface Earlier<T, U = T>
`crate::T` loses its qualification when it renders. `Later` is a `TS2744` --
a default may only name a parameter declared before it -- and `Earlier` is
worse, because it compiles and `T` now means the parameter. Neither can be
spelled around inside a parameter list, where a parameter shadows, so the
default goes and the trailing-run rule takes the defaults before it.
**A default inside a namespace.** The alias collection and `prefix_type_refs`
walked `type_ann` and nothing else, so a default was left to resolve against
the namespace it is printed in:
enum Outcome<T = crate::Error> { Done(T), Error(String) }
`Outcome.Done`'s `T` meant the sibling variant rather than the interface --
nothing in the declaration is a syntax error, so it surfaced only where the
two met. A default is collected and rewritten like any other reference now,
and reaches the same `__OutcomeError` alias.
**A renamed declaration named in a default** is not fixed here, and is not
particular to defaults: a field of the same type emits the same dangling
`Original`, which is #103. Both are pinned side by side so the day #103
lands, they move together. `#[tsify(type_params = "T = Renamed")]` says it
in the meantime.
The e2e crate follows #111's shape -- one source built under both features,
since a default renders like any other type and `Option` and `HashMap`
inside one move with the feature. It also records what a default does to
#76: the signature still loses its argument, and `Wrapper` now resolves
through the default rather than failing, so that line should change when #76
is fixed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,8 @@
2
2
3
3
## Unreleased
4
4
5
-
-**A default type parameter is now declared with its default.**`struct Foo<T = bool>(T)` declared `export type Foo<T> = T;` and now declares `export type Foo<T = boolean> = T;`, the same for interfaces, enums and `#[declare]` aliases. **Your `.d.ts` changes if you use one.** A default that cannot be honoured is dropped: one naming a parameter no field mentions, and then every default before it, since TypeScript only allows them on a trailing run
5
+
-**A default type parameter is now declared with its default.**`struct Foo<T = bool>(T)` declared `export type Foo<T> = T;` and now declares `export type Foo<T = boolean> = T;`, the same for interfaces, enums and `#[declare]` aliases. **Your `.d.ts` changes if you use one.**
6
+
- A default is read where the parameters are, so a name in it resolves against the parameter list before the declarations around it. One that would land somewhere other than the Rust says is dropped — naming a parameter that is declared nowhere or declared after it, or a type whose name a parameter has taken — and so is every default before it, since TypeScript only allows them on a trailing run. Inside `#[tsify(namespace)]`, a default is rewritten to the hoisted alias like any other reference, so a sibling variant cannot capture it
6
7
- While [#76](https://github.com/madonoharu/tsify/issues/76) is open this makes it quieter — `fn bar(foo: Ts<Foo<i64>>)` still writes `bar(foo: Foo)`, which the default now resolves to `Foo<boolean>` rather than raising `TS2314`
0 commit comments