-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
Wrapping type with Readonly causes type alias to be lost in annotation #34777
Comments
IIRC type aliases are not directly preserved in the way you think, TS just remembers if the first instantiation of a type was due to a type alias and back-maps it to the alias if so. Since this is just a heuristic, there are a lot of ways it can go wrong. For further elaboration see #32287 (comment) In short: type aliases are not first-class types. They are more like macros where the compiler expands the alias and uses the expansion directly, which often loses information on where the type originated. |
Thanks for your comment @fatcerberus - I understand what you're saying. What confuses is me is that the type ReadOnlyPerson = Readonly<{
name: string;
}>
type ReadOnlyInLinePerson = {
readonly name: string;
}
let y: ReadOnlyPerson
// hovering on z gives the expected type annotation -> z: ReadOnlyInLinePerson
let z: ReadOnlyInLinePerson Edit: I guess the workaround would be to not use the |
It confused me at first, too, but here's what I think happens:
I do wonder why it doesn't display as type ReadOnlyPerson = Readonly<Person> Now |
Interesting, that makes sense. It would be a bit cumbersome to define the type and the read-only version separately each time in order to improve the intellisense. Let's see what the official TS maintainers have to say about this but I suspect this is not something that can be easily remedied. |
This is confusing and non-intuitive to me. I think at the very least this should be documented, but if the contract can be improved, or if some control can be afforded via other keywords, that would be a huge help. |
I'm not sure that @fatcerberus isn't right. This seems like something that "should" work |
@RyanCavanaugh I found that if you redeclare type ReadOnlyPerson = { readonly name: string } then that fixes the issue and Repro (Playground): type A<T> = Array<T>;
type B<T> = A<T>;
type C<T> = B<T>;
type D<T> = C<T>;
declare let x: D<any>; // x :: A<any> |
Could be a possible workaround, type Person = {
name: string;
}
type ReadOnlyPerson = Readonly<{
name: string;
}>
// hovering on x shows a type annotation of `Person`
let x: Person
// hovering on y shows a type annotation of Readonly<{ name: string }>
let y: ReadOnlyPerson
interface DoNotExpand extends Readonly<{
name: string;
}> {
}
//let z: DoNotExpand
let z: DoNotExpand; I've only ever wanted to force TS to expand types. I've never wanted to force TS to alias types. (Now I have h4xx to force TS to expand and not-expand types, yay) |
The compiler's behaves as intended here. Instantiations of generic type aliases (such as |
TypeScript Version: 3.7.x-dev.201xxxxx
Search Terms:
Readonly, type, annotation, alias, expand
Code
Expected behavior:
Type aliases should be preserved in annotations when using the
Readonly
type. In the example above I would expect the type annotation fory
to beReadOnlyPerson
Actual behavior:
Type alias is lost in the annotation when using the
Readonly
type. The type annotation fory
in the example above isReadonly<{ name: string }
instead ofReadOnlyPerson
Playground Link:
http://www.typescriptlang.org/play/?ts=3.7-Beta&ssl=10&ssc=22&pln=1&pc=1#code/C4TwDgpgBAChBOBnA9gOygXigbwFBQKlQEMBbCALikWHgEtUBzAblwF9ddRIoAlCYgBMA8qgA2IOEjSY+AwWgkAePISJlK1WgxbsAfJzERgUAB5UpKVLiMmQVfkNETLaIA
Related Issues:
I wasn't able to find any bugs that looked similar, when through a couple of pages of issues using the search terms mentioned above.
The text was updated successfully, but these errors were encountered: