Enforce the name of an interface field must equal value of another field

时间:2019-03-19 14:52:57

标签: typescript

I have an interface as follows:

export interface DashboardRequest {
  name: string;
  type: string;
  [key:string]: any;
}

I was wondering if its possible to enforce that the field name of my third dynamic keyed field must be equal to whatever the value is for the type field?

e.g

const request:DashboardRequest = {
  name: 'foo';
  type: 'bar;
  bar: 5;
}

Is this possible?

1 个答案:

答案 0 :(得分:4)

I feel like there must be a better way, but I was able to get something along the lines of what you need in this manner:

type DashboardRequest<T extends string> = {
  name: string;
  type: T;
} & { [K in T]: any }

// annoying that you need to pass the type argument here :(
const request: DashboardRequest<'bar'> = {
  name: 'foo',
  type: 'bar',
}
// Compiler error:
//   Property 'bar' is missing in type '{ name: string; type: "bar"; }'
//   but required in type '{ bar: any; }'.


// Edit:
//   Thanks to Titian Cernicova-Dragomir for the idea to use a helper 
//   function to avoid needing to specify the type manually 
const DashboardRequest = {
  create: <T extends string>(o: DashboardRequest<T>) => o
}

// this also gives the correct compiler error
const req = DashboardRequest.create({ name: 'foo', type: 'bar' })