Type expression

typeof in types

  • Combining types
  • Tested with TypeScript 5.9

Inside a type, typeof name means "the type of the value called name". {Partial<typeof defaults>} reuses the shape of a settings object as the type of its overrides, so adding a setting to defaults updates the parameter type too. A wrong value type in the overrides is still TS2322, as the first example shows.

This is a type operator, not JavaScript's run-time typeof, which returns a string such as "object". The two share a keyword and nothing else.

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
The type of a value /** @param {Partial<typeof defaults>} overrides */ (overrides: Partial<typeof defaults>)
The type of a function /** @type {typeof formatPrice} */ : typeof formatPrice

Examples

config.js config.ts Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: config.js(17,12): error TS2322: Type 'string' is not assignable to type 'number'. config.ts(13,12): 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. config.js(17,12): error TS2322: Type 'string' is not assignable to type 'number'. config.ts(13,12): 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. config.js(17,12): error TS2322: Type 'string' is not assignable to type 'number'. config.ts(13,12): error TS2322: Type 'string' is not assignable to type 'number'. checked 21 October 2026
const defaults = {
  currency: "USD",
  pageSize: 24,
  showOutOfStock: false,
};

/**
 * @param {Partial<typeof defaults>} overrides
 * @returns {typeof defaults}
 */
export function settings(overrides) {
  return { ...defaults, ...overrides };
}

settings({ pageSize: 48 });
settings({ pageSize: "48" });error TS2322: Type 'string' is not assignable to type 'number'.
const defaults = {
  currency: "USD",
  pageSize: 24,
  showOutOfStock: false,
};

export function settings(overrides: Partial<typeof defaults>): typeof defaults {
  return { ...defaults, ...overrides };
}

settings({ pageSize: 48 });
settings({ pageSize: "48" });error TS2322: Type 'string' is not assignable to type 'number'.
Reusing the type of a value with typeof.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
format.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
/**
 * @param {number} amount
 * @param {string} [currency]
 */
export function formatPrice(amount, currency = "USD") {
  return new Intl.NumberFormat("en-US", { style: "currency", currency }).format(amount);
}

/** @type {typeof formatPrice} */
export const formatEuro = (amount, currency = "EUR") => formatPrice(amount, currency);

formatEuro(19.5);
The type of a function, without writing it twice.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
config.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: config.js(4,19): error TS2693: 'Settings' only refers to a type, but is being used as a value here. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. config.js(4,19): error TS2693: 'Settings' only refers to a type, but is being used as a value here. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. config.js(4,19): error TS2693: 'Settings' only refers to a type, but is being used as a value here. checked 21 October 2026
/** @typedef {{ currency: string }} Settings */

/** @type {typeof Settings} */error TS2693: 'Settings' only refers to a type, but is being used as a value here.
const settings = { currency: "USD" };

export { settings };
typeof needs a value, not a type.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

It takes a value

typeof must be followed by a value. A @typedef name is a type, so {typeof Settings} is TS2693 ("'Settings' only refers to a type, but is being used as a value here"), as the third example shows. A class name works either way: {Cart} is the instance type, {typeof Cart} the class itself with its constructor and static members.

Value names without typeof in a .js file

In a .js file TypeScript also accepts a value's name in a JSDoc type and uses the value's type: {defaults} means the same as {typeof defaults}, and ReturnType<createCart> works without the typeof. A .ts file rejects both (TS2749). Writing typeof keeps the JSDoc valid TypeScript and makes the intent clear; the ReturnType page shows the difference side by side.

Gotchas

  • typeof captures the widened type of a let or a mutable object property (string, not "USD"). Use a const assertion on the value to keep literal types.
  • typeof import("./config.js") gives the type of a whole module.

Questions

How do I get the type of a variable in JSDoc?

Write typeof and the variable's name inside the braces: /** @type {typeof defaults} */.

Sources

Last reviewed 20 October 2026.