【问题标题】: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]) 之类的粗俗行为的情况下明确这一点

【问题讨论】:

    标签: typescript mapped-types index-signature


    【解决方案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/…
    猜你喜欢
    • 2023-03-13
    • 2018-12-30
    • 2021-03-06
    • 2019-09-17
    • 2017-05-25
    • 1970-01-01
    • 2018-07-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多