Можно ли преобразовать обобщенный тип в объединение - PullRequest
1 голос
/ 30 марта 2020

Скажите, пожалуйста, возможно ли вывести последний тип (Задачи), не задавая вручную значения c?

interface Action {
  move: number,
  eat: string
}

interface Task<A extends keyof Action> {
  action: A,
  value: Action[A],
}

type Tasks = Task<'move'> | Task<'eat'>;

Ответы [ 2 ]

1 голос
/ 30 марта 2020

Вы можете создать «надуманный» условный дистрибутивный тип , чтобы иметь тип объединения с Task для каждого ключа в Action. Таким образом, вам не нужно устанавливать Task<"move"> | ... | Task<"other Action keys"> вручную:

type DesiredTasks = keyof Action extends infer I ? I extends keyof Action ? Task<I> : never : never
// type DesiredTasks = Task<"move"> | Task<"eat"> 
// same as { action: "move"; value: number; } | { action: "eat"; value: string; }

Почему бы не Task<keyof Action>?

Все типы значений свойств объединены вместе, например, различимые типы объединений больше не будет работать:

type Tasks = Task<keyof Action> // {action: "move" | "eat"; value: string | number; }

declare const t1: Tasks
if (t1.action === "eat") t1.value // value: string | number, no good...

declare const t2: DesiredTasks
if (t2.action === "eat") t2.value // value: string ✔

Sample TS Playground

0 голосов
/ 30 марта 2020

Вы можете использовать оператор keyof в качестве обобщенного c в Task для создания типа объединения

type Tasks = Task<keyof Action>
...