尽管验证有效,但我仍收到此错误。我所需要的只是一个函数,它使用一个对象来生成另一个函数来过滤固定类型的参数
Type 'keyof T' does not satisfy the constraint '"a" | "b" | "c"'.
Type 'string' is not assignable to type '"a" | "b" | "c"'.
Type 'keyof T' is not assignable to type '"c"'.
Type 'string' is not assignable to type '"c"'
type GM = {
a: number;
b: string;
c: string
}
type VMeth<T, C > = (old: T, n: C) => any;
const getVF = <T extends { [key in keyof Partial<GM>]: 1 }>(part: T): VMeth<GM, Pick<GM, keyof T>> => {
return function(){ } as any
}
const fd = getVF({ a: 1 });
fd({ a: 1, b: "", c: "s"}, { a: 1 });
答案 0 :(得分:2)
约束
T extends { [key in keyof Partial<GM>]: 1 }
表示 T
必须可分配给 {a?:1, b?:1, c?:1}
。这包括您尝试支持的类型,例如 {a: 1}
。但它也包括您显然不试图支持的类型。 TypeScript 中的对象类型是 extendable 或 open(相对于 exact 或 closed)。您可以通过向对象类型添加属性来扩展对象类型。因此也支持 {a?: 1, b?:1, c?:1, oops: string}
类型:
const oopsie = getVF({ a: 1, oops: "oops" }) // no error!
// const oopsie: VMeth<GM, Pick<GM, "a" | "oops">>
因为 T
实际上可能比 GM
拥有更多的键,编译器理所当然地抱怨
// Type 'keyof T' does not satisfy the constraint 'keyof GM'.
如果你真的想把 part
的键限制为 GM
的键(或者至少只关注那些键,因为无论你做什么对象类型都是开放的),你可以改为在这些键 K
中使您的函数通用:
const getVF = <K extends keyof GM>(part: Record<K, 1>):
VMeth<GM, Pick<GM, K>> => {
return function () { } as any
}
现在 K
必须是 "a" | "b" | "c"
并集的某个子集,不能是 "oops"
或其他任何东西。因此 Pick<GM, K>
将始终有效。您所需的用例仍然具有相同的功能:
fd({ a: 1, b: "", c: "s" }, { a: 1 });
// const fd: (old: GM, n: Pick<GM, "a">) => any
现在,如果我们明显添加了意外的属性,我们会收到编译器警告:
getVF({ a: 1, oops: "oops" }); // error, excess property!
如果你偷偷摸摸,你仍然可以设法在那里获得如此多的财产:
const existingObj = {a: 1, oops: "oops"} as const;
const aliased: {a: 1} = existingObj;
const okay = getVF(aliased); // no error
// const okay: VMeth<GM, Pick<GM, "a">>
但至少出来的值仍然是 Pick<GM, "a">
而不是像 Pick<GM, "a" | "oops">
这样的无效值。