【问题标题】:Why typescript typeguard doesn't work for an internal property of an object为什么 typescript typeguard 不适用于对象的内部属性
【发布时间】:2021-05-26 21:25:41
【问题描述】:

使用打字稿,当函数返回一个具有可能为空属性的对象时。为什么在这些内部属性上使用 typeguard 不允许 typescript 推断出内部 prop 在保护之后不能为 null?

这是一个最小的例子。 Try it

interface DatabaseResponse {
  settings: string | null
}
interface MainResponse {
  settings: string
}

const retrieveFromDatabase = (): DatabaseResponse => {
  return {
    settings: 'always a string but lets pretend it could be null sometimes'
  }
}

const main = (): MainResponse | Error => {
  const data = retrieveFromDatabase()

  if (data.settings === null) {
    throw new Error()
  }

  return data

}

main函数返回的错误是

Type 'DatabaseResponse' is not assignable to type 'MainResponse | Error'.
  Type 'DatabaseResponse' is not assignable to type 'MainResponse'.
    Types of property 'settings' are incompatible.
      Type 'string | null' is not assignable to type 'string'.
        Type 'null' is not assignable to type 'string'.

【问题讨论】:

标签: typescript typeguards


【解决方案1】:

这不是真正的类型保护。你可以这样做:

interface DatabaseResponse {
    settings: string | null
}
interface MainResponse {
    settings: string
}

const retrieveFromDatabase = (): DatabaseResponse => {
    return {
        settings: 'always a string but lets pretend it could be null sometimes'
    } as DatabaseResponse
}

const main = (): MainResponse | Error => {
    const data = retrieveFromDatabase()

    if (!isMainResponse(data)) {
        throw new Error()
    }

    return data
}

const isMainResponse = (data: DatabaseResponse | MainResponse): data is MainResponse {
  return !!data.settings;
}

或者类似地,使用相同的类型保护创建一个新的 nonNullable 类型

type NonNullableDB = { [K in keyof DatabaseResponse]: NonNullable<DatabaseResponse[K]> }

const isMainResponse = (data: DatabaseResponse | MainResponse): data is NonNullableDB => {
    return !!data.settings;
}

【讨论】:

  • “这不是真正的类型保护”。确实,从 TypeScript 4.1 开始,编译器并没有通过检查父对象的属性来保护父对象类型(它只对有区别的联合进行保护,DatabaseResponse 根本不是联合)。不过,它可能在未来......见github.com/microsoft/TypeScript/issues/42384
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-11
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 1970-01-01
  • 2022-08-07
  • 2016-02-18
相关资源
最近更新 更多