【问题标题】:Typescript cannot narrow Union based on optional property打字稿不能根据可选属性缩小联合
【发布时间】:2020-09-10 21:42:46
【问题描述】:

我在缩小 typescript 中的联合类型时遇到了问题。

假设我们有两个接口和一个联合:

interface A {
    flag: true
    callback: (arg: string) => void
}

interface B {
    flag?: false
    callback: (arg: number) => void
}

type AB = A | B

这可以正确缩小范围:

const testA: AB = {
    flag: true,
    callback: arg => {
        // typescript knows this is interface A and arg is a string
    }
}

const testB: AB = {
    flag: false,
    callback: arg => {
        // typescript knows this is interface B and arg is a number
    }
}

但这不起作用:

const testC: AB = {
    // we are implying flag: undefined
    callback: arg => {
        // typescript has no clue if this is A or B
        // arg is implicitly any
    }
}

我错过了什么?

这是typescript playground的链接

提前致谢

【问题讨论】:

  • 这可能有助于缩小您的问题:Typescript 实际上正在将正确的 testC 类型确定为 B,如 this playground 所示。所以我认为你的问题真的是:为什么它不能在testC.callback 中推断出参数arg 的正确类型?

标签: typescript


【解决方案1】:

flag?:声明可能没有值。

flag?: false 等于 flag: false |未定义,不是没有标志属性。

const testC: AB = {
    flag: undefined,
    callback: arg => {
        // typescript knows this is interface B and arg is a number
    }
}

【讨论】:

  • 如果是这样,为什么会编译? const b : B = { callback: arg => {} }
【解决方案2】:
// Error on testC, [...] 'number' is not assignable to type 'string'
const testC: AB = {
  flag: undefined,
  callback: (arg: string) => {
  }
}

// same error
const testC: AB = {
  callback: (arg: string) => {
  }
}

有趣的是:

interface B {
  flag: false | undefined;
  callback: (arg: number) => void
}

// Type '{ callback: (arg: any) => void; }' is not assignable to type 'AB'.
//   Property 'flag' is missing in type '{ callback: (arg: any) => void; }' but required in type 'B'.
const testC: AB = {
  callback: (arg) => {
  }
}

我不知道 Typescript 应该以不同的方式处理 flag?flag: undefined。但可能与人们在 JS 中不习惯的一种奇怪行为有关:

Object.keys({a: undefined}); // ['a']
Object.keys({}); // []

【讨论】:

    猜你喜欢
    • 2021-06-22
    • 2019-04-18
    • 1970-01-01
    • 2021-10-12
    • 1970-01-01
    • 2018-06-05
    • 2019-02-06
    • 1970-01-01
    • 2016-11-01
    相关资源
    最近更新 更多