Home > Back-end >  Typescript create type that uses other field in a dynamic way
Typescript create type that uses other field in a dynamic way

Time:12-06

There's a couple of questions related to this but none I could find that match my requirements.

I wish to create a factory that, based on the type, requires a factory for each key of that object that contains the value and the entire object. For example:

type Row = {
  foo: string
  bar: number
  baz: unknown
}

const factory: MyMagicType<Row> = [{
  field: 'foo',
  // Infers value as string
  factory: (value, obj) => ..
}, {
  field: 'bar',
  // Infers value as number
  factory: (value, obj) => ..
}]
^also throws that 'baz' hasn't been populated

I have tried using generics for this but got stuck.

type MyMagicType<TObj extends Record<string, unknown>, TField extends keyof TObj> {
  field: TField,
  factory: (val: TObj[TField], source: TObj) => any
}[]

But this doesn't work due to the field needing to be inferred rather than passed into the generic.

How can I omit the TField but still let it infer from field?

CodePudding user response:

Not sure how you want to type the second parameter and the return value of your factory functions, but here is a possible implementation of MyMagicType that types the first parameter correctly:

type Row = {
  foo: string
  bar: number
  baz: unknown
};

type MyMagicType<T extends object> = Array<{
  [K in keyof T]: {
    field: K,
    factory: (value: T[K], obj: any) => any,
  }
}[keyof T]>;

const factory: MyMagicType<Row> = [{
  field: 'foo',
  // Infers value as string
  factory: (value, obj) => undefined
}, {
  field: 'bar',
  // Infers value as number
  factory: (value, obj) => undefined
}];

TypeScript playground

  • Related