Description
🔎 Search Terms
generic type does not get inferred, generic type is not restricted
🕗 Version & Regression Information
- This is the behavior in every version I tried (5.5 beta, 5.x, 4.x, 3.x), and I reviewed the FAQ for entries about generic type inference
⏯ Playground Link
💻 Code
Let's say you have an enum, and you create a map of those enums to another type. You want a function such that when you pass a specific enum, you must also pass the data associated with that enum.
I know this example is possible to achieve with discriminated unions, but the real-world code makes it a lot harder to use those. This example just demonstrates the problem in a small way:
enum SomeThings {
One = 'one',
Two = 'two',
}
interface ArgMap {
[SomeThings.One]: {x: number},
[SomeThings.Two]: {y: string}
}
interface ArgType< T extends SomeThings > {
thing: T;
data: ArgMap[T];
}
// It is not possible to call this with values that will actually cause an error.
function doSomethingWithData<T extends SomeThings>({thing, data}: ArgType<T>) {
if (thing === SomeThings.One) {
// Error: TS infers "data" as the union "{x: number} | {y: string}"
// when it should be restricted to "ArgMap[T]", so "data.x" is not accessible
console.log(data.x);
}
}
🙁 Actual behavior
Typescript reports an error, because it thinks that data.x
is a union of the possible data types. However, it should always be theoretically possible to restrict the type of data
based on the enum associated with it. You can even use ArgType
as expected by itself:
type TestData = ArgType<SomeThings.One>['data']; // correctly restricts to "{x: number}"
🙂 Expected behavior
As far as I can tell, the types are correct, because it is impossible to pass an ArgType<T>
such that data does not match ArgMap[T]
. So it should be possible to restrict the type here
Additional information about the issue
No response