如何键入检查标称ID [英] How to type check nominal-typed IDs

查看:46
本文介绍了如何键入检查标称ID的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试此处所述的基于枚举的名义键入方法: https://basarat.gitbooks.io/typescript/docs/tips/nominalTyping.html

I'm trying out the enum-based nominal typing method described here: https://basarat.gitbooks.io/typescript/docs/tips/nominalTyping.html

enum PersonIdBrand {}
export type PersonId = PersonIdBrand & string

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

我遇到了一个问题,即将类型添加到测试使用的某些工厂方法中。这些帮助程序方法允许创建具有默认值的测试数据,该默认值可以有选择地覆盖:

I ran into an issue adding types to some factory methods used by tests. These helper methods allow creation of test data with defaults that can be selectively overridden:

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 进行类型检查?

If I instead use id: string instead, it compiles without any problem. Is there any way to make these functions type check using PersonId?

更新,在进行了更多探索之后,我认为此策略存在一个更基本的问题:

Update having explored a bit more, I think there is a more fundamental problem with this strategy:

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

这也将失败,并显示以下内容:

This also fails with:

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

那为什么会失败?当然,应该始终将 X 分配给 X |。未定义

So why does that fail? Surely an X should always be assignable to X | undefined?

推荐答案

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

I think since that code was written typescript has changed the way it handles unions and intersections with empty (or what it perceives as empty type). I am unable to find the PR that changes the behavior but I will try to post it if I find it (I can't find the PR but the break occurs in 2.9)

对于品牌类型,编译器团队使用一个交集,该交集的类型仅包含一个额外的成员,而不是与枚举的交集:

For branded types the compiler team uses an intersection with a type that just contains one extra member not an intersection with an enum:

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆