Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(typings): 改善和纠正各种 id 类型的性质 #481

Merged
merged 1 commit into from
Jun 28, 2018

Conversation

chuan6
Copy link
Contributor

@chuan6 chuan6 commented Jun 6, 2018

各种 id 类型如:UserId, ProjectId, TaskId 等等,它们应该有下列性质:

  • 1. 可以赋给 string 类型(允许如:const x: string = id as UserId
  • 2. 相互之间不可赋值(如遇 const tid: TeamId = uid as UserId 会报错,需要手动强转)
  • 3. string 不可以赋给它们(如遇 const id: UserId = 'hello' 会报错,需要手动强转)
  • 4. 可以直接使用在对象 index 的位置

原来 interface X extends String { kind?: 'X' } 的实现,满足了2,但没有满足1、3。

不满足1,导致当需要将 id 数据从带有场景上下文的业务代码传给不关心业务逻辑而只是简单接受 string 的底层组件时,需要通过 as string 强转,如果该信息包在一个对象结构里,那这个对象结构要么需要 as any,结果丢失所有类型信息,要么底层组件的对应对象结构类型声明就需要添加类型参数(泛型声明),结果增加冗长而意义不大的泛型声明。

而不满足3,会漏掉很多类型检查,因为并不是任何 string 类型的值都可以赋值给特定 id 类型的。

新的写法是:type X = string & { kind: 'X' },它能同时满足1、2、3、4,并在类型报错信息里有比较友好的信息提示。

TODOs:

参考:

@chuan6 chuan6 added the REFACTOR label Jun 6, 2018
@chuan6 chuan6 self-assigned this Jun 6, 2018
@chuan6 chuan6 requested a review from Saviio June 6, 2018 16:32
@chuan6 chuan6 force-pushed the refactor/id-typing branch from 889b82a to c13bf56 Compare June 6, 2018 16:44
@coveralls
Copy link

coveralls commented Jun 6, 2018

Coverage Status

Coverage remained the same at 95.909% when pulling c212338 on refactor/id-typing into 69660b5 on release.

@chuan6 chuan6 changed the title refactor(typings): 改善和纠正各种 id 类型的性质 WIP: refactor(typings): 改善和纠正各种 id 类型的性质 Jun 8, 2018
@chuan6 chuan6 force-pushed the refactor/id-typing branch from c13bf56 to d12f0e1 Compare June 24, 2018 11:45
@chuan6 chuan6 changed the title WIP: refactor(typings): 改善和纠正各种 id 类型的性质 refactor(typings): 改善和纠正各种 id 类型的性质 Jun 24, 2018
@chuan6 chuan6 force-pushed the refactor/id-typing branch from d12f0e1 to 676ee19 Compare June 25, 2018 01:41
@chuan6 chuan6 changed the base branch from release to tmp/release-0.11 June 25, 2018 02:14
@chuan6 chuan6 force-pushed the refactor/id-typing branch 3 times, most recently from 441bcc6 to 611f1eb Compare June 27, 2018 06:52
@chuan6 chuan6 changed the base branch from tmp/release-0.11 to release June 27, 2018 06:52
各种 id 类型如:UserId, ProjectId, TaskId 等等,它们应该有下列性质:

 1.可以赋给 string 类型(允许如:`const x: string = id as UserId`)
 2.相互之间不可赋值(如遇 `const tid: TeamId = uid as UserId` 会报错,
   需要手动强转)
 3.string 不可以赋给它们(如遇 `const id: UserId = 'hello'` 会报错,需
   要手动强转)
 4.可以直接使用在对象 index 的位置

原来 `interface X extends String { kind?: 'X' }` 的实现,满足了2,但没
有满足1、3、4。

不满足1,导致当需要将 id 数据从带有场景上下文的业务代码传给不关心业务逻
辑而只是简单接受 string 的底层组件时,需要通过 `as string` 强转,如果
该信息包在一个对象结构里,那这个对象结构要么需要 `as any`,结果丢失所
有类型信息,要么底层组件的对应对象结构类型声明就需要添加类型参数(泛型
声明),结果增加冗长而意义不大的泛型声明。

不满足3,会漏掉很多类型检查,因为并不是任何 string 类型的值都可以赋
值给特定 id 类型的。

不满足4,有时通过把 id 作为 key,构建简易的字典对象时,就不得不麻烦地
在 [] 里写 `as string`。

新的写法是:

  `type X = string & { kind: 'X' }`

它能同时满足1、2、3、4。

参考:

 - https://codemix.com/opaque-types-in-javascript/
 - microsoft/TypeScript#15807
 - microsoft/TypeScript#4895
 - microsoft/TypeScript#202
 - https://github.com/Microsoft/TypeScript/blob/d9b93903c035e48c8da1d731332787f83efc4619/src/compiler/types.ts#L54
@chuan6 chuan6 force-pushed the refactor/id-typing branch from 611f1eb to c212338 Compare June 28, 2018 05:47
@chuan6 chuan6 merged commit 358e200 into release Jun 28, 2018
@chuan6 chuan6 deleted the refactor/id-typing branch June 28, 2018 13:32
@chuan6 chuan6 mentioned this pull request Aug 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants