error TS2564: Property 'userId' has no initializer and is not definitely assigned in the constructor. is reported for a class field declared with a type (here /** @type {string} */ userId;) when neither the declaration nor the constructor gives it a value. Until something does, reading it gives undefined, which the type does not allow.
The check is strictPropertyInitialization, part of strict. It applies to fields declared in the class body; a property created only by this.x = ... in the constructor is set by definition.
At a glance
| Code | TS2564 |
|---|---|
| Message | Property '{0}' has no initializer and is not definitely assigned in the constructor. |
| TypeScript's category | error |
| Listed under | Classes, JSX and unused code |
| Turned on by | strictPropertyInitialization, strict |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The message is TypeScript's own text from its diagnostic messages file (Apache-2.0); {0} is filled in by tsc for each error.
What it looks like
export class Session {
/** @type {string} */
userId;error TS2564: Property 'userId' has no initializer and is not definitely assigned in the constructor.
startedAt = new Date();
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- A field has a
@typethat does not includeundefined, no initializer, and no assignment in the constructor. - The value is set later (in an
initmethod, after anawait), which the checker cannot follow.
How to fix it
Set it in the constructor, or allow undefined in its type
Take the value as a constructor parameter and assign it there, or give the field a starting value. If it really is empty for a while, say so: /** @type {string | undefined} */ token;, and handle the empty case where it is read.
export class Session {
/** @type {string} */
userId;
/** @type {string | undefined} */
token;
startedAt = new Date();
/** @param {string} userId */
constructor(userId) {
this.userId = userId;
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Gotchas
- Assignments inside methods the constructor calls (
this.reset()) do not count; the checker only looks at the constructor body itself. - A field with no
@typeand no value is TS7008 instead, the implicitanyerror.
Sources
- TSConfig Reference: strictPropertyInitialization · TypeScript
- Classes: Fields · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.