Home > Software design >  Typescript - How to create a type with the same properties as an interface, but with different prope
Typescript - How to create a type with the same properties as an interface, but with different prope

Time:02-12

I'm making a query builder. I have data models that look like this:

export interface SalesOrder {
  id: number
  customerName: string;
  date: Date;
}

In my query builder, I want to have the columns look something like this:

{
  id: 'salesOrder.id',
  customerName: 'customer.name',
  date: 'salesOrder.date',
}

I'm trying to figure out how I can type the Columns object generically so that it will have all the keys from the model, but all of the types will be a string. So then I would be able to declare it like const columns: Columns<SalesOrder> and it would understand that the object must have all the same keys as in the SalesOrder model, but with all the values being string.

I tried this:

export interface Columns<T> {
  [alias: keyof T]: string;
}

But it complains about the keyof T part, saying "An index signature parameter type must be either 'string' or 'number'."

CodePudding user response:

The end of that error message should have been:

Consider using a mapped object type instead.

See the documentation on mapped types.

Here's what that means:

export type Columns<T> = {
  [alias in keyof T]: string;
}

It needs to be a type, because this is actually a mapped type. It walks all possibilities of keyof T and evaluates each member of that union individually. This isn't really supported in interfaces.

And [key: MyType] is an index signature. It says that for any MyType there is a value of a consistent type. Where [key in MyType] define the keys of a mapped type.

Playground


Alternatively, you could try the Record type.

export type Columns<T> = Record<keyof T, string>

Playground

  • Related