Andrew Floatrx
Andrew Floatrx

Reputation: 145

Typescript dynamic type depends on value (generic)

Is it possible get dynamic type depended on value of key dataIndex (create dynamic discriminating union type with generic)?

type EntityList<EntityType> = {
  dataIndex: keyof EntityType;
  render?: (value: any /*bad*/, record: EntityType) => void;
}[]

// Some dynamic type
type Issue = {
  id: number;
  name: string;
  description?: string;
  flag?: boolean;
};

const arr:EntityList<Issue> = [
  { dataIndex: 'id', render: (id, record) => { 
    console.log({id, record}); } // id should be number
  }, 

  { dataIndex: 'name', render: (name, record) => { 
    console.log({name, record}); } // name should be string
  }, 

  { dataIndex: 'flag', render: (flag, record) => { 
    console.log({flag, record}); } // flag should be boolean
   }, 
]

answer:

type EntityList<EntityType> = {
  [K in keyof EntityType]: {
    dataIndex: K, 
    render?: (value: EntityType[K], record: EntityType) => void
  }
}[keyof EntityType][]

thanks @Tobias S.

Upvotes: 2

Views: 234

Answers (1)

Tobias S.
Tobias S.

Reputation: 23925

This should work for you:

type EntityList<EntityType> = {
  [K in keyof Issue]: {
    dataIndex: K, 
    render?: (value: Issue[K], record: EntityType) => void
  }
}[keyof Issue][]

We create a mapped type and iterate over all keys of Issue. Afterwards we convert this type to a union of all possible combinations with [keyof Issue].

Playground

This does not quite match your requirement since you wanted flag to be of type boolean. But since the flag property is optional the type is boolean | undefined. To fix this, add -?:

type EntityList<EntityType> = {
  [K in keyof Issue]-?: {
    dataIndex: K, 
    render?: (value: Issue[K], record: EntityType) => void
  }
}[keyof Issue][]

Upvotes: 2

Related Questions