Type expression

keyof

  • Combining types
  • Tested with TypeScript 5.9

keyof T is the union of the property names of T. For { sku: string, name: string, price: number }, keyof gives "sku" | "name" | "price", so a parameter typed {keyof Product} accepts only those strings and rejects a typo like "prise" (TS2345).

For the keys of an object you have as a value, not as a type, combine it with typeof: {keyof typeof LABELS}.

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
The keys of a type /** @param {keyof Product} field */ (field: keyof Product)
The keys of a value /** @typedef {keyof typeof LABELS} Column */ type Column = keyof typeof LABELS;

Examples

sort.js sort.ts 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 */

/**
 * @param {Product[]} products
 * @param {keyof Product} field
 */
export function sortBy(products, field) {
  return [...products].sort((a, b) => String(a[field]).localeCompare(String(b[field])));
}

/** @type {Product[]} */
const products = [{ sku: "TEE-01", name: "Cotton tee", price: 19.5 }];
sortBy(products, "name");
type Product = { sku: string; name: string; price: number };

export function sortBy(products: Product[], field: keyof Product) {
  return [...products].sort((a, b) => String(a[field]).localeCompare(String(b[field])));
}

const products: Product[] = [{ sku: "TEE-01", name: "Cotton tee", price: 19.5 }];
sortBy(products, "name");
keyof Product: one of Product's property names.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
sort.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: sort.js(9,8): error TS2345: Argument of type '"prise"' is not assignable to parameter of type 'keyof Product'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. sort.js(9,8): error TS2345: Argument of type '"prise"' is not assignable to parameter of type 'keyof Product'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. sort.js(9,8): error TS2345: Argument of type '"prise"' is not assignable to parameter of type 'keyof Product'. checked 21 October 2026
/** @typedef {{ sku: string, name: string, price: number }} Product */

/** @param {keyof Product} field */
export function column(field) {
  return field;
}

column("prise");error TS2345: Argument of type '"prise"' is not assignable to parameter of type 'keyof Product'.
A key that is not a property name.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
labels.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: labels.js(16,9): error TS2345: Argument of type '"stock"' is not assignable to parameter of type '"sku" | "name" | "price"'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. labels.js(16,9): error TS2345: Argument of type '"stock"' is not assignable to parameter of type '"sku" | "name" | "price"'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. labels.js(16,9): error TS2345: Argument of type '"stock"' is not assignable to parameter of type '"name" | "price" | "sku"'. checked 21 October 2026
const LABELS = {
  sku: "SKU",
  name: "Product name",
  price: "Price",
};

/** @typedef {keyof typeof LABELS} Column */

/** @param {Column} column */
export function heading(column) {
  return LABELS[column];
}

heading("price");
heading("stock");error TS2345: Argument of type '"stock"' is not assignable to parameter of type '"sku" | "name" | "price"'.
keyof typeof: the keys of an object value.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

With generics

keyof is most useful as a constraint: @template T with @template {keyof T} K lets a function take an object and one of its keys, and return T[K], the type of that property. The generic constraints page has that example.

Types with index signatures

For Record<string, number>, keyof is string (and number, since numeric keys are strings in JavaScript), so it no longer limits anything. keyof is precise only for types with known property names.

Gotchas

  • keyof of a union gives only the keys every member shares.
  • Inside the function, a[field] has the union of all property types; narrow it or use the generic form when you need the exact one.

Questions

How do I accept only the property names of an object type in JSDoc?

Type the parameter as {keyof YourType}. For an object value, use {keyof typeof yourObject}.

Sources

Last reviewed 20 October 2026.