-
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
Enum generic does not restrict union of possible objects where enum is defined #58634
Comments
Because within the function the compiler doesn't know which type is passed along. It could be |
The compiler should be able to know that // We know which one was passed now:
if (thing === SomeThings.One) {
console.log(data.x);
}
// Correctly shows an error, so it does narrow the type of `data` based on the enum here:
doSomethingWithData({thing: SomeThings.One, data: {y: 'xyz'}); I think it evaluates |
You misunderstand how generics work. Just because This is a perfectly valid and legal call: |
#27808, @noahtallen just use the distributive behavior to make it work function doSomethingWithData<T extends SomeThings>({thing, data}: T extends unknown ? ArgType<T> : never) {
if (thing === SomeThings.One) {
console.log(data.x); // OK
}
} Note that you also have to make the literal object |
That's great, thanks for sharing! looks like const foo: ArgType<SomeThings.One> = {thing: SomeThings.One, data: {x: 1}};
if (someCondition) {
foo.data.x = 100;
}
// works!
doSomethingWithData(foo);
doSomethingWithData({ thing: SomeThings.Two, data: {y: 'hi'}}); Anyways, I'm curious how this works. Why |
Because And for "distributive" behavior, see https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types. |
Hm interesting. It's odd to me that something like Either way, happy that there's a solution! |
Yes. Conditional types distribute over type parameters, so: type ArrayOf<T> = T extends T ? T[] : never;
type Test = ArrayOf<string | number>; // string[] | number[]; whereas without distribution you’d get |
🔎 Search Terms
generic type does not get inferred, generic type is not restricted
🕗 Version & Regression Information
⏯ Playground Link
https://www.typescriptlang.org/play/?ts=5.4.5#code/KYOwrgtgBAyg9hYAVAFgSxAcwM5QN4BQUUA8iMFALxQDkc5NANEVEgO5xW0AuHTBAXwIEM3YACcAZgEMAxhQCC4zAFlpAB3wsA2vESoMOAHRlgAXQBc+AB5XwEAEYSBzYroTJ0WbEfZxL+ACeVtjc4oZCQiIgYlJyispIgerAADysUMDWYiAAJrh6noa4AHxaAJDcXphWSADcBOW50tzSVkqqGtpIZg1RAPT9UADCcOLiwLLcUNLKUNzJFGi4GJISE7lQAG5o0lAOcFVQHWqa0nnHiYsWBAsprMChHQBiY6ZcJ12FBt4m5L23RYPJ5Xe7UDpJFKpb7VHymEraGjNVo0AEEQasRa4WYUCahcJTYCbFASYB1KBobg0XDYYDACCGAA2gQpEHUcGw2DQDkZFG4nHU0k5M220kZYD5KBaUFycEeIBo0wgLVkKEumEhaRhxT+wBKRgIsnooSgkjgnGoeCqhis2t+pkYMpabRsVgAjAIBA1ZYVrVgAOqUlAAEWdAAozXAAJQNAiSMAgKZoegyuC+6qBqqh1qpJCZbKgfKwDw-HAlMNW6qO5HSATtUFpJAlKNaYhoSRQMN+zBUSjUO3GUwtwjEYhGkDYOC8oyMuCYMM1ozWGNQDEwFBwMCMzZOKB4sJoQmbfnq07ufSw3VmR0OMDTZYK7hGYszdSCiYxZkU6YASRgUHZTluV5eYBSFbEQCgOAHAAK0maY2BJCYoAAIm7FCZguFCaww2VHygZVuFVeYSSgccwjke9IIhRYAH4WEiAggA
💻 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:
🙁 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 ofdata
based on the enum associated with it. You can even useArgType
as expected by itself:🙂 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 matchArgMap[T]
. So it should be possible to restrict the type hereAdditional information about the issue
No response
The text was updated successfully, but these errors were encountered: