Description
#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.