Combining Known and Dynamic Keys
Mix fixed properties with index signatures safely.
Combining Known and Dynamic Keys is a free TypeScript Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Fixed Plus Flexible
Often an object has a few guaranteed properties plus an open-ended set of extras. TypeScript lets you declare named properties and an index signature in the same type — with one important constraint.
A Known Key Alongside a Signature
Here length is always present, while any other string key maps to a number. The named property and the index signature coexist.
interface NumberMap {
length: number
[key: string]: number
}
const m: NumberMap = { length: 2, a: 1, b: 1 }
console.log(m.length, m.a)The Compatibility Constraint
The catch: every fixed property's type must be assignable to the index signature's value type. The index signature is a promise about all keys, so each named key must honor it.
interface Valid {
id: number // ok: number matches the signature
[key: string]: number
}
const v: Valid = { id: 1, score: 99 }
console.log(v.id + v.score)When the Constraint Is Violated
If a fixed property's type does not match the index value type, TypeScript rejects it. A string-named property cannot live in a number-valued dictionary.
// interface Broken {
// name: string // Error: string not assignable to number
// [key: string]: number
// }Widening the Index Value Type
To allow mixed fixed-property types, widen the index signature to a union that covers them all. Now both a string name and numeric scores fit.
interface Record {
name: string
[key: string]: string | number
}
const r: Record = { name: "ana", score: 10 }
console.log(r.name, r.score)Optional Fixed Properties
Fixed properties can be optional with ?. They still must be compatible with the index signature when present.
interface Config {
id: string
label?: string
[key: string]: string | undefined
}
const c: Config = { id: "x" }
console.log(c.label) // undefinedWhy Optional Needs undefined
Because an optional property may be missing, its effective type includes undefined. The index signature must therefore also allow undefined, or TypeScript complains about the optional member.
interface Safe {
title?: string
[key: string]: string | undefined
}
const s: Safe = {}
for (const k in s) console.log(s[k])Different Value Types via Unions
A realistic settings object: a known boolean flag, a known string, and arbitrary extra values. The signature's union spans every fixed property type.
interface Settings {
enabled: boolean
theme: string
[key: string]: boolean | string
}
const s: Settings = { enabled: true, theme: "dark", lang: "en" }
console.log(s.enabled, s.lang)Number Index With Known Keys
The constraint applies to number index signatures too. A named numeric property must match the number index value type.
interface Sparse {
count: number
[index: number]: number
}
const sp: Sparse = { count: 1, 0: 100, 1: 200 }
console.log(sp.count, sp[0])A Cleaner Alternative
When the fixed keys and dynamic keys have genuinely unrelated types, consider splitting them: nest the dynamic part under its own property. This avoids forcing an awkward union.
interface Better {
name: string
scores: { [key: string]: number }
}
const b: Better = { name: "ana", scores: { math: 90 } }
console.log(b.name, b.scores.math)When to Combine
Combine known and dynamic keys when fixed properties naturally share the value type of the extras — counters with a total, settings of one kind with a couple of guaranteed flags. Otherwise, nesting keeps types honest.
interface Tally {
total: number
[bucket: string]: number
}
const t: Tally = { total: 0, a: 3, b: 5 }
t.total = t.a + t.b
console.log(t.total) // 8Quick Check
Test your understanding of mixing fixed and dynamic keys.
Recap
You can declare fixed properties and an index signature together, but each fixed property's type must be assignable to the index signature's value type. Widen the signature with a union to accommodate differing fixed-property types, and include undefined when fixed properties are optional. When types are truly unrelated, nest the dynamic portion under its own key instead.
Frequently asked questions
Is the “Combining Known and Dynamic Keys” lesson free?
Yes — the full text of “Combining Known and Dynamic Keys” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Combining Known and Dynamic Keys”?
Mix fixed properties with index signatures safely. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start TypeScript Academy?
No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Combining Known and Dynamic Keys” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this TypeScript Academy lesson?
Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Defining Index Signatures
- String vs Number Index Signatures
- Combining Known and Dynamic Keys
- Index Signatures vs Record