元组成员的打字稿类型依赖于其他

时间:2019-07-18 18:04:12

标签: typescript

我想创建一个函数,该函数接受许多对对象和这些对象的键,并让编译器强制执行。我目前写了以下内容:

declare function foo(...params: [any, string][]): void;

我可以写些什么

foo([a, "propOfA"], [b, "propOfB"]);

但是,它也允许我写

foo([a, "propofB"], [b, "propOfA"]);

这很有意义,因为第二个值的类型就是string。我可以使用keyof来限制每个元组的第二个值成为同一元组的第一个值的键吗?

2 个答案:

答案 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"]);

对我很好。希望能有所帮助;祝你好运!

Link to code

答案 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']) ab必须具有相同的类型(或兼容的类型)。