如何为映射类型添加索引签名?

How do I add an index signature for a mapped type?

假设我有接口

interface X {
   a: string;
   b: number;
   c: boolean;
}

和一个函数

function values(x: X) {
   return Object.keys(x).map(s => x[s])
}

当我启用打字稿的 strict 标志时,我收到错误 "Element implicitly has an 'any' type because type 'X' has no index signature"。所以为了明确,我可以在 X

的定义中添加一个索引签名
[key: string]: any;

简单易行。


但是,如果 I X 现在是映射类型:

type X<T> = {
  [P in keyof T]: string;
}

我有这个功能

function values<T>(x: X<T>) {
  return Object.keys(x).map(s => x[s])
}

我应该在哪里添加索引签名?有没有什么办法可以使这一点明确而不诉诸于做一些像 Object.keys(x).map(s => (x as any)[s])

这样粗暴的事情

您可以:

interface X {
    a: string;
    b: number;
    c: boolean;
    [key: string]: X[keyof X];
}

X[keyof X] 的结果现在将是 (string | number | boolean),它比 any 效果更好,因为您的函数的 return 将是 (string | number | boolean)[]

Example

另一种适用于这两个示例的方法是:

function values(x: X) {
    const keys = Object.keys(x) as (keyof X)[];
    return keys.map(s => x[s]);
}

不漂亮,但至少比 (x as any) 更有型。

当然也可以做成通用的:

function values<T>(x: T) {
    const keys = Object.keys(x) as (keyof T)[];
    return keys.map(s => x[s]);
}