Typescript: Should warn against invalid typeof expression

Created on 30 Dec 2018  路  8Comments  路  Source: microsoft/TypeScript


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:

Working as Intended

Most helpful comment

@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.

All 8 comments

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.

EDIT: 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:

  1. It used to be that null and undefined were always in the domain of every type, before strictNullChecks was implemented.
  2. When writing library code, you usually want to put live guards at API boundaries, in case the caller is pure JavaScript and therefore doesn't benefit from the type system to catch null-ish values being passed in (it's much more likely that the caller accidentally passes 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.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

blendsdk picture blendsdk  路  3Comments

manekinekko picture manekinekko  路  3Comments

jbondc picture jbondc  路  3Comments

seanzer picture seanzer  路  3Comments

MartynasZilinskas picture MartynasZilinskas  路  3Comments