TypeScript 无法使用 keyof 作为属性从泛型正确推断类型

时间:2021-04-30 16:02:44

标签: typescript typescript-generics

我目前正在为验证组件编写一些 typedef 和类,该组件正在构建以验证特定类(下面的“Main”)上的字段。目标:

  1. 每个验证规则 (MainValidationRule) 应包含它正在验证的密钥 (T extends keyof Main),以及验证相应值并返回指示有效性标志的验证函数 ({{1} }).
  2. 为了便于使用验证器,在运行时,验证规则数组将组合成一个对象,将每个字段 ((value: Main[T]) => boolean) 映射到该字段的所有验证规则数组 ({{1} }).

但是,当我尝试将规则映射到所需的结构化(下面的代码)时,TypeScript 给出了类型错误:

Image of type error

我会假设,因为 T in keyof Main 的任何给定值都保证 Array<MainValidationRule<T>> 将满足约束(即我们知道如果 rule.key,那么 rule 将满足类型 rule.key === 'foo',同样适用于 'bar' 或任何其他可能添加到 rule 的键),这将编译正常。但是,TypeScript 似乎正在检查 MainValidationRule<'foo'>所有 可能的值是否是特定 键的有效规则,它失败了(例如){{1}如果键是 Main,} 不是有效规则 - 尽管事实上我们的约束意味着这永远不可能。

我做错了吗?或者有没有另一种方法可以让 TypeScript 正确推断约束得到满足? MainValidationRule<keyof Main> 类经常使用新属性更新,因此手动输入并检查每个可能的变化是不切实际的。代码如下。提前致谢!

MainValidationRule<'bar'>

1 个答案:

答案 0 :(得分:1)

有时最好使用联合类型而不是 Foo<keyof Bar>

为了清楚起见,只需比较我的 MainValidationRuleMainValidationRule<keyof Main>

看起来他们是平等的,但事实并非如此。

对于 TS,推断简单联合类型要容易得多。

代码如下:

type Main = {
  foo: string;
  bar: number;
};

type Values<T> = T[keyof T]

type MainValidationRule = Values<{
  [P in keyof Main]: {
    key: P;
    isValid: (value: Main[P]) => boolean;
  }
}>

type Rules = Array<MainValidationRule>


type MainValidationRulesMap = Partial<{ [T in keyof Main]: Rules }>;

const mainValidationRulesMap: MainValidationRulesMap = {};

const mainValidationRules: Rules = [];

mainValidationRules.forEach(rule => {
  mainValidationRulesMap[rule.key] = [rule]; // ok
});

Playground