[英]Are compile-time tagged numbers possible in 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
到一个需要Seconds
的函数,或者错误地分配变量。
请注意,您尝试执行的操作通常被称为“newtype 模式”,位于 Haskell 中的newtype
关键字之后(正是为此目的而存在的)。 特别是,您可以在此页面上阅读有关它在 Typescript 中使用的更多信息(我也是在这里学到了这个小技巧)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.