# TypeScript Record Type: How to Build Dictionary Types with Mapped Types

> Learn how to build dictionary types in TypeScript using the built-in Record utility. Master homogenous dictionary structures for precise key value typing.

- Repository: [Microsoft/TypeScript](https://github.com/microsoft/typescript)
- Tags: deep-dive
- Published: 2026-02-11

---

**The TypeScript `Record` type is a built-in generic utility that constructs an object type where every key is drawn from a union type `K` and every value is strictly typed as `T`, effectively creating a homogenous dictionary structure.**

The TypeScript `Record` type provides a concise, declarative way to define object structures where properties share uniform value types. According to the microsoft/TypeScript source code, this utility is defined in the core library files and serves as a fundamental building block for type-safe lookup tables and mapped objects. Understanding how `Record` works under the hood helps developers leverage structural typing effectively while maintaining strict compile-time checks.

## What Is the TypeScript Record Type?

`Record<K, T>` creates an object type where each key comes from the union type `K` and each value must conform to type `T`. The type parameter `K` must extend `keyof any` (meaning `string`, `number`, or `symbol`), while `T` can be any valid TypeScript type.

Because `Record` is implemented as a **mapped type**, it behaves like any other object type in the type system. It participates in excess-property checking, works with `keyof` and lookup types, and follows structural assignability rules. This makes it especially useful for defining lookup tables, configuration dictionaries, and cache objects where consistency across all entries is required.

## How Record Is Defined in the TypeScript Source Code

In the microsoft/TypeScript repository, the `Record` type is declared in [`src/lib/es5.d.ts`](https://github.com/microsoft/TypeScript/blob/main/src/lib/es5.d.ts) at line 1595. The implementation uses a mapped type pattern:

```typescript
type Record<K extends keyof any, T> = {
    [P in K]: T;
}

```

This definition makes `Record` available globally without requiring any imports. The TypeScript compiler handles `Record` through standard mapped type mechanics in [`src/compiler/checker.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts), ensuring it follows the same structural compatibility rules as manually defined object types.

## Practical TypeScript Record Type Examples

### String-to-Number Dictionary

Create a simple lookup table mapping string keys to numeric values:

```typescript
type AgeMap = Record<string, number>;

const ages: AgeMap = {
  alice: 30,
  bob: 27,
  // carol: "thirty"   // Error: Type 'string' is not assignable to type 'number'
};

```

### Enum-Based Feature Flags

Use `Record` with enum keys to build type-safe configuration objects:

```typescript
enum Feature {
  Search = "search",
  Share = "share",
  Export = "export",
}

type FeatureFlags = Record<Feature, boolean>;

const flags: FeatureFlags = {
  [Feature.Search]: true,
  [Feature.Share]: false,
  [Feature.Export]: true,
};

```

### Union Keys with Complex Values

Map a union of role strings to arrays of user objects:

```typescript
type User = { id: number; name: string };
type UserRoles = "admin" | "editor" | "viewer";

type RoleAssignments = Record<UserRoles, User[]>;

const assignments: RoleAssignments = {
  admin: [{ id: 1, name: "Alice" }],
  editor: [{ id: 2, name: "Bob" }, { id: 3, name: "Carol" }],
  viewer: [], // Empty arrays satisfy the User[] type
};

```

### Generic Record Factory Function

Build a helper function that constructs a `Record` from runtime keys:

```typescript
function fromKeys<K extends keyof any, T>(
  keys: readonly K[], 
  value: T
): Record<K, T> {
  return keys.reduce((acc, key) => {
    acc[key] = value;
    return acc;
  }, {} as Record<K, T>);
}

const defaults = fromKeys(["host", "port"] as const, "");
// Type: Record<"host" | "port", string>

```

## Summary

- The TypeScript `Record<K, T>` utility creates object types with keys from union `K` and uniform values of type `T`, defined as `type Record<K extends keyof any, T> = { [P in K]: T }`.
- Defined in [`src/lib/es5.d.ts`](https://github.com/microsoft/TypeScript/blob/main/src/lib/es5.d.ts) as a mapped type, `Record` requires no imports and works globally across all TypeScript projects.
- The type parameter `K` must extend `keyof any` (accepting `string`, `number`, or `symbol`), while `T` can be any type.
- `Record` participates in excess-property checking and structural assignability like regular object types.
- Common use cases include enum-to-value mappings, dictionary types, and generic factory functions that build consistent object structures.

## Frequently Asked Questions

### What is the difference between Record and a regular index signature in TypeScript?

While functionally similar to `{ [key: string]: T }`, the `Record` utility provides a cleaner syntax that explicitly couples specific key unions to value types. The main distinction is that `Record` enforces that **all** values share exactly the same type `T`, whereas index signatures or interface definitions might allow more flexibility in value types across different keys.

### Can I use Record with optional properties?

No, the standard `Record` type does not support optional properties—all keys in union `K` must be present with a value of type `T`. If you need optional keys, use a custom mapped type with the `?` modifier: `{ [P in K]?: T }` instead of `Record<K, T>`.

### Where is the Record type defined in the TypeScript source code?

The `Record` type is declared in [`src/lib/es5.d.ts`](https://github.com/microsoft/TypeScript/blob/main/src/lib/es5.d.ts) at line 1595 within the microsoft/TypeScript repository. Additional type-checking logic that handles `Record` in structural compatibility checks resides in [`src/compiler/checker.ts`](https://github.com/microsoft/TypeScript/blob/main/src/compiler/checker.ts), while the public API surface exposes it through [`src/services/typescriptServices.ts`](https://github.com/microsoft/TypeScript/blob/main/src/services/typescriptServices.ts).

### Can Record keys be numbers or symbols?

Yes, because the constraint `K extends keyof any` accepts `string`, `number`, or `symbol`. You can create `Record<number, T>` for array-like objects or `Record<symbol, T>` for private property dictionaries, though string keys are the most common implementation in application code.