-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Generic derived value type #28597
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
Comments
@ahejlsberg it seems like we might be able to recognize discriminants in conditional types similarly to unions - though it also seems much less straightforward to resolve them. |
This isn't a bug (see this discussion in #24085 ). Consider the following code: type ExamplePrice = filterValueType<"price">;
// = { from: number; to: number; }
type ExampleRange = filterValueType<"price_range">;
// = { fromRange: number; toRange: number; }
type ExampleBoth = filterValueType<"price" | "price_range">;
// = priceFilterValue | priceRangeFilterValue The last is because (for whatever reason), conditional types are automatically mapped over unions. Therefore, I can make the following call to the function: const weirdInput: productFilterParameters<"price" | "price_range"> = {
filter: "price",
value: {
fromRange: 0,
toRange: 10,
},
}
addProductFilter<"price" | "price_range">(weirdInput); with no errors. Everything type checks, as it's supposed to. Inside the function, the case will match "price", and yet there will be a I have a proposal at #27808 to add an |
@weswigham so is this possible to implement in to the typescript or should i find another solution? |
I've just come across this issue myself. Here's a quick reproduction. type state = 'a' | 'b' | 'c';
interface MyInterface<S extends state> {
state: S,
additionalProp: S extends 'a' ? string[] : never;
}
const myFun = <S extends state>(arg: MyInterface<S>) => {
// This infer arg as MyInterface<'c'>
if (arg.state === 'c') {
return arg.additionalProp.length; // This should throw "cannot use property 'length' on type never"
}
// Manually casting this type works as expected
const forcedType: MyInterface<'b'> = { state: 'b' };
forcedType.additionalProp.length // error
} It looks as though, despite the conditional statement, the type of |
@andyrichardson that behavior is as expected (although for a completely different reason). All operations are legal on Since TypeScript does provide a best-effort check for operations on definitely Replacing |
@Nathan-Fenner this isn't an issue relating to the use of The problem is that following the condition |
The error absolutely is produced (provided that You obtain the error:
As expected. Your issue is due to misuse of |
@Nathan-Fenner you're right, the error does appear when strictNullChecks are enabled - but that doesn't solve the bug in question.
The reason strict null checks throws an error is because the type of Type following conditional (incorrectly inferred)Type when explicitly stated |
@andyrichardson The behavior is still as expected:
This isn't the case. Given that const exampleValue: MyInterface<'a' | 'c'> = {
state: 'c',
additionalProp: ["foo", "bar", "baz"],
}; This value can be passed to You can avoid distribution with the following trick: interface MyInterface<S extends state> {
state: S,
additionalProp: [S] extends ['a'] ? string[] : never;
} by wrapping the two types in a single-element tuple. However, this won't actually solve the problem, because it is still impossible to distinguish (solely using flow types) that The following trick almost works, except the TS's flow-typing is not sophisticated enough to understand that deducing type state = 'a' | 'b' | 'c';
interface MyInterface<S extends state> {
state: [S] extends ['a'] ? 'a' : [S] extends ['b'] ? 'b' : [S] extends ['c'] ? 'c' : null,
additionalProp: [S] extends ['a'] ? string[] : null;
} This makes the code actually sound (since the |
Hello I was facing the same issue in my action factory (I might come back later with a minimal example). I think we need to come up with a way to declare the type as a Singletton or accept that it is singleton if it extends a singleton. In my case, it would be even more useful to allow a generic of singleton types eg ActionType<'my feature', 'my action type','my action name'>( being the type of 'myfeature | my action | my action name' |
Hey guys.
I can not see if I'm doing anything wrong here. I am expecting to be able to get exact type from generic type ...
Is this just limitation of typescript or i am doing anything whrong here?
TypeScript Version: 3.1.3
Search Terms:
Generic derived value type
Code
Expected behavior:
Code
Actual behavior:
Code
Playground Link:
Playground
Related Issues:
The text was updated successfully, but these errors were encountered: