-
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
Improve type readability (fix type alias propagation, allow aliasing inferred types) #45954
Comments
This could be super helpful for some crazy generic code in some of the libraries. I imagine if we could use template literals as the "dynamic" type name this could be even more useful. |
This would be great. I have a generic type that turns classes to plain interfaces (useful to work with the library class-transformer). a type that could be |
This would be incredibly helpful. Typescript is great to onboard newcomers to projects, but complex type expansions unfortunately end up scaring many junior programmers, even when the types themselves would be easily readable with a system like this. |
The thing is that the Typescript compiler has been architected to describe types in full semantic accuracy, rather than communicate types to developers with full clarity. If we had a way to to provide names to inferred types, then we could communicate a developer's intent far more clearly. In languages like C#, types come first for better or worse, so types become a defacto channel for developers to convey their intent. Developers spend proportionally more time thinking about type names and documenting them. Such a shift would only benefit the Typescript ecosystem. |
I often have the opposite problem and would prefer to read I agree that the problem identified in the OP is real but I wanted to point out that it's one end of a spectrum, and I would rather have a language server option like I also want to add that this piece of syntax would be devoid of semantic value, which on top of being a little weird in a type system would add bloat to TS which is already extremely verbose when types get complex. My final observation would be that TS is not a semantic tool: it's a programming language to hack types on top of unruly Javascript. I understand that one would prefer it to be differently, but that way of thinking caused me the greatest pain when I picked up the language. TS is not Haskell or whatnot, it looks imperative because it is. |
Obviously it's not something that fits all scenarios... it'd primarily be a syntax that API developers could opt-in to in order to make their APIs clearer at their discretion. But it could also be easily utilised by the consumer of the API to tidy up returned types. You're right though, I think typescript is in over its head already. We have to be careful that new features actually improve the development experience. |
Would it be possible to develop this as an extension to Intellisense(?) or at least VSCode so that it's possible to toggle between the two views? I don't know whether anything would be required from Typescript itself for that. |
I don't think the syntax changes are needed, but the better alias inference would be great. Here's a minimal example (notably, this has no usage of libraries like io-ts):
This shows two aliases that resolve to the same type, but only one of them is compatible with the alias name preservation work done in #42149 and #42284 . I believe the issue is specific to type aliases that infer a non-primitive type (hence my use of Outside the language level, it would be great if at the language server level types (aliases and otherwise) could be viewed as an expandable tree. That would hopefully be a happy medium for both the use cases suggeted by @martaver and @geoffreytools . |
Suggestion
π Search Terms
preserve type aliases,inferred types,type names,readability,type expansion
β Viability Checklist
My suggestion meets these guidelines:
β Suggestion
One thing that makes working with Typescript's type system occasionally hopeless is when cumulative inferred types are displayed in type expansion and 'pollute' the information in quick info or errors.
So the proposal is two fold:
π Motivating Example
With any kind of sophisticated typing, we quickly end up with error messages and parameter info that takes multiple seconds to load, and shows a truncated mess of type syntax. Worse, the expansion of these inferred types accumulates and adversely affects any code that touches them.
Typescript fails us in two distinct areas with regard to type expansion, and the culprit seems to be inferred types...
1. Typescript doesn't always respect type aliases, even when they are explicitly provided
E.g. First, what works:
So far, so good. The rule seems to be that if we explicitly alias a type, Typescript will use that name and terminate expansion.
But this rule gets broken when there is logic to the type alias.
You could argue that this is handy, but the consequences of this deviation from the rule means that all other types referencing this one will repeat the full expansion.
2. There is no way to name an inferred type
There is also a scenario where fully expanded inferred types are unavoidable. More specifically, where there is no way to explicitly specify a type alias whose name should be displayed. E.g.
That's already pretty out of hand. All we would need to know, ideally, is something like (pseudocode)
t.TypeC<{mother: Person, father: Person, child: Person}>
.But since the type of
Person
is inferred from the function's return type, we don't get a chance to create a type alias for it. In fact, that's the reason we're able to declare a type alias of the same name for the underlying data type.So wherever we use the Person instance, we're now stuck with a fully expanded inferred type. If we were able to provide Typescript with an alias for the inferred type, we could escape expansion and clean up type expansions everywhere.
Proposed
as type
syntaxSuch syntax could work like this:
So that Family would then display:
t.TypeC<{mother: PersonType, father: PersonType, child: PersonType}>
Since the above kind of factory that returns an inferred type is a common pattern, it could also be shorthanded like this:
...so that the name of the variable would double as the name of the type alias.
There could even be syntax that is used upstream by the function returning the inferred type...
The MyMap alias expanded is Mapped<{ age: number, name: string }>
π» Use Cases
I think I've covered quite specific use cases in my motivating example.
Leveraging type inference to construct sophisticated types is common enough now that we should pay particular attention to developer experience for type systems.
These two changes would especially allow both developers and library authors to have better control over the types their code emits to intellisense and allow them to craft an improved developer experience.
Specifically, we could use libraries like
io-ts
andzod
without polluting our type intellisense.The text was updated successfully, but these errors were encountered: