TypeScript Version: 3.2.2
Search Terms: typeof undefined
Code
// This condition will always return 'false' since the types '"string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '42' have no overlap.
typeof 42 === 42
typeof 42 === undefined
typeof 42 === null
Expected behavior:
typeof 42 === undefined
typeof 42 === null
Should warn as what typeof 42 === 42 warns.
Actual behavior:
No warnings
Playground Link:
http://www.typescriptlang.org/play/index.html#src=%2F%2F%20This%20condition%20will%20always%20return%20'false'%20since%20the%20types%20'%22string%22%20%7C%20%22number%22%20%7C%20%22bigint%22%20%7C%20%22boolean%22%20%7C%20%22symbol%22%20%7C%20%22undefined%22%20%7C%20%22object%22%20%7C%20%22function%22'%20and%20'42'%20have%20no%20overlap.%0Atypeof%2042%20%3D%3D%3D%2042%0A%0Atypeof%2042%20%3D%3D%3D%20undefined%0A%0Atypeof%2042%20%3D%3D%3D%20null
Related Issues:
I think fixing this case without breaking many common patterns would require special casing the check (with typeof and null), rather than changing the comparability relation. At that point I wonder if this would be better addressed with a lint rule instead.
What common pattern compares the result of typeof against undefined or null? It can never be anything other than a handful of strings so such a comparison seems like it would always indicate a logic error.
@fatcerberus TypeScript always allows comparing with null or undefined (because reasons). There's nothing special about comparing the result of a typeof expression. That's what @jack-williams means by:
would require special casing the check (with typeof and null), rather than changing the comparability relation.
IMO comparing something with null or undefined shouldn't be treated different from any other value. If you need to, your type declarations are probably wrong. But that's already discussed in another issue and was declined for compatibility reasons. Therefore I've written a lint rule, see below.
At that point I wonder if this would be better addressed with a lint rule instead.
This check already exists as lint rule.
strict-type-predicatesunknown, bigint or type parameters)no-useless-predicateEDIT: Thanks @ajafff, that鈥檚 a more detailed response than mine!
The common patterns are not those including typeof, but of the form M === undefined for some other arbitrary expression M.
To fix this issue the options seem to be changing the comparable relation for all M, but I鈥檓 not sure how desirable that is. Alternatively, special-casing certain forms of M, such as typeof, which I think might be better suited to a lint rule. See above comment for details!
Oh, that makes sense. I guess I assumed typeof was already special-cased, since it acts as a type guard. But I guess that鈥檚 controlled by a different part of the compiler than this error.
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
I recently ran into a similar issue, where it would have been nice if 'x === undefined' erred when x's type doesn't include undefined.
Can someone elaborate on:
@fatcerberus TypeScript always allows comparing with null or undefined (because reasons).
I assume there are 2 main reasons:
null and undefined were always in the domain of every type, before strictNullChecks was implemented.undefined or null rather than some arbitrary wrong type). If x === undefined was a type error then you'd nearly always have to cast for such checks. That would get annoying fast.
Most helpful comment
@fatcerberus TypeScript always allows comparing with
nullorundefined(because reasons). There's nothing special about comparing the result of atypeofexpression. That's what @jack-williams means by:IMO comparing something with
nullorundefinedshouldn't be treated different from any other value. If you need to, your type declarations are probably wrong. But that's already discussed in another issue and was declined for compatibility reasons. Therefore I've written a lint rule, see below.This check already exists as lint rule.
strict-type-predicatesunknown,bigintor type parameters)no-useless-predicate