REUSABLE TYPES · LESSON 10 OF 24
keyof, typeof and indexed access
Derive property names and values from existing contracts.
- keyof
- typeof
- T[K]
- constraints
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
keyof produces a union of property keys. For a known object type it can stop misspelled property names before execution. Indexed access T[K] obtains the corresponding property value type.
The typeof type operator derives a type from a value declaration. It is used in a type position and differs from JavaScript typeof expressions, which return a runtime string.
A generic getter links the object, chosen key and result. K extends keyof T ensures the key belongs to the object. The result retains the particular property type instead of becoming a union of every field.
These operations help avoid duplicated declarations. They still do not validate a key arriving from a URL or JSON file; that string must be checked against permitted values at runtime.
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
const settings = { theme: "dark", pageSize: 20 };
type Settings = typeof settings;
type SettingKey = keyof Settings;
function get<T, K extends keyof T>(object: T, key: K): T[K] {
return object[key];
}
const key: SettingKey = "pageSize";
console.log(get(settings, key).toFixed(0));
console.log(get(settings, "theme").toUpperCase());
package.json
{
"name": "edupoly-typescript-keyof-typeof-indexed-access",
"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
{
"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
- Settings follows the fields of the actual settings object.
- The key selects a numeric return value in the first call.
- get(settings, "missing") is rejected before execution.
Expected result
20
DARK4. Practice independently
Write a generic setter that checks the property value too.
Show the explanation
Use function set<T, K extends keyof T>(object: T, key: K, value: T[K]): void { object[key] = value; }. set(settings, "pageSize", "large") must fail.
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.
