0

考虑以下表示商店的示例数据,其中包含待处理和已完成的采购订单 ID 列表:

{
    "shop-45": {
        "FULFILLED": [55, 70]
    },
    "shop-46: {
        "PENDING": [59, 54]
        "FULFILLED": [100, 101]
    }
}

如果一家商店既没有待处理订单也没有完成订单,则它根本不会出现在列表中。

我尝试使用以下内容来表示这一点:

type Status = "PENDING" | "FULFILLED";

interface ShopList {
    [shop: string]: {
        [status in Status]: number[];
    }
}

不出所料,tsc抱怨当我没有这两个 PENDINGFULFILLED作为商店的子属性时。

我通过将该属性设为可选 ( [status in Status]?: number[]) 来消除错误,但我认为这不是我真正想要做的,因为商店永远不会有零子属性

另一个异想天开的,在黑暗中射击的尝试[status in Partial<Status>]: number[];类似地抱怨。

这是我唯一的选择,而且根本不用担心吗?

这是一个平凡的 MCVE;真正的要复杂得多,并且有更多的层次。这就是(总是?)使用泛型而不是重复每个可能的键名的动机:枚举被用作其他对象中的字段值。

讨论类似情况的 TypeScript/问题参考:7374 | 19211 | 14934 | 5683 .

4

1 回答 1

2

如果您希望禁止没有任何一种商店就不会出现的情况,PENDING或者FULFILLED您需要更明确地说明您的类型。例如,您可以执行以下操作:

type ShopWithPending = {
    PENDING: number[];
}

type ShopWithFulfilled = {
    FULFILLED: number[];
}

type ShopStatus = ShopWithPending | ShopWithFulfilled | (ShopWithPending & ShopWithFulfilled);

interface ShopList {
    [shop: string]: ShopStatus
}

但是,这确实使shops从列表中拉出的使用变得困难,因为 Typescript 会将ShopStatus类型视为不保证具有任何属性的东西,因此不允许您尊重PENDINGFULFILLED.

为了恢复这种能力,您需要在Shop允许 Typescript 将类型推断缩小到特定类型版本的类型上使用其他东西。

于 2018-05-04T21:00:10.527 回答