如何键入检查名义类型的ID

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何键入检查名义类型的ID相关的知识,希望对你有一定的参考价值。

我正在尝试这里描述的基于枚举的名义输入方法:https://basarat.gitbooks.io/typescript/docs/tips/nominalTyping.html

enum PersonIdBrand {}
export type PersonId = PersonIdBrand & string

interface Person {
  id: PersonId
  firstName: string
  lastName: string
}

我遇到了一个问题,将类型添加到测试使用的一些工厂方法中。这些辅助方法允许使用可以有选择地重写的默认值创建测试数据:

const makeTestPerson = ({
  id = 'personId' as PersonId,
  firstName = 'Bob',
  lastName = 'Smith'
}: Partial<Person> = {}): Person => ({
  id,
  firstName,
  lastName
})

const person = makeTestPerson({ lastName: 'Ross' })

但是,tsc给出了一个错误:

error TS2322: Type 'PersonId' is not assignable to type 'never'.

11   id = 'personId' as PersonId,

如果我改为使用id: string,它编译没有任何问题。有没有办法使用PersonId进行这些函数类型检查?


更新已经探讨了一点,我认为这个策略存在一个更基本的问题:

const maybePersonId: PersonId | undefined = ("personId" as PersonId)

这也失败了:

TS2322: Type 'PersonId' is not assignable to type 'undefined'.

那么为什么会失败呢?肯定一个X应该总是可以分配给X | undefined

答案

我认为自从代码编写以来,typescript已经改变了处理联合和交叉与空(或它认为是空类型)的方式。我无法找到改变行为的PR但是如果我找到它会尝试发布它(我找不到PR但是在2.9中发生了中断)

对于品牌类型,compiler team使用的交集类型只包含一个额外成员而不是与枚举的交集:

export type Path = string & { __pathBrand: any };

我会采用这种方法:

export type PersonId = { __personIdBran: any } & string

interface Person {
  id: PersonId
  firstName: string
  lastName: string
}

const makeTestPerson = ({
  id = 'personId' as PersonId,
  firstName = 'Bob',
  lastName = 'Smith'
}: Partial<Person> = {}): Person => ({
  id,
  firstName,
  lastName
})

const person = makeTestPerson({ lastName: 'Ross' })

以上是关于如何键入检查名义类型的ID的主要内容,如果未能解决你的问题,请参考以下文章

linux打开终端如何启动scala,如何在终端下运行Scala代码片段?

如何在PyCharm中运行mypy插件以检查键入的代码?

键入检查函数参数是“Pythonic”吗? [关闭]

分享前端开发常用代码片段

收藏|分享前端开发常用代码片段

如何在 Toad for Oracle 中使用自定义代码片段?