如何从字符串或字符串数​​组属性推断类型

时间:2020-05-06 21:29:22

标签: typescript

鉴于以下情况:

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 时,结果将与匹配的动作一起执行。

问题

我希望规则后果推断正确的类型。 目标可以通过某种方式完成此操作。但是我不知道如何。我目前的方法:

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 :(得分:0)

这是我能找出的最好的方法。您将不得不放弃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

使用函数创建规则可以使您使用泛型,而不必在每次创建新规则时都将其同时指定为类型和值,从而无需重复进行操作。