繁体   English   中英

TypeScript 未能使用 keyof 作为属性从泛型中正确推断类型

[英]TypeScript failing to correctly infer types from generic using keyof as property

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

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

但是,当我尝试将 map 规则转换为所需的结构(代码如下)时,TypeScript 给出了类型错误:

类型错误的图像

我会假设,因为rule.key的任何给定值都保证rule将满足约束(即,我们知道如果rule.key === 'foo' ,那么rule将满足MainValidationRule<'foo'>类型, 'bar' 或可能添加到Main的任何其他键也是如此),这将编译得很好。 但相反,TypeScript 似乎正在检查MainValidationRule<keyof Main>所有可能值是否是特定键的有效规则,如果键是'foo' ,则失败,例如MainValidationRule<'bar'>不是有效规则'foo' - 尽管我们的限制意味着这永远不可能。

难道我做错了什么? 还是有另一种方法可以写出这会导致 TypeScript 正确推断出满足约束? Main class 经常更新新属性,因此手动输入并检查每个可能的变化是不切实际的。 代码如下。 提前致谢!

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

type MainValidationRule<T extends keyof Main> = {
    key: T;
    isValid: (value: Main[T]) => boolean;
};

type MainValidationRulesMap = { [ T in keyof Main ]?: Array<MainValidationRule<T>> };
const mainValidationRulesMap: MainValidationRulesMap = {};
const mainValidationRules: Array<MainValidationRule<keyof Main>> = [];

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

有时最好使用联合类型而不是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
});

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM