codewithjohn.dev
Published on

Quick Intro to Record Types in TypeScript

In TypeScript, a powerful language for building robust JavaScript applications, the Record<Keys, Type> utility type provides a versatile way to define objects with specific key and value types. This enhances code maintainability, readability, and type safety.

Key Concepts:

  • Keys: Represent the property names (identifiers) within the object. These can be strings, numbers, symbols, or even custom types.
  • Type: Specifies the data type allowed for the values associated with the keys. This can be any valid TypeScript type, including primitives, arrays, objects, or user-defined types.

Syntax:

type RecordType<Keys, Type> = {
  [key in Keys]: Type
}
  • RecordType: The name you assign to the newly created type.
  • <Keys>: Represents the type of the object's keys.
  • <Type>: Represents the type of the object's values.

Illustrative Examples:

  1. Simple String-Number Dictionary:
type ProductPrices = Record<string, number>

const prices: ProductPrices = {
  apple: 1.25,
  banana: 0.79,
  orange: 1.5,
}

const applePrice = prices['apple'] // Type safety ensures applePrice is a number

In this example, ProductPrices defines a type for an object where keys are strings (product names) and values are numbers (prices).

  1. Object as Values:
interface User {
  name: string
  email: string
}

type UserById = Record<string, User>

const users: UserById = {
  '1': { name: 'Alice', email: 'alice@example.com' },
  '2': { name: 'Bob', email: 'bob@example.com' },
}

const user1 = users['1'] // Type safety ensures user1 is of type User

Here, UserById creates a type for an object where keys are strings (user IDs) and values are objects of type User.

  1. Union Type for Keys:
type OrderStatus = 'pending' | 'shipped' | 'delivered'

type OrderDetails<T> = Record<OrderStatus, T>

const order1Details: OrderDetails<string> = {
  pending: 'Processing your order',
  shipped: 'Your order is on its way!',
  delivered: 'Order delivered!',
}

const order2Details: OrderDetails<number> = {
  pending: 1, // Key matches "pending", value is now a number
  shipped: 2,
  delivered: 3,
}

// Type safety ensures correct types based on the generic type parameter T

This example demonstrates a generic type OrderDetails that takes a type parameter T. The keys are restricted to the OrderStatus union type, while the values can be of any type specified by T. This allows flexibility while maintaining type safety.

Benefits of Record Types:

  • Improved Code Readability: Makes object structure and expected data types explicit.
  • Enhanced Type Safety: Catches potential type errors at compile time.
  • Increased Maintainability: Makes code easier to understand and modify.
  • Flexibility: Can be used with various key and value types.

By effectively utilizing Record types, you can create well-structured, type-safe, and maintainable TypeScript code.