-
Notifications
You must be signed in to change notification settings - Fork 12.4k
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
[Feature Request] Type guard on conditional types #23493
Comments
I'm not sure narrowing would be sound: let x: Test<string, boolean> = { multiple: true, value: "hello" };
typeGuard<string, boolean>(x);
/*
Passes type-checker.
input.multiple === true does not imply input.values is present.
*/ Why not use a union type with a discriminant property? (requires type Test<V> = { multiple: true; values: V[] } | { multiple?: false; value: V };
function typeGuard<V>(input: Test<V>) {
if (input.multiple) {
return input.values;
} else {
return input.value;
}
} |
have this issue any plan?🤫 |
@Kingwl probably no plans yet as marked as Thanks. |
@Cryrivers |
I think the thing is that it can't be safely fixed due to @jack-williams example. The problem is that the types for type Test<V, M extends boolean> = { multiple?: M } & (
M extends true ? { values: V[] } : { value: V }
)
type TestTrue = Test<string, true> // { multiple?: true; } & { values: string[]; }
type TestFalse = Test<string, false> // { multiple?: false; } & { value: string; }
type TestBoolean = Test<string, boolean>
// ({ multiple?: boolean; } & { values: string[]; }) | ({ multiple?: boolean; } & { value: string; }) It's the third case that makes let x: Test<string, boolean> = { multiple: true, value: "hello" }; a valid assignment and would make the proposed narrowing unsound. Although as a side note you can force type XorBoolean<B extends boolean> = boolean extends B ? never : boolean
type Test2<V, M extends XorBoolean<M>> = { multiple?: M } & (
M extends true ? { values: V[] } : { value: V }
)
type Test2True = Test2<string, true> // { multiple?: true; } & { values: string[]; }
type Test2False = Test2<string, false> // { multiple?: false; } & { value: string; }
type Test2Boolean = Test2<string, boolean> // error: type boolean does not satisfy constraint never Still doesn't narrow in the original example however since type constraints like that aren't taken into account. |
Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed. |
Code
Expected behavior:
input.values
can be inferred inif
block andinput.value
can be inferred inelse
block.Actual behavior:
Property 'values' does not exist on type 'Test<V, M>'.
Property 'value' does not exist on type 'Test<V, M>'.
Playground Link: https://www.typescriptlang.org/play/#src=type%20Test%3CV%2C%20M%20extends%20boolean%3E%20%3D%20%7B%20multiple%3F%3A%20M%20%7D%20%26%20(%0D%0A%20%20%20%20M%20extends%20true%20%3F%20%7B%20values%3A%20V%5B%5D%20%7D%20%3A%20%7B%20value%3A%20V%20%7D%0D%0A)%0D%0A%0D%0Afunction%20typeGuard%3CV%2C%20M%20extends%20boolean%3E(input%3A%20Test%3CV%2C%20M%3E)%20%7B%0D%0A%20%20%20%20if%20(input.multiple)%20%7B%0D%0A%20%20%20%20%20%20%20%20return%20input.values%3B%0D%0A%20%20%20%20%7D%20else%20%7B%0D%0A%20%20%20%20%20%20%20%20return%20input.value%3B%0D%0A%20%20%20%20%7D%0D%0A%7D
Related Issues:
The text was updated successfully, but these errors were encountered: