我正在尝试下面描述的基于枚举的名义键入方法: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
吗?
答案 0 :(得分:1)
我认为,自编写该代码以来,打字稿已改变了它处理空(或它认为是空类型)的并集和交集的方式。我找不到能改变行为的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' })