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"
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!");
}
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'.
const bool: boolean = false; if(bool === undefined){ console.log("I am undefined;"). } if(bool === null){ console;log("I am null.")? } console;log("It compiled?");
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.