Understanding TypeScript Record: The Ultimate Guide

Recently, I was working on a TypeScript project that required creating a flexible way to store key-value pairs with type safety. The issue is… many developers struggle with properly typing objects in TypeScript.

In this article, I’ll cover everything you need to know about the TypeScript Record utility type, with practical examples that will make your code more robust and maintainable. So let’s dive in!

What is a TypeScript Record?

Record is a built-in utility type in TypeScript that helps you define an object type with specific key types and value types. It creates an object type whose property keys are Keys and property values are Type.

The syntax looks like this:

Record<Keys, Type>

Where:

  • Keys can be a union of string literals or a string/number/symbol
  • Type can be any TypeScript type that you want your values to have

When to Use TypeScript Record

Below, I will explain some methods for using the TypeScript Record.

Method 1: Creating Objects with String Literal Keys

Let’s say we’re building a shopping application and want to store product prices:

type ProductNames = 'Ford' | 'Tesla' | 'Jeep';
type ProductPrices = Record<ProductNames, number>;

const prices: ProductPrices = {
  Ford: 1.99,
  Tesla: 0.99,
  Jeep: 2.49
};

console.log("Product Prices:", prices);

Now, TypeScript ensures that:

  1. You must include all the keys (‘Ford’, ‘Tesla’, ‘Jeep’)
  2. All values must be numbers
  3. You can’t add any extra keys that aren’t in the ProductNames type
Creating Objects with String Literal Keys in TypeScript

Method 2: Using Broader Key Types

Sometimes we need more flexibility with our keys:

// An object with string keys and boolean values
const userPermissions: Record<string, boolean> = {
  canEdit: true,
  canDelete: false,
  canCreate: true
};

// Add new permissions anytime
userPermissions.canPublish = true;

// Console log to display current permissions
console.log("User Permissions:", userPermissions);

Since we used string as our key type, we can add any string key we want.

Use Broader Key Types with TypeScript Records

Method 3: Creating Dictionaries or Maps

The record is perfect for dictionary-like structures:

type UserId = string;
type UserData = { name: string; email: string; lastLogin: Date };

const userDatabase: Record<UserId, UserData> = {
  'user_123': {
    name: 'John Smith',
    email: 'john@example.com',
    lastLogin: new Date()
  },
  'user_456': {
    name: 'Sarah Jones',
    email: 'sarah@example.com',
    lastLogin: new Date()
  }
};

This pattern is incredibly useful for any lookup table or cache.

TypeScript Record Creating Dictionaries or Maps

Record vs. Interface vs. Type in TypeScript

When should you use Record instead of defining a regular interface or type alias? Here’s a quick comparison:

// Using Record
type UserRoles = Record<string, string[]>;

// Using interface
interface UserRoles {
  [username: string]: string[];
}

// Using type with index signature
type UserRoles = {
  [username: string]: string[];
};

The main advantages of Record:

  1. It’s more concise and expressive
  2. It works great with mapped types and other type utilities
  3. It clearly communicates your intent to other developers

I use Record when I need a quick way to define a dictionary-like structure with consistent value types.

Advanced Usage of Records in TypeScript

Method 4: Combining with Other Utility Types

Record becomes really powerful when combined with other TypeScript utility types:

type User = {
  id: number;
  name: string;
  email: string;
  isAdmin: boolean;
};

// Create a record of users with only public information
type PublicUser = Pick<User, 'id' | 'name'>;

const userDirectory: Record<number, PublicUser> = {
  1: { id: 1, name: 'John Smith' },
  2: { id: 2, name: 'Jane Doe' }
};

// Console log to display the user directory
console.log("User Directory:", userDirectory);
TypeScript Record Combining with Other Utility Types

Method 5: Using a Record for API Responses in TypeScript

When working with APIs, I often use Record to type responses that return collections:

type ApiResponse<T> = {
  data: T;
  status: number;
  message: string;
};

// For a single user
type UserResponse = ApiResponse<User>;

// For a collection of users
type UsersResponse = ApiResponse<Record<string, User>>;

// Example response
const response: UsersResponse = {
  data: {
    'user_1': { id: 1, name: 'John', email: 'john@example.com', isAdmin: false },
    'user_2': { id: 2, name: 'Jane', email: 'jane@example.com', isAdmin: true }
  },
  status: 200,
  message: 'Success'
};
Use a Record for API Responses in TypeScript

Real-World Examples in TypeScript Record

State Management in TypeScript

The record is excellent for state management in React applications:

type FormState = Record<string, string | boolean | number>;

const initialState: FormState = {
  name: '',
  email: '',
  age: 0,
  subscribe: false
};

function updateForm(state: FormState, field: string, value: string | boolean | number): FormState {
  return {
    ...state,
    [field]: value
  };
}

// Update form state example
const updatedState = updateForm(initialState, 'name', 'John Doe');

// Console log to display initial and updated form states
console.log("Initial Form State:", initialState);
console.log("Updated Form State:", updatedState);
TypeScript Record Explained

Best Practices When Using Record

  1. Be specific with key types when possible, use string literal unions instead of string when you know all possible keys.
  2. Consider read-only records for immutability
   type ReadOnlyConfig = Readonly<Record<string, string>>;
  1. Use with caution for empty objects
   // This allows any property
   const obj: Record<string, unknown> = {};

   // This is more specific and safer
   const obj: Record<'id' | 'name', string> = { id: '1', name: 'John' };

Conclusion

I hope you found this article helpful! The TypeScript Record utility type is one of those features that seems simple at first but becomes increasingly valuable as your projects grow in complexity.

It helps you maintain type safety when working with dynamic objects and key-value collections, which is essential for building robust applications.

Other TypeScript articles you may also like:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.