Tslint Typeerror: Cannot Read Property 'kind' of Undefined
Equally a JavaScript developer, I'm sure yous've encountered the frustrating runtime TypeError Cannot read properties of undefined
.TypeScript gives yous 2 means of interpreting null
and undefined
types, also known as Type Check Modes, and one of them can avoid this easily disregarded TypeError.
Until TypeScript 2.0, there was only i blazon cheque fashion - regular - and it considers null
and undefined
equally subtypes of all other types. This means null
and undefined
values are valid values for all types.
TypeScript two.0 introduced Strict Type Check Way (as well referred to equally strict zip checking mode). Strict Blazon Check differs from Regular Type Check because it considers goose egg
and undefined
types of their own.
I'll show you how Regular Blazon Check handles undefined
(the same applies to aught
) and how Strict Type Check prevents you from introducing unwanted behavior in our code, like that infamous TypeError Cannot read backdrop of undefined
.
When undefined becomes a problem
The function translatePowerLevel beneath takes a number as argument and returns strings 1
, two
, many
or it's over 9000!
.
office translatePowerLevel(powerLevel: number): string {
if (powerLevel === 1) {
render 'i';
}
if (powerLevel === 2) {
return 'two';
}
if (powerLevel > 2 && powerLevel <= 9000) {
return 'many';
}
if (powerLevel > 9000) {
return 'it\'s over 9000!';
}
}
All the same, this code doesn't handle 0, a valid input - yes, looking at yous, Yamcha.
Yamcha's Power Level
When JavaScript reaches the end of a function that has no explicit return, it returns undefined
.
The translatePowerLevel
function render value is typed explicitly as string
, but it is peradventure too returning undefined
when the statement powerLevel
has the value0. Why is TypeScript not triggering an error?
In Regular Blazon Check Style, TypeScript is aware that a function might render undefined
. Merely at the aforementioned time, TypeScript infers the return type to be merely of type string
because TypeScript is widening the undefined
type to string
type.
As another example, if you assign aught
or undefined
to variables while in Regular Type Bank check Mode, TypeScript will infer these variables to be of type whatever
.
const java = nil;
const tea = undefined;
Interpreting undefined
or nil
as subtypes of all other types can lead to runtime issues. For example, if you effort to become the length of the result of translateNumber(0)
, which is undefined
, JavaScript will throw this TypeError at runtime: Cannot read properties of undefined (reading 'length').
const powerLevel = translatePowerLevel(0); // undefined
panel.log(powerLevel.length); // Uncaught TypeError: Cannot read properties of undefined (reading 'length')
Unfortunately, TypeScript's Regular Type Check Mode is not able to warning you lot to when y'all may accept fabricated that error.
Strict Type Check Mode to the Rescue
Strict Blazon Bank check Mode changes how TypeScript interprets undefined
and nil
values. Just first, allow'due south enable Strict Type Check Style.
How to Enable Strict Blazon Check Mode in TypeScript
In the root of your projection, there should be a tsconfig.json file
. This is the TypeScript's configuration file and yous can read more well-nigh information technology hither.
// tsconfig.json example
{
"compilerOptions": {
"module": "organisation",
"noImplicitAny": true,
"removeComments": truthful,
"preserveConstEnums": truthful,
"outFile": "../../congenital/local/tsc.js",
"sourceMap": truthful
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
Inside compilerOptions
property, all we need to do is add the property "strictNullChecks": true
.
Information technology will await something similar this:
// tsconfig.json
{
"compilerOptions": {
"module": "arrangement",
"noImplicitAny": truthful,
"removeComments": true,
"preserveConstEnums": truthful,
"outFile": "../../built/local/tsc.js",
"sourceMap": truthful,
"strictNullChecks": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "**/*.spec.ts"]
}
Now that nosotros have switched to Strict Blazon Check Manner, TypeScript throws this error for translatePowerLevel
part: Function lacks ending render statement and return type does not include 'undefined'
.
That mistake message is telling y'all the office is returning undefined
implicitly, but its return type does not include undefined
in it.
Awesome! TypeScript is now aware the return type does non match all possible return values, and this could lead to problems at runtime! But how can you match the return type to all possible return values?
You lot tin can either add a render argument so the part always returns a string
(solution #i), or alter the return blazon from string
to string | undefined
(solution #2).
Lucifer All Possible Return Values: Solution #1
Adding a return statement so it is always explicitly returning a value - in the code below, information technology is now returning the string aught
.
// Solution #1: add a return argument then it e'er returns a string
function translatePowerLevel(powerLevel: number): string {
if (powerLevel === 1) {
render 'i';
}
if (powerLevel === 2) {
return '2';
}
if (powerLevel > 2 && powerLevel <= 9000) {
render 'many';
}
if (powerLevel > 9000) {
return 'it\'south over 9000!';
}
// new return statement
render 'zilch';
}
Friction match All Possible Return Values: Solution #2
Make the undefined
render type explicit then wherever translatePowerLevel
is used, you have to handle nullish
values besides.
// Solution #two: return type every bit string | undefined
role translatePowerLevel(powerLevel: number): string | undefined {
if (powerLevel === 1) {
return 'one';
}
if (powerLevel === 2) {
return 'ii';
}
if (powerLevel > two && powerLevel <= 9000) {
render 'many';
}
if (powerLevel > 9000) {
render 'it\'s over 9000!';
}
}
If you were to compile the post-obit code again using Solution #2, TypeScript would throw the error Object is possibly 'undefined'
.
const powerLevel = translatePowerLevel(0); // undefined
panel.log(powerLevel.length); // Object is perhaps 'undefined'.
When yous choose a solution like Solution #ii, TypeScript expects you lot to write code that handles possible nullish
values.
There's no reason not to utilize Strict Blazon Check Mode
Now yous understand how TypeScript interprets null
and undefined
types and how y'all can migrate your project to Strict Fashion.
If y'all are starting a new project, you should definitely enable Strict Type Check Mode from the commencement. And in case y'all will drift from Regular to Strict Type Cheque, our team can help with strategies to do then in a less painful way.
At Bitovi we highly recommend using - or migrating to - Strict Type Check Way for Angular application development, as it can help y'all produce meliorate, more reliable lawmaking. If you need help with edifice astonishing web apps feel free to achieve us at bitovi.com .
Tslint Typeerror: Cannot Read Property 'kind' of Undefined
Source: https://www.bitovi.com/blog/how-to-avoid-the-infamous-cannot-read-properties-of-undefined-with-typescript