TypeScript

TypeScript Record Utility: Everything You Need to Know

The TypeScript Record utility type is an effective and adaptable tool for building type-safe key-value mappings. It simplifies object definitions while also ensuring code consistency and type safety.

In this blog, we'll explore:

  1. What the Record utility type is.
  2. When and why to use it.
  3. Practical examples and advanced use cases.
  4. Best practices for using Record in your projects.

What is the Record Utility Type?

The Record utility type is a built-in TypeScript feature that lets you map a set of keys to a particular value type.

Record<Keys, ValueType>
  • Keys: Specifies the keys of the object, usually a string, number, or union of literals.
  • ValueType: Defines the type of the values associated with the keys.

When to Use the Record Type

  • Static Key-Value Mappings: For creating objects with fixed keys and uniform value types.
  • Enums or Literal Types as Keys: Ensures all keys from enums or literal unions are accounted for.
  • Simplify Object Type Definitions: Reduces verbosity when defining objects with consistent value types.

Basic Example of Record

The following is a method for generating a mapping of country codes to country names using Record:

const countries: Record<string, string> = {
  US: 'United States',
  CA: 'Canada',
  FR: 'France',
};

console.log(countries['US']); // Output: United States

Using Literal Types with Record

To improve type safety, utilize literal types to restrict the keys:

type CountryCode = 'US' | 'CA' | 'FR';

const countries: Record<CountryCode, string> = {
  US: 'United States',
  CA: 'Canada',
  FR: 'France',
};

console.log(countries.US); // Output: United States

The CountryCode type ensures that only the specified keys are allowed.

Using Enums with Record

Enums are an excellent fit for the Record type, ensuring that all enum values are present.

enum Role {
  Admin = 'admin',
  User = 'user',
  Guest = 'guest',
}

const roleDescriptions: Record<Role, string> = {
  [Role.Admin]: 'Full access to the system.',
  [Role.User]: 'Can view and edit their own data.',
  [Role.Guest]: 'Can only view public information.',
};

console.log(roleDescriptions[Role.Admin]); // Output: Full access to the system.

Nested Record Types

Record can be used to model complex structures by creating nested key-value mappings.

type ProductCategory = 'electronics' | 'clothing' | 'grocery';

const inventory: Record<ProductCategory, Record<string, number>> = {
  electronics: {
    laptop: 50,
    smartphone: 100,
  },
  clothing: {
    jeans: 200,
    tshirt: 300,
  },
  grocery: {
    apple: 500,
    milk: 100,
  },
};

console.log(inventory.electronics.laptop); // Output: 50

Dynamic Record Creation

Type-safe records can be created dynamically by combining Record with generics.

function createRecord<K extends string, V>(keys: K[], values: V[]): Record<K, V> {
  const record = {} as Record<K, V>;
  keys.forEach((key, index) => {
    record[key] = values[index];
  });
  return record;
}

const keys = ['apple', 'banana', 'cherry'];
const values = [1.2, 0.5, 2.3];

const priceLookup = createRecord(keys, values);
console.log(priceLookup.banana); // Output: 0.5

Using Record with Optional Keys

Combine Record with Partial to make keys optional:

type UserRoles = 'Admin' | 'User' | 'Guest';

const userPermissions: Partial<Record<UserRoles, string>> = {
  Admin: 'Full Access',
  User: 'Limited Access',
};

console.log(userPermissions.Guest); // Output: undefined

Common Use Cases for Record

  • Mapping Roles to Descriptions:
const roleDescriptions: Record<string, string> = {
  admin: 'Full access',
  user: 'Limited access',
  guest: 'Read-only access',
};
  • Theming in Applications:
type Theme = 'light' | 'dark';

const themeStyles: Record<Theme, string> = {
  light: 'background: white; color: black;',
  dark: 'background: black; color: white;',
};
  • API Endpoint Configuration:
const apiEndpoints: Record<'getUser' | 'getPosts', string> = {
  getUser: '/api/user',
  getPosts: '/api/posts',
};

Best Practices for Using Record

  • Prefer Literal or Enum Keys: Avoid using generic string or number keys unless necessary.
  • Combine with Utility Types: Use Partial, Pick, or Omit with Record for more flexibility.
  • Validate Data at Runtime: TypeScript types don’t exist at runtime, so validate external data before populating a Record.

About

At DevelopersMonk, we share tutorials, tips, and insights on modern programming frameworks like React, Next.js, Spring Boot, and more. Join us on our journey to simplify coding and empower developers worldwide!

Email: developersmonks@gmail.com

Phone: +23359*******

Quick Links

  • Home
  • About
  • Contact Us
  • Categories

  • Java
  • TypeScript
  • JavaScript
  • React
  • Nextjs
  • Spring Boot
  • DevOps