打字稿打字相关类型

时间:2020-09-04 16:58:04

标签: typescript

我具有以下类型和转换功能:

type LeftRightField = null |
    { left: null, right: number } |
    { left: number, right: null } |
    { left: number, right: number }

type LeftRightArray = [null, number] |
    [number, null] |
    [number, number] |
    null

const fmtField = function (field: LeftRightField): LeftRightArray {
    const rightField = field?.right ?? null
    const leftField = field?.left ?? null
    return (leftField == null && rightField == null) ? null : [leftField, rightField]
}

Playground

但是这失败了

输入'number | null”不能分配给类型“ null”。
不能将“数字”类型分配给“空”类型

进行转换的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

这似乎是TypeScript的实例,无法跟踪我一直在调用的correlated types。在您的情况下,leftFieldrightField都是联合类型number | null。不幸的是,当您进行类型防护时,编译器不会将它们视为在一起。它将它们视为不相关的,因此即使[leftField, rightField]子类型是不可能的,[number | null, number | null]也被视为类型[null, null]

在这里要做的唯一“正确”的事情,不仅仅是放弃和asserting这样的事情是安全的:

return (leftField === null && rightField === null) ? null :
 [leftField, rightField] as LeftRightArray;

将代码重构为可能冗余的独立代码路径,编译器可以使用control flow analysis进行验证:

return (leftField === null) ? (
 rightField === null ? null : [leftField, rightField]
) : [leftField, rightField];

如果您仅使用两个字段,则可以。如果您使用的资源不止这些,那么冗余可能太多了,您只需断言然后继续。

Playground link