Introduced in Typescript 3.7, the nullish coalescing operator seems to be a perfect type guard for scenarios like the following:
const fs = (s: string) => s
const fn = (n: number) => n
let a: string | null | undefined
let b: number | null | undefined
const x = (a ?? null) && fs(a)
const y = (b ?? null) && fn(b)
However, running this code on the typescript playground, it raises alerts for both 'a' and 'b' parameters passed into the 'fs' / 'fn' functions:
https://i.sstatic.net/ywI5M.png Further experimentation revealed that the issue extends beyond just the nullish coalescing operator. I'm struggling to understand when typescript can utilize something as a typeguard and when it cannot. Check out some examples.
The last two lines are particularly perplexing to me. Although the expressions assigned to 'x7' and 'x8' appear to be identical, TypeScript acknowledges the typeguard in one but not the other:
const fs = (str: string) => str
const create = (s: string) => s === 's' ? 'string' : s === 'n' ? null : undefined
const a: string | null | undefined = create('s')
const b: string | null | undefined = 's'
let x
if (a !== null && a !== undefined) {
x = a
} else {
x = fs(a)
}
const x1 = a !== null && a !== undefined && fs(a)
const x2 = a !== null && a !== void 0 && fs(a)
const x3 = (a ?? null) && fs(a)
const x4 = (b ?? null) && fs(b)
const x5 = a !== null && a !== undefined ? a : fs(a)
const something = a !== null && a !== undefined
const x6 = something ? a : fs(a)
const x7 = something && fs(a)
const x8 = (a !== null && a !== undefined) && fs(a)
I'm unsure if TypeScript is simply unable to apply the typeguard for some reason or if there might be a bug in the system. Is there a guideline for when TypeScript can implement a typeguard and when it cannot? Or could there be another reason causing these examples to fail compilation?
On a side note, employing a user-defined type guard works flawlessly, but it would be ideal not to have to include additional runtime code for the typeguard to function.