Как можно вывести типы из свойства строки или массива строк - PullRequest
1 голос
/ 07 мая 2020

Для следующего сценария:

type Action =
| { type: 'FOO' }
| { type: 'BAR' }

type Rule = {
   target: string | string[],
   consequence: (action:Action) => void
}

const rule1:Rule = {
  target: 'FOO',
  consequence: action => console.log(action) // { type: 'FOO' }
}

const rule2:Rule = {
  target: ['FOO', 'BAR'],
  consequence: action => console.log(action) // { type: 'FOO' } | { type: 'BAR' }
}

Действие может быть отправлено (например, с помощью redux), и правило может на него реагировать. Когда цель соответствует action.type , то последствие выполняется с соответствующим действием.

The Question

Я хочу, чтобы правила последствие выводит правильный тип. Это можно как-то сделать с помощью target . Но я не знаю как. Мой текущий подход:

type Rule<Action> = {
  target: string | string[],
  consequence: (action:Action) => void
}
const rule:Rule<{ type: 'FOO' }> = ...

Но мне нужен способ, в котором я могу написать

const rule:Rule<{ type: 'FOO' } | { type: 'BAR' }> = ...

, и правильный тип будет определен правилами target

1 Ответ

0 голосов
/ 07 мая 2020

Это лучшее, что я мог придумать. Вам придется отказаться от target как отдельного значения и полагаться на то, что он всегда будет массивом, даже если этот массив имеет единственный элемент. Может быть способ заставить его работать с перегрузками функций, но я не мог заставить его работать.

type ActionType = "FOO" | "BAR";

type Action<T extends ActionType> = { type: T };

function createRule<T extends ActionType[]>(target: T) {
  return {
    target,
    consequence: (action: Action<T[number]>) => console.log(action)
  };
}

const foo = createRule(["FOO"]);
const bar = createRule(["FOO", "BAR"]);

foo.consequence({ type: "FOO" });
foo.consequence({ type: "BAR" }); // nope
bar.consequence({ type: "FOO" });
bar.consequence({ type: "BAR" });
bar.consequence({ type: "BAZ" }); // nope

https://codesandbox.io/s/dawn-wildflower-03cbq?file= / src / index.ts

Использование функции для создания правила позволяет вам использовать универсальные шаблоны без необходимости повторяться, определяя их как тип и значение каждый раз, когда вы создаете новое правило.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...