Optional Generic Type Inference
See original GitHub issue#13487 added default generic types, but it’s still not possible to infer a generic type:
type Return<T extends () => S, S = any> = S
Here S
takes its default type any
, but T
could permit inference of a subset type of any
for S
:
const Hello = () => 'World'
type HelloReturn = Return<typeof Hello> // any
Here HelloReturn
still has any
type, and TypeScript could infer S
as the literal type 'World'
, which is a subset of any
.
Use Case
Here’s an example of a fully declarative workaround for #6606, using generic type inference:
type Return<T extends () => S, S = any> = S
const Hello = () => 'World'
type HelloReturn = Return<typeof Hello> // 'World'
Default Type
If return of T
is not a subset of S
, it should throw an error:
type ReturnString<T extends () => S, S = string> = S
const Hello = () => 'World'
type HelloReturn = ReturnString<typeof Hello> // 'World'
const calculateMeaningOfLife = () => 42
type MeaningOfLife = ReturnString<typeof calculateMeaningOfLife> // ERROR: T should return a subset of String
Multiple Possible Type Inferences
The current implementation always returns the superset (which is just the default generic type), solving this issue would require to return the subset (the most precise type of all the inferred possibilities).
If a type has multiple possible type inferences, TypeScript should check that all these types are not disjoint, and that they all are subsets of the Default Generic Type.
The inferred type is the most precise subset.
Issue Analytics
- State:
- Created 7 years ago
- Reactions:190
- Comments:46 (23 by maintainers)
Top GitHub Comments
Yeah, yeah, but John, your language designers were so preoccupied with whether or not they could that they stopped to wonder whether or not they should.
Typescript is beginning to delve into the territory of too complicated. This is a hard shove off a cliff, in my opinion. Generic syntax is relatively well understood. Generic constraints are relatively well understood. Generic constraints in the form of a pair of lambda expressions would confuse almost everyone who’s seen a generic in another language before.
JavaScript’s a dynamically typed language, and therefore it requires levels of expression in typing that statically typed languages don’t. Nobody is forcing you to use these advanced ways of typing, better yet, you could even create a linter rule that forbids their usage.
On the other hand, this feature would enable proper and stricter typings for so many real-world use-cases that it would be very welcome, even if used only for typing external libraries @DefinitelyTyped. Moreover, I’ve mentioned two related, complex cases, in which this proposal trumps the necessity for additional complexity, i.e. it proposes to make the language simpler, rather than more complex.