打字稿打字相关类型

Ore*_*lus 0 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]
}
Run Code Online (Sandbox Code Playgroud)

操场

然而这失败了

输入'号码| null' 不可分配给类型 'null'。
类型 'number' 不能分配给类型 'null'

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

jca*_*alz 5

这看起来像是 TypeScript 的一个实例无法跟踪我一直在调用的相关类型。在您的情况下,leftFieldrightField都是 union type number | null。不幸的是,当您进行类型保护时,编译器不会将它们一起考虑。它将它们视为uncorrelated,因此即使子类型是不可能的,[leftField, rightField]也被视为类型。[number | null, number | null][null, null]

除了放弃并断言你正在做的事情是安全的,这里唯一“正确”的事情是:

return (leftField === null && rightField === null) ? null :
 [leftField, rightField] as LeftRightArray;
Run Code Online (Sandbox Code Playgroud)

将代码重构为编译器可以通过控制流分析验证的可能冗余的单独代码路径:

return (leftField === null) ? (
 rightField === null ? null : [leftField, rightField]
) : [leftField, rightField];
Run Code Online (Sandbox Code Playgroud)

如果您只使用两个字段,这很好。如果您使用的比这多得多,那么冗余可能太多了,您应该断言并继续。

游乐场链接