TypeScript error

TS2322: A value does not match its declared type

  • Error TS2322
  • Tested with TypeScript 5.9

error TS2322: Type 'string' is not assignable to type 'number'. is the checker's most common error. It appears when a value is stored somewhere whose type was declared: a variable with @type, a property of an object typed with a @typedef, or the value a function returns under @returns. The first type in the message is the value you wrote; the second is the type the annotation promised.

In a JavaScript project the declared type almost always comes from a JSDoc comment, so the fix is either in the value (convert it, correct it) or in the comment (the type was too narrow). The error never changes what runs: it tells you the code and its documentation disagree.

At a glance

CodeTS2322
MessageType '{0}' is not assignable to type '{1}'.
TypeScript's categoryerror
Listed underTypes 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 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

product.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: product.js(8,3): error TS2322: Type 'string' is not assignable to type 'number'. product.js(14,1): error TS2322: Type 'string' is not assignable to type 'number'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. product.js(8,3): error TS2322: Type 'string' is not assignable to type 'number'. product.js(14,1): error TS2322: Type 'string' is not assignable to type 'number'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. product.js(8,3): error TS2322: Type 'string' is not assignable to type 'number'. product.js(14,1): error TS2322: Type 'string' is not assignable to type 'number'. checked 21 October 2026
/** @typedef {{ sku: string, name: string, price: number }} Product */

/** @type {Product} */
export const tee = {
  sku: "TEE-01",
  name: "Cotton tee",
  price: "19.99",error TS2322: Type 'string' is not assignable to type 'number'.
};

/** @type {number} */
let quantity = 1;
quantity = "2";error TS2322: Type 'string' is not assignable to type 'number'.

export { quantity };
A property of the wrong type, and a variable given a value of another type.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
cart.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: cart.js(8,3): error TS2322: Type 'string' is not assignable to type 'number'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. cart.js(8,3): error TS2322: Type 'string' is not assignable to type 'number'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. cart.js(8,3): error TS2322: Type 'string' is not assignable to type 'number'. checked 21 October 2026
/**
 * @param {number[]} prices
 * @returns {number}
 */
export function cartTotal(prices) {
  const total = prices.reduce((sum, price) => sum + price, 0);
  return total.toFixed(2);error TS2322: Type 'string' is not assignable to type 'number'.
}
A return value that does not match @returns.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

What causes it

  • A @type or @typedef says a variable or property holds one type, and the code puts a value of another type there (a string where a number is declared, null where null is not allowed).
  • A function's @returns tag names a type and a return statement hands back something else.
  • With strictNullChecks on (part of strict), a value that may be undefined or null is stored where the type does not include them. The message then names undefined or null as the type that is not assignable.

How to fix it

Fix or convert the value

When the annotation is right, change the value: write the number as a number, or convert text with Number(...) before storing it. A return that formats a number for display (toFixed returns a string) belongs in a separate function whose @returns says string.

cart.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
/** @typedef {{ sku: string, name: string, price: number }} Product */

/** @type {Product} */
export const tee = {
  sku: "TEE-01",
  name: "Cotton tee",
  price: 19.99,
};

/** @type {number} */
let quantity = 1;
quantity = Number("2");

/**
 * @param {number[]} prices
 * @returns {number}
 */
export function cartTotal(prices) {
  const total = prices.reduce((sum, price) => sum + price, 0);
  return Math.round(total * 100) / 100;
}

/**
 * @param {number[]} prices
 * @returns {string}
 */
export function cartTotalLabel(prices) {
  return cartTotal(prices).toFixed(2);
}

export { quantity };
The values match their types.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

Or widen the declared type

When the value is right and the comment is too strict, change the comment: @type {number | string} for a value that really can be either, @returns {string} when the function's job is to format. A union is honest documentation; it also makes every caller handle both cases.

Read the whole message for objects

For objects and arrays the first line names the outer types and the indented lines underneath say which property differs. In the editor the squiggle sits on the property itself, which is usually the line to change.

Where the error is reported

For an object literal typed with @type, TypeScript reports the property that does not fit, not the whole object. For an assignment it reports the variable on the left. For a return it reports the returned expression. The examples show all three.

Gotchas

  • A cast (/** @type {number} */ (value)) silences the error only when the two types overlap; between unrelated types such as string and number the cast itself is an error (TS2352). Converting the value is almost always the better fix.
  • Missing or extra properties have their own messages: TS2741 and TS2739 for missing ones, TS2353 for unknown ones in an object literal.
  • When the value is a function argument the same mismatch is reported as TS2345 instead.

Questions

Why does my .js file get TS2322 when JavaScript allows any value anywhere?

Because the file is type-checked (checkJs or // @ts-check) and a JSDoc comment declared a type. Without the comment the variable's type is whatever it was first given, and later assignments of another type are reported the same way.

Sources

Last reviewed 20 October 2026.