我想创建一个函数,该函数接受许多对对象和这些对象的键,并让编译器强制执行。我目前写了以下内容:
declare function foo(...params: [any, string][]): void;
我可以写些什么
foo([a, "propOfA"], [b, "propOfB"]);
但是,它也允许我写
foo([a, "propofB"], [b, "propOfA"]);
这很有意义,因为第二个值的类型就是string
。我可以使用keyof
来限制每个元组的第二个值成为同一元组的第一个值的键吗?
答案 0 :(得分:4)
如果只有一个参数,则@ExplosionPills answer中的代码将起作用。如果要支持多个元组值的参数,每个参数都将第二个元素约束为第一个元素的键,则可以这样做:
declare function foo<A extends any[]>(
...params: { [I in keyof A]: [A[I], keyof A[I]] }
): void;
这里,我们使用mapped tuples来表示params
作为A
数组的函数,并且inference from mapped types允许我们从第一个元素中推断出A
每个元组参数。让我们确保它有效:
const a = { a: 1 };
const b = { b: 2 };
// not allowed
foo([a, "b"]);
foo([b, "a"]);
foo([a, "a"], [b, "a"])
// okay
foo([a, "a"]);
foo([b, "b"]);
foo([a, "a"], [b, "b"]);
对我很好。希望能有所帮助;祝你好运!
答案 1 :(得分:1)
您可以使用泛型来做到这一点:
declare function foo<T>(...params: [T, keyof T][]): void;
现在,将从您传入的参数的第一个数组元素中推断出类型T。
const a = { a: 1 }
const b = { b: 2 }
// not allowed
foo([a, 'b']);
foo([b, 'a']);
// okay
foo([a, 'a']);
foo([b, 'b']);
请注意,如果您使用多个参数,例如foo([a, 'a'], [b, 'b'])
a
和b
必须具有相同的类型(或兼容的类型)。