Dynamic Property Assignment in TypeScript: A Comprehensive Guide

The Problem with Dynamic Property Assignment

When working with objects in TypeScript, the type system determines the type of a variable at declaration time. This means that if we try to assign a property dynamically to an object, TypeScript will throw an error if the property does not exist on the object.

Solutions to Dynamic Property Assignment

There are several ways to achieve dynamic property assignment in TypeScript while maintaining type safety. Here are seven approaches:

  1. Explicitly Declare the Object TypeThis approach involves explicitly declaring the object type and all its properties upfront.
    interface Organization {
      name: string;
      address: string;
    }
    
    const organization: Organization = {
      name: 'Example Inc.',
      address: '123 Main St',
    };
  2. Use Object Index SignatureThis approach uses an object index signature, which allows us to define the type of keys and values for an object.
    interface Organization {
      [key: string]: string;
    }
    
    const organization: Organization = {
      name: 'Example Inc.',
      address: '123 Main St',
    };
  3. Use the Record Utility TypeWe can use the Record utility type to create an object type with specified keys and values.
    type Organization = Record<string, string>;
    
    const organization: Organization = {
      name: 'Example Inc.',
      address: '123 Main St',
    };
  4. Use the Map Data TypeThis approach uses the Map data type, which allows us to store key-value pairs.
    const organization = new Map<string, string>();
    organization.set('name', 'Example Inc.');
    organization.set('address', '123 Main St');
  5. Use Optional Object PropertiesWe can use optional object properties to achieve dynamic property assignment.
    interface Organization {
      name?: string;
      address?: string;
    }
    
    const organization: Organization = {
      name: 'Example Inc.',
    };
  6. Leverage Type AssertionsType assertions allow us to override the inferred type of a variable, making it possible to assign properties dynamically.
    interface Organization {
      name: string;
      address: string;
    }
    
    const organization = {} as Organization;
    organization.name = 'Example Inc.';
  7. Use the Partial Utility TypeWe can use the Partial utility type to make all properties of an object type optional.
    type Organization = {
      name: string;
      address: string;
    };
    
    const organization: Partial<Organization> = {
      name: 'Example Inc.',
    };

Comparing Approaches

Each approach has its pros and cons. The choice of approach depends on the specific use case and requirements.

  • Index/Key Signatures: Allow for dynamic property assignment, but may lead to unpredictable behavior if not used carefully.
  • Conditional/Optional Properties: Provide a way to assign properties conditionally, but may require additional checks for undefined values.

Recent Improvements to Index Access Handling

In TypeScript 5.5, a new improvement called “Control Flow Narrowing for Constant Indexed Accesses” was introduced, which narrows expressions of the form obj[key] when both obj and key are effectively constant.

const obj = { foo: 'bar' };
const key = 'foo';

if (typeof obj[key] === 'tring') {
  console.log(obj[key].toUpperCase()); // works
}

By understanding the different approaches to dynamic property assignment in TypeScript, developers can write more flexible and maintainable code while maintaining type safety.

Leave a Reply