【问题标题】:How to create a TypeScript interface with both an index signature and a fixed property of a different type?如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?
【发布时间】:2019-05-01 08:07:08
【问题描述】:

从一个旧的 api 我得到一个 JSON 响应,如下所示:

const someObject = {
    "general": {
        "2000": 50,
        "4000": 100,
        "8000": 200,
    },
    "foo": [
        0,
        1,
        2,
    ],
    "bar": [
        5,
        7,
    ],
    "baz": [
        8,
        9,
    ],
};

请记住,除“general”之外的所有索引都是动态的,可能不在响应中,我无法为每个属性键入,但必须使用索引签名。

我想通过 typescript@2.9.2 来实现:

interface ISomeObject {
    general: {
        [index: string]: number;
    };

    [index: string]?: number[];
}

因为general 将始终在响应中,但其他索引可能在其中也可能不在其中。

我面临的问题:

  • 我不能将[index: string]?: number[] 设为可选,因为它会抱怨此处将数字用作值。
  • [index: string]: number[] 将覆盖 general: number 的定义,因此 tsc 会抱怨:

    Property 'general' of type '{ [index: string]: number; }' is not assignable to string index type 'number[]'.`
    

我什至可以使用 TypeScript 界面输入这种格式吗?

【问题讨论】:

标签: json typescript interface index-signature


【解决方案1】:

这是TypeScript Dictarray concept 的变体。

作弊修复是告诉 TypeScript 一切都很好,并且你知道自己在做什么:

interface ISomeObject {
    [index: string]: number[];
    // @ts-ignore: I'm creating a Dictarray!
    general: {
        [index: string]: number;
    };
}

编译器会正确推断返回类型,在这种情况下是数字:

let x: ISomeObject;

const a = x.general['idx'];
const b = x['idx'];

链接的文章有更多信息,但这是您具体案例的要点。

【讨论】:

  • 我觉得非常幸运,我刚刚遇到了这个问题,而你恰好在一小时内提供了答案。谢谢!
  • 这个答案似乎遇到了打字稿不喜欢let x: ISomeObject = {general: {}}的问题。基本上,它与this answer 中概述的限制相同。因此,也许使用联合类型(如链接答案中所述)是比@ts-ignore 更好的解决方案?
  • 最好使用let x = { general: {}} as ISomeObject; - 当你开始使用联合体时,它的限制是不断地填充到两个更窄的类型之一。我更喜欢 early-gnarl 到 Late-gnarl :)
  • @Fenton:这仍然是使用 TS 3.7.2 的最佳解决方案吗?我在问,因为我有 general 属性的另一种接口类型。在对象生成中使用as 会抑制所有检查并使编译器忽略general 值中的错误赋值。
猜你喜欢
  • 2020-02-02
  • 2020-04-24
  • 2015-10-12
  • 2018-09-15
  • 1970-01-01
  • 2022-01-10
  • 1970-01-01
  • 2020-01-01
  • 1970-01-01
相关资源
最近更新 更多