Question
Understanding TypeScript Record<K, T>: Definition, Usage, and Examples
Question
In TypeScript, what does Record<K, T> mean?
TypeScript 2.1 introduced the Record utility type. One example often shown is:
function mapObject<K extends string, T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U>
The Advanced Types documentation also shows Record as a mapped type:
type Record<K extends string, T> = {
[P in K]: T;
}
Unlike Readonly, Partial, and Pick, Record is not homomorphic because it does not copy properties from an existing type. For example:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
Based on this, I want to understand the following clearly:
- What is a simple definition of
Record? - Does
Record<K, T>mean that all properties on the object have typeT? - What role does
Kplay exactly? - Does
Kprevent additional keys that are not listed inK, or can other keys still exist? - Is this type:
type ThreeStringProps = Record<'prop1' | 'prop2' | 'prop3', string>
exactly the same as this?
type ThreeStringProps = {
prop1: string;
prop2: string;
prop3: string;
}
Short Answer
By the end of this page, you will understand that Record<K, T> is a TypeScript utility type for building an object type whose keys come from K and whose values all have type T. You will also see how it compares to writing object types by hand, how extra keys behave, and when Record is useful in real code.
Concept
Record<K, T> is a utility type that creates an object type.
Its meaning is:
- use the set of property names in
K - for each of those property names, assign the value type
T
The common mental reading is:
"An object with keys
K, where every listed key stores a value of typeT."
The core definition is:
type Record<K extends keyof any, T> = {
[P in K]: T;
}
A simpler form is often shown as:
type Record<K extends string, T> = {
[P in K]: T;
}
What K does
K is the set of allowed property names that this type will create.
For example:
Mental Model
Think of Record<K, T> like making a row of labeled storage boxes.
Kis the list of labels to print on the boxesTis the kind of item each box is allowed to hold
Example:
Record<'name' | 'email' | 'city', string>
This means:
- make a box labeled
name - make a box labeled
email - make a box labeled
city - every box must contain a
string
So it is like a template for an object shape.
If you try to put a number into one of those boxes, TypeScript complains. If you forget one of the required boxes, TypeScript complains. If you add an unexpected box in a direct object literal, TypeScript often complains too.
Syntax and Examples
Core syntax
Record<K, T>
K= the property namesT= the type for each property value
Basic example
type Settings = Record<'theme' | 'language', string>;
const appSettings: Settings = {
theme: 'dark',
language: 'en'
};
This is the same as:
type Settings = {
theme: string;
language: string;
};
Number values example
type Scores = Record<'alice' | 'bob', number>;
: = {
: ,
:
};
Step by Step Execution
Consider this example:
type Fields = Record<'firstName' | 'lastName', string>;
const person: Fields = {
firstName: 'Ada',
lastName: 'Lovelace'
};
Step 1: Evaluate the keys
K is:
'firstName' | 'lastName'
That means the object type must include these two properties.
Step 2: Evaluate the value type
T is:
string
That means each property created from K must have a string value.
Step 3: Expand the mapped type mentally
TypeScript treats this roughly like:
type Fields = {
: ;
: ;
}
Real World Use Cases
Lookup tables
type Route = 'home' | 'about' | 'contact';
const paths: Record<Route, string> = {
home: '/',
about: '/about',
contact: '/contact'
};
Useful when an app has a fixed set of route names.
Status labels
type Status = 'idle' | 'loading' | 'success' | 'error';
const labels: Record<Status, string> = {
idle: 'Idle',
loading: 'Loading...',
success: 'Success',
error: 'Error'
};
This ensures every status has a label.
Feature flags
Real Codebase Usage
In real TypeScript projects, Record is often used when developers want a key-to-value mapping with known keys.
Common patterns
Configuration objects
type Environment = 'development' | 'production';
const apiBaseUrl: Record<Environment, string> = {
development: 'http://localhost:3000',
production: 'https://api.example.com'
};
Enum-like mappings
type Role = 'admin' | 'user' | 'guest';
const permissions: Record<Role, number> = {
admin: 3,
user: 2,
guest: 1
};
Validation result storage
= | ;
(): <, > {
{
: values..() ? : ,
: values.. >= ? :
};
}
Common Mistakes
1. Thinking Record<K, T> means any string key
Broken assumption:
type Person = Record<'name' | 'email', string>;
This does not mean all string keys are allowed. It specifically creates name and email.
To represent arbitrary string keys, use:
type StringMap = Record<string, string>;
2. Forgetting required keys
Broken code:
type Config = Record<'host' | 'port', string>;
const config: Config = {
host: 'localhost'
};
Problem:
portis required but missing
Comparisons
Record vs manually written object type
| Approach | Example | Best when |
|---|---|---|
Record | `Record<'a' | 'b', number>` |
| Manual object type | { a: number; b: number } | keys are few or value types differ |
Record vs index signature
| Feature | Record<'a' | 'b', number> | { [key: string]: number } |
|---|---|---|
| Key set known ahead of time | Yes | No |
| Requires specific keys | Yes |
Cheat Sheet
Quick definition
type X = Record<K, T>
Creates an object type with:
- keys from
K - values of type
T
Expansion rule
Record<'a' | 'b', number>
becomes:
{
a: number;
b: number;
}
When to use it
Use Record when:
- you know the keys ahead of time
- all those keys have the same value type
Common examples
type Labels = Record<'save' | 'cancel', string>;
type Flags = Record< | , >;
= < | , >;
FAQ
What is Record<K, T> in TypeScript?
It is a utility type that creates an object type with keys from K and values of type T.
Is Record<'a' | 'b', string> the same as { a: string; b: string }?
Yes. In practice, those two types are equivalent.
What does the K in Record<K, T> represent?
K represents the property names, usually as a union such as 'a' | 'b' | 'c'.
Does Record allow extra properties?
Direct object literals usually get an error for extra properties. But values stored in variables may still be assignable if they include the required keys.
Does Record<K, T> mean every property on the object must be type T?
It means every property listed in K must have type T. It does not globally describe every possible property in every situation.
When should I use Record instead of a normal object type?
Mini Project
Description
Create a small status-message dictionary for an application. This project shows how Record can guarantee that every allowed status has a message and that every message has the same value type.
Goal
Build a type-safe object that maps app statuses to user-facing messages using Record.
Requirements
- Define a union type for the allowed statuses.
- Create a
Recordtype that maps each status to a string message. - Create an object that satisfies the type.
- Write a function that accepts a status and returns the corresponding message.
Keep learning
Related questions
Angular formGroup Error Explained: Fixing 'Can't bind to formGroup' in Reactive Forms
Learn why Angular shows 'Can't bind to formGroup' and how to fix it by importing ReactiveFormsModule correctly.
Fix "Element implicitly has an 'any' type" in TypeScript Object Indexing
Learn why TypeScript rejects string object indexing and how to fix it with keyof, unions, and typed object keys in React.
Fix "Property has no initializer" in Angular TypeScript Components
Learn why Angular TypeScript shows "Property has no initializer" and how to fix it using defaults, optional properties, or definite assignment.