error TS7008: Member 'items' implicitly has an 'any[]' type. is reported for a class property whose type would fall back to any (or any[]) under noImplicitAny. In a .js file the checker types a property from the values assigned to it in the class, so the error means none of those values tells it anything: the field is declared bare (items;), or set only to [], null or undefined.
A field assigned a real value in the constructor is fine without a tag: owner in the example gets string from this.owner = owner. Empty arrays are the common trap, because [] says nothing about what will go in it.
At a glance
| Code | TS7008 |
|---|---|
| Message | Member '{0}' implicitly has an '{1}' type. |
| TypeScript's category | error |
| Listed under | Implicit any |
| Turned on by | noImplicitAny, 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} and {1} are filled in by tsc for each error.
What it looks like
export class Cart {
items;error TS7008: Member 'items' implicitly has an 'any[]' type.
owner;
/** @param {string} owner */
constructor(owner) {
this.owner = owner;
this.items = [];
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
- A class field is declared without an initializer and nothing in the class assigns it a typed value.
- Every assignment is
[],nullorundefined, which in a.jsfile leave the type asanyorany[]. noImplicitAnyis on (part ofstrict).
How to fix it
Put a @type tag on the field
/** @type {string[]} */ on the line above items = []; gives the field its type. For a property created in the constructor, put the tag above the assignment: /** @type {string[]} */ this.items = [];. A field initialized with a value the checker can read (createdAt = new Date()) needs no tag.
export class Cart {
/** @type {string[]} */
items = [];
/** @type {string} */
owner;
createdAt = new Date();
/** @param {string} owner */
constructor(owner) {
this.owner = owner;
}
}jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Gotchas
- Properties that are only assigned in a method (not the constructor or the field list) are treated as optional, so code reading them must handle
undefined. - A
@typeon a field without an initializer is also checked bystrictPropertyInitialization: if the constructor does not set it, that is TS2564.
Sources
- Type Checking JavaScript Files: Properties are inferred from assignments in class bodies · TypeScript handbook
- TSConfig Reference: noImplicitAny · TypeScript
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.