If you've stumbled upon this post there's a strong chance that you've just been hit by the following error message when trying to compile/transpile a TypeScript project with Visual Studio 2017:
Error TS2564 (TS) Property 'class' has no initializer and is not definitely assigned in the constructor.
The property name(s) might vary, but the outcome doesn't change: your TS project doesn't compile anymore. Why is something like this suddendly happening, and how can we fix that for good?
The Issue
The problem is most likely due to the strictPropertyInitialization flag firstly introduced in TypeScript 2.7 (and beyond), which could cause these kind of errors: if you recently upgraded your TypeScript TSC executable, or Visual Studio 2017, you are most likely dealing with the consequences of this breaking change.
As you can see by taking a look to the TypeScript 2.7 release notes, TS 2.7 introduces a new flag called --strictPropertyInitialization . This flag performs checks to ensure that each instance property of a class gets initialized in the constructor body, or by a property initializer. To give a quick example on that, consider the following code:
1 2 3 4 5 6 7 8 9 10 11 12 |
class C { foo: number; bar = "hello"; baz: boolean; // ~~~ // Error! Property 'baz' has no initializer and is not definitely assigned in the // constructor. constructor() { this.foo = 42; } } |
In the above sample, if we truly meant for baz to potentially be undefined, we should have declared it with the type boolean | undefined.
It's worth noting that there are certain scenarios where properties can be initialized indirectly - perhaps by a helper method or dependency injection library; in that case, you can use the new definite assignment assertion modifiers for your properties and fix the issue for good:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class C { foo!: number; // ^ // Notice this '!' modifier. // This is the "definite assignment assertion" constructor() { this.initialize(); } initialize() { this.foo = 0; } } |
Keep in mind that --strictPropertyInitialization will be turned on by default in TS >= 2.7, together with other --strict mode flags: such default behaviour will most likely impact your existing projects and/or third party NPM packages, expecially if they were built against previous version of TypeScript.
The Fix
If the problem is related to a NPM package the first thing to do is to update it to its latest version, as the author had most likely already experienced that and possibly came out with an update to properly address the new behaviour. If the issue is happening inside our own code, the best thing we can do is to fix that manually by adding the definite assignment assertion modifier like explained above: in most scenarios, a bunch of ! placed in the right spots will be enough fix your project.
If you cannot do that, we can choose to disable the new feature by setting the strictPropertyInitialization initialization flag to false in the compilerOptions section within our tsconfig.json configuration file; alternatively, we can also add the --strictPropertyInitialization false command-line switch to turn off this checking.
In the unlikely case both of the above fixes won't be enough, try to temporarily downgrade to TypeScript <= 2.6 and see if the error persists.
References