error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. and its twin TS2363 (the right-hand side) are reported for -, *, /, % and ** when an operand is not a number. JavaScript converts the operand silently at run time; the checker asks you to do it on purpose.
The two classic cases in JavaScript are subtracting Date objects to measure time (new Date() - startedAt), which works at run time through valueOf, and multiplying an input's value, which is a string. + is not on the list: with a string it concatenates, so it has its own message (TS2365) when it cannot apply.
At a glance
| Code | TS2362 |
|---|---|
| Message | The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. |
Also on this page: TS2363 | The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type. |
| TypeScript's category | error |
| Listed under | Types do not match |
| Turned on by | No option: every checked file reports it |
| In .js files | Reported when the file is checked: checkJs in jsconfig.json, or // @ts-check at the top of the file |
The messages are TypeScript's own text from its diagnostic messages file (Apache-2.0).
What it looks like
const startedAt = new Date();
export const elapsedMs = new Date() - startedAt;error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
export const sinceStart = Date.now() - startedAt;error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.
const field = document.querySelector("input");
export const doubled = field ? field.value * 2 : 0;error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} What causes it
How to fix it
Convert the operand to a number
Use date.getTime() (or Date.now() for the current time) for dates, and Number(text) or input.valueAsNumber for form values. The result is the same number JavaScript would have used, now visible in the code.
const startedAt = new Date();
export const elapsedMs = Date.now() - startedAt.getTime();
export const sinceStart = Date.now() - startedAt.valueOf();
const field = document.querySelector("input");
export const doubled = field ? Number(field.value) * 2 : 0;jsconfig.json for this example
{
"compilerOptions": {
"checkJs": true,
"noEmit": true,
"strict": true,
"target": "es2022",
"module": "nodenext",
"types": []
},
"include": ["*.js"]
} Gotchas
- Unary plus (
+startedAt) also converts and the checker accepts it, butgetTime()says what is meant. Number("")is0andNumber("abc")isNaN; the checker only seesnumber, so validate input before doing arithmetic with it.
Sources
- Date.prototype.getTime() · MDN Web Docs
- Everyday Types: The primitives · TypeScript handbook
- diagnosticMessages.json (TypeScript 5.9.3) · TypeScript on GitHub
Last reviewed 20 October 2026.