Skip to content

FOUNDATIONS · LESSON 3 OF 24

Arrays, tuples and readonly collections

Model a sequence, a fixed-position record, and a read-only view.

  • arrays
  • tuples
  • readonly
  • undefined

Your runnable checkpoint

Extract into a new practice folder. Each download includes complete source, package.json, tsconfig.json and an offline lesson. Use Node.js 22 or 24. Each checkpoint is independent.

Install with npm install. Run npm run check, then npm run build. Terminal lessons use npm start; browser lessons use npm run serve and http://127.0.0.1:4173.

1. Understand the concepts

number[] describes a variable-length sequence of numbers. A tuple such as [string, number] describes positions with different meanings. Prefer a named object when many positions would be hard to remember.

noUncheckedIndexedAccess makes an arbitrary array lookup possibly undefined. An empty array has no first item. Handle that case instead of assuming that scores[0] exists.

readonly number[] prevents mutation through that reference. It does not freeze the runtime array and does not stop a different mutable reference from changing it. A readonly tuple also prevents assignment to its positions.

map transforms each element and infers its callback parameter. Destructuring a known tuple preserves the type of each position, unlike indexing an arbitrary array.

2. Build and run

These are complete files. Preserve the paths shown below, including the src directory. The package and compiler configuration are included at the end.

src/main.ts

src/main.ts
const scores: number[] = [72, 88, 95];
const student: readonly [name: string, score: number] = ["Asha", 88];
function average(values: readonly number[]): number | undefined {
  if (values.length === 0) return undefined;
  return values.reduce((sum, value) => sum + value, 0) / values.length;
}
const [name, score] = student;
console.log(`${name}: ${score}`);
console.log(scores.map(value => value + 1).join(", "));
console.log(average([]) ?? "No scores");

package.json

package.json
{
  "name": "edupoly-typescript-arrays-tuples-and-readonly",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "check": "tsc --noEmit",
    "build": "tsc",
    "start": "node dist/main.js"
  },
  "devDependencies": {
    "typescript": "5.9.3"
  }
}

tsconfig.json

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": [
      "ES2022",
      "DOM"
    ],
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "exactOptionalPropertyTypes": true,
    "noEmitOnError": true,
    "verbatimModuleSyntax": true,
    "rootDir": "src",
    "outDir": "dist",
    "sourceMap": true,
    "types": [],
    "moduleDetection": "force"
  },
  "include": [
    "src/**/*"
  ]
}

3. Trace the code and check the result

  1. The tuple labels document each position without creating runtime property names.
  2. The empty-array branch avoids dividing by zero.
  3. The nullish fallback is used only for undefined or null.

Expected result

Asha: 88
73, 89, 96
No scores

4. Practice independently

Return the first score safely without a non-null assertion.

Show the explanation

Use function first(values: readonly number[]): number | undefined { return values[0]; }. Let the caller handle undefined.

When something goes wrong

If tsc is missing, run npm install in the folder containing package.json. If the output looks old, rebuild before running. Read the first compiler diagnostic and check the indicated field or argument. For module errors, preserve the .js extensions in imports. Browser examples must run through the included local server, not directly as TypeScript files.

Read the related official TypeScript documentation ↗