Closed
Description
TypeScript Version: typescript@3.6.0-dev.20190809
Search Terms: unknown, type guard, double-equals, ==, null
Code
Minimal repro case:
export function test(v: unknown) {
let nullOrUndefined: null | undefined;
if (v === null || v === undefined) {
// This works, as `v` is narrowed to `null | undefined`.
nullOrUndefined = v;
}
if (v == null) {
// Error: Type 'unknown' is not assignable to type 'null | undefined'.
nullOrUndefined = v;
}
}
A more practical use-case for the narrowing would be something like this:
if (typeof v === 'string' || v == null) {
// v should be `string | null | undefined` in here.
if (v) {
// v is a non-empty string
doSearch(v);
} else {
// v is empty string, null, or undefined
clearSearch();
}
}
Expected behavior:
v == null
narrows an unknown
type to null | undefined
, same as v === null || v === undefined
does.
Reading the ECMAScript spec on ==
, I believe that == null
will guarantee that the value is either null or undefined. == undefined
would do the same thing, though linters generally prefer the shorter == null
.
Actual behavior:
Compile error:
src/index.ts:11:5 - error TS2322: Type 'unknown' is not assignable to type 'null | undefined'.
Type 'unknown' is not assignable to type 'null'.
11 nullOrUndefined = v;
~~~~~~~~~~~~~~~
Found 1 error.
Related Issues:
- Triple-equal narrowing of
unknown
was added in Fix #25172: Add narrowing forunknown
with triple equals #26941- The PR specifically noted "Does not work with == because we would need to consider coercion rules."
- That's true for the general case. Thankfully, the behavior of
== null
is well-defined and can be special-cased.
- There's a general issue Allow more constructs to work as type guards for
unknown
#25720 open for better narrowing ofunknown
.