您可以constrain R
,因此它必须可分配给Record<KR, T[KL]>
,使用the Record
utility type表示R[KR]
处的属性必须可分配给L[KL]
.就像这样:
declare function foo<
T,
R extends Record<KR, T[KL]>,
KL extends keyof T,
KR extends keyof R
>(lft: T, rgh: R, kl: KL, kr: KR): void;
是的,这是一个递归约束,因为R
依赖于KR
,KR
依赖于R
,但它恰好是TypeScrip支持的循环形式之一.让我们看看它是如何工作的:
const obj1 = { id: 1, name: "foo" };
const obj2 = { oid: 2, score: 98 }
foo(obj1, obj2, 'id', 'oid'); // ok
foo(obj1, obj2, 'name', 'oid'); // error!
// -----> ~~~~
// Argument of type '{ oid: number; score: number; }' is not assignable to
// parameter of type 'Record<"oid", string>'. Types of property 'oid'
// are incompatible.
看上go 不错!第一个调用成功是因为{oid: string, score: number}
可以赋值给Record<"oid", number>
,而第二个调用失败是因为它不能赋值给 Record<"oid", string>
.
Playground link to code个