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

问题描述 投票:0回答:1

我正在尝试这里描述的基于枚举的名义输入方法: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 enums
1个回答
1
投票

我认为自从代码编写以来,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' })
© www.soinside.com 2019 - 2024. All rights reserved.