Type expression

Indexed access types

  • Combining types
  • Tested with TypeScript 5.9

Order["status"] is the type of the status property of Order. It lets a function take exactly what a property holds without repeating its definition, so the two stay in step when Order changes.

Indexing with number gives the element type of an array: Order["lines"][number] is the type of one line. Combined with a const assertion, (typeof SIZES)[number] turns an array of values into a union type.

At a glance

Use JSDoc in a .js file TypeScript in a .ts file
One property's type /** @typedef {Order["status"]} OrderStatus */ type OrderStatus = Order["status"];
An array's element type /** @typedef {Order["lines"][number]} OrderLine */ type OrderLine = Order["lines"][number];
Elements of a const array /** @typedef {(typeof SIZES)[number]} Size */ type Size = (typeof SIZES)[number];

Examples

order.js order.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 {object} Order
 * @property {string} id
 * @property {"pending" | "shipped" | "delivered"} status
 * @property {{ sku: string, quantity: number }[]} lines
 */

/** @typedef {Order["status"]} OrderStatus */
/** @typedef {Order["lines"][number]} OrderLine */

/** @param {OrderStatus} status */
export function isOpen(status) {
  return status !== "delivered";
}

/** @param {OrderLine} line */
export function lineLabel(line) {
  return `${line.quantity} × ${line.sku}`;
}

isOpen("pending");
lineLabel({ sku: "TEE-01", quantity: 2 });
interface Order {
  id: string;
  status: "pending" | "shipped" | "delivered";
  lines: { sku: string; quantity: number }[];
}

type OrderStatus = Order["status"];
type OrderLine = Order["lines"][number];

export function isOpen(status: OrderStatus) {
  return status !== "delivered";
}

export function lineLabel(line: OrderLine) {
  return `${line.quantity} × ${line.sku}`;
}

isOpen("pending");
lineLabel({ sku: "TEE-01", quantity: 2 });
Indexed access: the type of one property.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
order.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: order.js(4,19): error TS2339: Property 'stauts' does not exist on type 'Order'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. order.js(4,19): error TS2339: Property 'stauts' does not exist on type 'Order'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. order.js(4,19): error TS2339: Property 'stauts' does not exist on type 'Order'. checked 21 October 2026
/** @typedef {{ id: string, status: string }} Order */

/** @param {Order["stauts"]} status */error TS2339: Property 'stauts' does not exist on type 'Order'.
export function isOpen(status) {
  return status !== "delivered";
}
Indexing a property that does not exist.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}
sizes.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: sizes.js(12,10): error TS2345: Argument of type '"XXL"' is not assignable to parameter of type '"S" | "M" | "L" | "XL"'. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. sizes.js(12,10): error TS2345: Argument of type '"XXL"' is not assignable to parameter of type '"S" | "M" | "L" | "XL"'. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. sizes.js(12,10): error TS2345: Argument of type '"XXL"' is not assignable to parameter of type '"L" | "M" | "S" | "XL"'. checked 21 October 2026
export const SIZES = /** @type {const} */ (["S", "M", "L", "XL"]);

/** @typedef {(typeof SIZES)[number]} Size */

/** @param {Size} size */
export function stockFor(size) {
  return SIZES.indexOf(size);
}

stockFor("XL");
stockFor("XXL");error TS2345: Argument of type '"XXL"' is not assignable to parameter of type '"S" | "M" | "L" | "XL"'.
The element type of a const array.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": ["*.js"]
}

The key is checked

The index must be a key of the type. Order["stauts"] is TS2339, reported on the JSDoc line, as the second example shows. That makes indexed access safer than copying a property's type by hand.

Values and their type from one list

const SIZES = /** @type {const} */ (["S", "M", "L", "XL"]) keeps the strings as literals, and (typeof SIZES)[number] is "S" | "M" | "L" | "XL". The array is used at run time (for a dropdown, say) and the type comes from it, so the list exists once.

Gotchas

  • The property name goes in quotes: Order["status"]. Order.status is not a type.
  • Indexing with a union, Order["id" | "status"], gives the union of those properties' types.

Questions

How do I get the type of an array element in JSDoc?

Index the array type with number: {Order["lines"][number]}, or {(typeof items)[number]} for an array value.

Sources

Last reviewed 20 October 2026.