如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?

Posted

技术标签:

【中文标题】如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?【英文标题】:How to create a TypeScript interface with both an index signature and a fixed property of a different type? 【发布时间】: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 界面输入这种格式吗?

【问题讨论】:

你为这个可能令人困惑的问题提出了一个很好的标题! @John rubber duck problem solving 的力量 ;) 谢谢你的客气话。 这能回答你的问题吗? How to define Typescript type as a dictionary of strings but with one numeric "id" property 【参考方案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 值中的错误赋值。

以上是关于如何创建具有索引签名和不同类型的固定属性的 TypeScript 接口?的主要内容,如果未能解决你的问题,请参考以下文章

具有命名属性和不同类型的任意命名索引属性的打字稿接口[重复]

编译打字稿时如何防止错误“对象类型的索引签名隐式具有'任何'类型”?

如何在 TypeScript 中添加索引签名

如何创建具有可变参数/不同方法签名的方法接口?

元素隐式具有“任何”类型,因为类型“窗口”没有索引签名?

如何在java中的每个arraylist中创建具有不同类型对象的arraylist数组?