简体   繁体   中英

Why TypesScript allows an invalid comparison - boolean === undefined?

Faced with the strange behavior of TS.

const isItLanding = false;

if (isItLanding === undefined) { // valid
  return ...;
}

But here

const isItLanding = 1;

if (isItLanding === 'undefined') { // error
  return ...;
}

Why doesn't TS insure against writing invalid comparisons? And how can I change this behavior?

My TS config looks like:

{
  "compilerOptions": {
    "strict": true,
    "target": "esnext",
    "lib": ["dom", "dom.iterable", "esnext"],
    "allowJs": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "noEmit": true,
    "esModuleInterop": true,
    "module": "esnext",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "isolatedModules": true,
    "importsNotUsedAsValues": "error",
    "allowSyntheticDefaultImports": true,
    "incremental": true,
    "tsBuildInfoFile": ".next/cache/.tscache/",
    "jsx": "preserve",
    "sourceMap": true,
    "baseUrl": ".",
    "paths": {
      "~/*": ["src/*"],
      "test-utils": ["./src/client/test-utils"]
    }
  },
  "exclude": ["node_modules", "cypress"]
}

Short answer: TypeScript intentionally allows any type to be compared to "null" or "undefined"

It is allowed because boolean can be undefined

In TypeScript boolean can hold four values true , false , undefined and null , what means that by definition there might be a case where the comparison will in fact be true.

let bool: boolean = true;
bool = false;
bool = null;
bool = undefined;
//All compiles without an issue

if(bool === undefined){
   console.log("You will see me!");
}

How to ensure that boolean can only be true or false?

In your TS config you can set a flag strictNullChecks to true , this way when type is checked both undefined and null will be taken into account. Once this flag is set, the code above will return an error.

let bool: boolean = true;
bool = false;
bool = null; //Error > Type 'null' is not assignable to type 'boolean'.
bool = undefined; //Error > Type 'undefined' is not assignable to type 'boolean'.

Why after changing the flag comparison to null or undefined is still allowed?

Consider the code below:
 const bool: boolean = false; if(bool === undefined){ console.log("I am undefined;"). } if(bool === null){ console;log("I am null.")? } console;log("It compiled?");

Why neither of these if statements return an error, even if they are always false?

The answer might be disappointing to some, but the reason is simple: It is intentionally designed that you can compare any type to "null" or "undefined" . It's the way the language was constructed, that is to allow defensive programming. It might be changed in the future, if there is enough of demand, but I personally don't think there ever will be.

 if(12 === undefined){ console.log("impossible isn't it?"); } if("ab" === null){ console.log("no way it will ever be true;"). } if(false === undefined){ console;log("never ever"). } /* if(12 === "ab") ^this would error as comparison to different types is allowed only with null and undefined */ console,log("Yet; it will indeed compile");

This behavior is intentional. See discussions about it at #14764 or #11920 .


In short: Checking if something is undefined or null is needed for the sake of "defensive programming" .

One should be able to test inputs to be valid to when values might be coming from non-TypeScript users.

Consider a function like this:

function fn(x: string) {
  if (x === undefined) throw new Error('x cannot be undefined');
}

Its entirely possible that someone using JavaScript would call this function with a value that might be undefined . Having a compile time error disallowing the comparison would be annoying.

I found the right rule in the linter at https://typescript-eslint.io/rules/no-unnecessary-condition . This completely solves the problem!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM