[英]Declare a constructor to correctly infer generic type from (keyof) argument in TypeScript
[英]TypeScript failing to correctly infer types from generic using keyof as property
我目前正在为验证组件编写一些 typedef 和类,该组件正在构建以验证特定 class (下面的“主要”)上的字段。 目标:
MainValidationRule
) 应包含它正在验证的密钥 ( T extends keyof Main
),以及验证相应值并返回指示有效性的标志的验证 function ( (value: Main[T]) => boolean
) .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>
为了清楚起见,只需比较我的MainValidationRule
和MainValidationRule<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.