typescript - TypeScript 中是否可以使用编译时标记的数字?
问题描述
例如,我想创建一个Port
类型和一个Seconds
类型,它们都是围绕number
类型的薄包装器,因此两者都不能分配给另一个。
let httpPort: Port = 80;
let oneMinute: Seconds = 60;
httpPort = oneMinute; // type error
oneMinute = httpPort; // type error
解决方案
我们可以通过unique symbol
. 具体来说,具有声明类型的字段unique symbol
永远不会与另一个同名字段比较兼容,除非它来自同一个声明。所以我们可以用伪造的唯一符号标记我们的数字,使它们无与伦比。
type Port = number & { readonly __tag: unique symbol };
type Seconds = number & { readonly __tag: unique symbol };
// Note that we do have to explicitly cast the numbers, as we're
// technically lying to the type system to get this behavior.
let httpPort = 80 as Port;
let oneMinute = 60 as Seconds;
现在httpPort
和oneMinute
是互不相容的。如果我们尝试比较它们,我们会得到类似的结果。
file.ts:8:1 - error TS2322: Type 'Seconds' is not assignable to type 'Port'.
Type 'Seconds' is not assignable to type '{ readonly __tag: unique symbol; }'.
Types of property '__tag' are incompatible.
Type 'typeof __tag' is not assignable to type 'typeof __tag'. Two different types with this name exist, but they are unrelated.
8 httpPort = oneMinute; // type error
不幸的是,我们仍然可以做一些无意义的事情,比如添加两个端口或一个端口或第二个端口,因为 Typescript 很乐意将它们中的任何一个向上转换为number
(毕竟这就是交集类型的工作方式),但至少我们不能传递一个Port
给期望 a 的函数Seconds
,或错误地分配变量。
请注意,您尝试执行的操作通常被称为“新类型模式”,newtype
位于 Haskell 中的关键字之后(正是为了这个目的而存在)。特别是,您可以在此页面上阅读有关它在 Typescript 中的使用的更多信息(我也在这里学习了这个小技巧)。
推荐阅读
- python - Python Turtle 在打开第二个窗口时崩溃
- amazon-web-services - 如何让 traefik 在我的云架构上工作?
- android - 如何以编程方式将字符串添加到资源值?
- java - 在android中比较两个字符串,如url
- netlogo - Netlogo:计算自己和其他代理之间的距离
- google-apps-script - 试图从工作表中的不同选项卡获取 url
- jquery - 在移动设备上强制 jPlayer 缓冲条
- c# - PHP的openssl_sign在C#中使用字符串
- vb.net - InternetMessageHeaders 不更新 EWS
- apache - 设置 puppet 并安装 apache 包问题