如何为映射类型添加索引签名?
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 => (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/…以上是关于如何为映射类型添加索引签名?的主要内容,如果未能解决你的问题,请参考以下文章