In certain cases I set the type of a const, and TypeScript ignores it. In particular, sometimes I add | undefined and TypeScript ignores the fact that the value might be undefined. Am I missing something?
I'm grabbing an element from an Array or a NodeList. I'm saving it in a let or a const. By default TypeScript assumes that an array access will never fail. I know this particular array access is very likely to fail. I'm trying to mark the type of the expression so when I try to use it later I don't forget to check for undefined. Here's an example:
const myArray = ["a", "b", "see", "d", "e", "f"];
// Default:
export const plain0 = myArray[0]; // "a"
export const plain9 = myArray[9]; // undefined
export const plainMissing = undefined; // undefined
console.log(plain0.length); // This will work as expected.
console.log(plain9.length); // This will cause a runtime error.
console.log(plainMissing.length); // Does not compile.
// With explicitly variable declarations:
export const variableType0 : string | undefined = myArray[0];
export const variableType9 : string | undefined = myArray[9];
export const variableTypeMissing : string | undefined = undefined; // undefined
console.log(variableType0.length); // Compiles but shouldn't!!!!
console.log(variableType9.length); // Compiles but shouldn't!!!!
console.log(variableTypeMissing.length); // Does not compile!
VS Code and tsc agree on the results. They both ignore my type declarations and allow me to access a string | undefined as if it was a string. The compiler is ignoring my declarations. It's treating variableType* in my code just like plain*.
I asked tsc to generate a .d.ts file for me. That confirms that it knows the second set of constants should have different types than the first set.
export declare const plain0: string;
export declare const plain9: string;
export declare const plainMissing: undefined;
export declare const variableType0: string | undefined;
export declare const variableType9: string | undefined;
export declare const variableTypeMissing: string | undefined;
When I'm in VS Code and I hover my mouse over any of the const statements, the tool tips show me the same types as the .d.ts files. These are the values I'm expecting.
But when I hover my mouse over any of the log statements, I see different types. On those lines, the tool tips for variableType0, variableType9, and variableTypeMissing are string, string, and undefined, respectively. Those types perfectly match the errors that I see. But those types do not match their declarations.
Is there some reason that TypeScript is ignoring my declarations? Is there something I'm doing wrong? Am I misunderstanding the rules? Is it a bug in the compiler? How can I mark the code so the compiler will force me to use ?. not just .?
This is my tsconfig.json. It mostly comes from vite, but I changed a few things.
{
"compilerOptions": {
"declaration": true,
"declarationDir": "./types",
"noImplicitAny": true,
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": ["ESNext", "DOM"],
"moduleResolution": "Node",
"strict": true,
"sourceMap": true,
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"emitDeclarationOnly": true,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noImplicitReturns": true,
"skipLibCheck": true
},
"include": ["src"]
}
EDIT / Simpler Example
const x : number|undefined = Math.random();
x.toFixed();
const y : number|string = Math.random();
y.toFixed();
This version does not use arrays. I'm running into the same problem. TypeScript thinks it knows the type of the variable. I'm telling TypeScript that I know better by offering a declaration. TypeScript is not giving me an error, saying it doesn't like my declaration. But then it ignores my declaration.