我正在研究条件类型,并试图对此进行验证。有趣的是,如果我通过“ val”作为参数,则test()函数会执行 验证,如果我通过“ name”,则验证失败(这是预期的行为)。但是,Typescript显然不认为o [p]可以依赖为数字,而是抛出以下内容:
运算符'+ ='不能应用于类型'number'和'T [{[T键中的K]:T [K]扩展数字? K:从不; } [T键]]。
我是否以某种方式误解了用法?我以为“从不”会禁止任何不是数字的参数。
class Test {
public static SumParam<T>
(t: T[], p:{ [K in keyof T]: T[K] extends number ? K : never }[keyof T]): number {
let n:number = 0;
for (let o of t) {
n += o[p]; //Operator '+=' cannot be applied to types 'number' and 'T[{ [K in keyof T]: T[K] extends number ? K : never; }[keyof T]]'.
}
return (n);
}
public test(): void {
Test.SumParam(
[{ name: "alice", val: 3 },
{ name: "bob", val: 4 }],
"val"); //validates
Test.SumParam(
[{ name: "alice", val: 3 },
{ name: "bob", val: 4 }],
"name"); //Argument of type '"name"' is not assignable to parameter of type '"val"'.
}
}
编译器缩小范围并认识到“ val”是唯一可枚举的属性扩展数字的事实……这并不意味着条件语法正在起作用……?
答案 0 :(得分:2)
Typescript将无法遵循仍具有未解析的类型参数的条件类型。因此,它将无法知道o[p]
的类型为数字。
如果您不介意在数组中的项目上出现错误,则可以通过允许打字稿知道o[p]
是数字的方式来键入函数
class Test {
public static SumParam<T extends Record<K, number>, K extends keyof T>
(t: T[], p: K): number {
let n:number = 0;
if (!t) return (n);
for (let o of t) {
n += o[p]; //ok.
}
return (n);
}
public test(): void {
Test.SumParam(
[{ name: "alice", val: 3 },
{ name: "bob", val: 4 }],
"val"); //ok, no error here
Test.SumParam(
[{ name: "alice", val: 3 }, // Type 'string' is not assignable to type 'number'.
{ name: "bob", val: 4 }], // Type 'string' is not assignable to type 'number'.
"name");
}
}
答案 1 :(得分:0)
我为name
遇到了其他错误,但总的来说,它可以正常工作:
class Test {
public static SumParam<K extends string, T extends { [key in K]: number }>(t: T[], p: K): number {
let n:number = 0;
for (let o of t) {
n += o[p];
}
return (n);
}
public test(): void {
Test.SumParam(
[{ name: "alice", val: 3 },
{ name: "bob", val: 4 }],
"val"); //validates
Test.SumParam(
[{ name: "alice", val: 3 },
{ name: "bob", val: 4 }],
"name"); // Type 'string' is not assignable to type 'number'.
}
}