Repository navigation
type guards strangeness #7224
Description
Activity
Aleksey-Bykov I'm also finding that user-defined type guards often don't work the way I intuitively expect. Your example makes intuitive sense to me and I would have expected it to work.
However, since you haven't started with a union type, I suspect you are working outside the bounds of what tsc can currently do with type guards. I got your example to work by changing the declaration of
valueto:let value: string | (string & AsNonBlank);
This seems to satisfy the compiler, and the narrowing happens as expected in both the
ifandelsebranches.Interestingly, the following version of your code does work as you expect:
const enum AsUnaryFunc {} export function isUnaryFunc(value: Function) : value is Function & AsUnaryFunc { return value.length === 1; } let value: Function; if (isUnaryFunc(value)) { doThis(value); // expected value to be Function & AsUnaryFunc, AND IT IS } else { doThat(value); } function doThis(value: Function & AsUnaryFunc): void { } function doThat(value: Function) : void { }
It's the same code as yours, just with
Function/AsUnaryFunctioninstead ofstring/AsNonBlank.zpdDG4gta8XKpMCd commented
on Feb 25, 2016 AuthorMore actionsTroy Gerwien (@yortus) thanks!
zpdDG4gta8XKpMCd commented
on Feb 26, 2016 AuthorMore actionsTroy Gerwien (@yortus) just checked with the union, it doesn't work either
const enum AsNonBlank {} export function isNonBlank(value: string | string & AsNonBlank) : value is string & AsNonBlank { return !/^\s*$/g.test(value); } let value: string; if (isNonBlank(value)) { doThis(value); // expected value to be string & AsNonBlank, actual is *STILL* a string } else { doThat(value); } function doThis(value: string & AsNonBlank): void { } function doThat(value: string) : void { }
Sorry I wasn't clear - this one works for me:
const enum AsNonBlank {} export function isNonBlank(value: string) : value is string & AsNonBlank { return !/^\s*$/g.test(value); } let value: string | (string & AsNonBlank); // <-- union here if (isNonBlank(value)) { doThis(value); // expected value to be string & AsNonBlank } else { doThat(value); } function doThis(value: string & AsNonBlank): void { } function doThat(value: string) : void { }
- added a commit that references this issue
on Jun 2, 2016 zpdDG4gta8XKpMCd commented
on Jun 2, 2016 AuthorMore actionsThanks! That's a great help!
- locked and limited conversation to collaborators
on Jun 19, 2018
TypeScript Version:
1.8.0
Code
Expected behavior:
value should either be
string & AsNonBlankor there must be a message saying that the type guard is invalid or something
Actual behavior:
value is a
string