How dynamically infer the key of a TypeScript object

December 12, 2024

With TypeScript you can dynamically infer the key of a TypeScript object, using the keyof operator.

interface Fields {
  name: string
  age: number
  address: {
    city: string
    street: string
  }
}

interface ColumnBase<Data, Field extends keyof Data> {
  field: Field
  header: string
  render?: (fieldValue: Data[Field]) => string
}

// Infer the type for each field in the Data structure.
type Column<Data> = {
  [K in keyof Data]: ColumnBase<Data, K>
}[keyof Data]

const columns: Column<Data>[] = [
  {
    field: 'name',
    header: 'Name',
    // Because the 'field' is 'name'
    // the type of the fieldValue is string.
    render: (fieldValue) => fieldValue
  },
  {
    field: 'age',
    header: 'Age',
    // Because the 'field' is 'age'
    // the type of the fieldValue is number.
    render: (fieldValue) => fieldValue.toString()
  },
  {
    field: 'address',
    header: 'City',
    // Because the 'field' is 'address'
    // the type of the fieldValue is { city: string, street: string }.
    render: (fieldValue) => fieldValue.city
  },
  {
    field: 'address',
    header: 'Street',
    // Because the 'field' is 'address'
    // the type of the fieldValue is { city: string, street: string }.
    render: (fieldValue) => fieldValue.street
  }
]