-
Notifications
You must be signed in to change notification settings - Fork 12.8k
type guard narrowing to a type with type with any
in type parameters replaces any
with unknown
#57892
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
Likely this is working as intended. There is a subtype relationship between interface Box<T> {
value: T;
}
function isBox(box: unknown): box is Box<any> {
return true;
}
declare class Dog {
bark(): void;
}
declare const smth: Box<number> | Dog;
if (isBox(smth)) {
smth.value;
// ^? Box<number>
} |
If the type guard is typed as It's fine if TypeScript tries to guess missing intent. But here we authored it as "narrow this to |
Narrowing is more like a filtering operation and not like a cast/assignment. Otherwise, you likely wouldn't be able to express "check if it's a Box and if it's a Box keep the type intact". We can check how this doesn't infer the type argument: interface Box<T> {
value: T;
}
function isBox<T>(box: unknown): box is Box<T> {
return true;
}
declare class Dog {
bark(): void;
}
declare const smth: Box<number> | Dog;
if (isBox(smth)) {
// ^? function isBox<unknown>(box: unknown): box is Box<unknown>
smth.value;
// ^? Box<number>
} |
It really isn't. People in general hate This has been the behavior since at least 3.3 and I don't think this is a) surprising, since we haven't gotten other reports on it or b) a welcome change to all the people who wrote declarations of the form |
I missed the regression part since I think I was working off the other example. I'll bisect to ensure we're on the same page here. |
Yeah, the 4.9.5 behavior is just inconsistent for no obvious reason: interface Box<T> {
value: T
}
function isBox(box: unknown): box is Box<any> {
return true
}
declare const box1: string | Box<unknown>;
if (isBox(box1)) {
box1.value
// ^?
// any
}
declare const box2: string | Box<{} | null | undefined>;
if (isBox(box2)) {
box2.value
// ^?
// {} | null | undefined
}
declare const box3: string | Box<string>;
if (isBox(box3)) {
box3.value
// ^?
// string
} It doesn't make sense to narrow from |
note that IIRC |
This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
π Search Terms
type guard parameter any unknown
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play?ts=5.5.0-dev.20240321#code/JYOwLgpgTgZghgYwgAgEIHsAeAeAKgPmQG8AoZc5ANzgBsBXCALmVxIF8SSY6QExh0IZMADOGHAQAUAIyzMeAaxDoA7iACUzWZmEi0WPIVIVkUCGDpQhYKA3acEgkWGQg6AW2nRxzcdkXKaoQAvMTU9EwAjBwkwDDIkqJ+bp7Q+JIpXlDi6urEZBSZ3lgAdOF2JgD0lSYmAHoA-PZxCUkGcCAAnulF2Vi5+Sa94mW0FRTVtRSN7EA
π» Code
π Actual behavior
π Expected behavior
Additional information about the issue
Maybe caused by #52282 which also caused #53178
The text was updated successfully, but these errors were encountered: