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

Posted

技术标签:

【中文标题】如何为映射类型添加索引签名?【英文标题】:How do I add an index signature for a mapped type? 【发布时间】:2018-05-07 23:11:44 【问题描述】:

假设我有接口

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

还有一个函数

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

当我启用 typescript 的 strict 标志时,我收到错误消息“元素隐式具有 'any' 类型,因为类型 'X' 没有索引签名”。因此,为了明确起见,我可以在 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 =&gt; (x as any)[s]) 之类的粗俗行为的情况下明确这一点

【问题讨论】:

【参考方案1】:

你可以:

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

X[keyof X] 的结果现在将是 (string | number | boolean),它比 any 工作得更好,因为您的函数的返回将是 (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]);

【讨论】:

谢谢@Meligy。是的,你是对的,我本可以在第一个示例中使索引签名更具体,但这并不是我真正感兴趣的。我的问题更多是关于如何将索引签名添加到第二个示例 如果您不想要太多的仪式(并且可能会选择any 作为中间选择,然后再选择其他东西以不完全松散打字),那么没有什么可做的。我假设第二个例子是为了解决第一个问题,对吧?我添加了另一种方法,让我知道你的想法。 如果您的目标是使第一个示例通用,我也为此添加了第三个示例。 不错的一个!我想这可能是最好的方法。我发现 Object.keys(x) 的类型为 string[] 而不是 (keyof T)[] 有点令人失望,尽管核心贡献者反对这样做也是有道理的 亲爱的耶稣,谢谢@Meligy?。我一直试图解决这个问题!如果有人试图用字符串枚举来做到这一点:enum eFoo a = 'a', b = 'b' ; interface Foo [key: string]: eFoo[keyof eFoo]; typescriptlang.org/play/…

以上是关于如何为映射类型添加索引签名?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用映射类型删除索引签名

打字稿:映射类型中的索引签名

MySQL如何为表字段添加索引

如何为以下示例添加索引?

Mysql如何为表字段添加索引?

如何为 MySQL 表添加索引?