-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Typeguard with ""|undefined not working #31156
Comments
This looks like a bug to me. The current behaviour when the source type is a union (here When the source type is not a union then the code intersects the source with the candidate ( I think |
@andrewbranch fyi I didn't look fully into this, but generally assume @jack-williams is right 😉 |
@RyanCavanaugh given the discussion in #31206, what should we bump the milestone to? |
Cross-posting from PR #31206 for visibility:
|
I need a sad face react =( Thank you for the update, and the attempt! |
This is a repro of a problem @G-Rath had, on TS 3.7.4, //--strictNullChecks
declare const s: string | undefined;
declare function isEmptyStrOrUndefined(mixed: string|undefined): mixed is "" | undefined;
if (isEmptyStrOrUndefined(s)) {
//Expected: s should be ""|undefined now
//Actual: s is undefined
if (s == undefined) {
//Should be undefined now
console.log(s);
} else {
//Expected: Should be "" now
//Actual: s is `never`
//Property 'length' does not exist on type 'never'.
console.log(s.length);
}
}
declare function isEmptyStr(mixed: string | undefined): mixed is "";
declare function isUndefined(mixed: string|undefined): mixed is undefined;
if (isEmptyStr(s) || isUndefined(s)) {
//Expected: s should be ""|undefined now
//Actual: s is ""|undefined; as expected
if (s == undefined) {
//Should be undefined now
console.log(s);
} else {
//Expected: Should be "" now
//Actual: s is ""; as expected
console.log(s.length);
}
} It seems like type guard unions heck things up. Is this because it's checking subtypes only when the type guard is for a union type? [EDIT] It seems like his problem is different from mine. See his comment 👇 for more info. The workaround of not using union type guards works, though, even if cumbersome. Instead of, myTypeGuard (x : X) : A|B;
if (myTypeGuard(x)) {
//stuff
} Use, myTypeGuardA (x : X) : A;
myTypeGuardB (x : X) : B;
if (myTypeGuardA(x) || myTypeGuardB(x)) {
//stuff
} |
I came across this when upgrading @typescript-eslint/typescript-estree from 2.12.0 to 2.13.0 as part of package update on The change that caused this issue is that If I comment out the Here's a playground helpfully supplied by @AnyhowStep |
I ran into this in real-world code. This is an abbreviated reproduction of my case:
|
We encountered a vaguely similar problem in #41871. The commonalities seem to be:
Our repro works all the way back to TypeScript 2.0.10, so this problem apparently has been around for a while. |
minimal example declare function assert<T>(value: any): asserts value is T
declare const foo: number | string | boolean
assert<1 | string>(foo)
const bar = foo //string |
I also ran into this problem: function isEmptyOrUndefined(str: string | undefined): str is undefined | "" {
return str == undefined || str === "";
}
function test(s: string | undefined) {
if (isEmptyOrUndefined(s)) {
let len = s?.length; // error
}
} I'm going to work around it for now by returning |
TypeScript Version: 3.3.0, and the version on TS playground (3.4.1 as of this writing)
Search Terms: typeguard, empty string literal, undefined, union
Code
Expected behavior:
s
should be""|undefined
where marked.Also, unrelated, but this is where I would have liked a
NaN
literal in TS =/Actual behavior:
s
isundefined
Playground Link: Here
Related Issues: Not that I could find
The text was updated successfully, but these errors were encountered: