TypeScript 永远不会支持的两个特性

职场   2025-01-25 22:08   浙江  

* 戳上方蓝字“前端新世界”关注我

TypeScript是一个非常强大的编程语言,但没有任何一种语言是完美的。有些特性,无论它们多么有用,TypeScript也永远不会支持。

今天,我们来探讨其中的两个:否定类型(Negated Types)和名义类型(Nominal/Branded Types)。我们将探讨它们不被支持的原因,并展示一些巧妙的替代方法。

否定类型(Negated Types)

TypeScript与数学中的集合论紧密相关。我们之所以知道这一点,是因为TypeScript支持类型上的集合操作,比如并集(Union)、交集(Intersection)、连接(Concatenation)等。

然而,TypeScript并不支持类型减法,也就是所谓的否定类型。

举个例子,你不能写string - "click"这样的代码。不过,有一个很酷的技巧可以作为替代方案。

这个技巧在泛型函数参数中效果最好。看看下面这个处理函数,它接受除了"click"之外的所有字符串:

type NotClick<T> = T extends "click" ? never : T;

function handler<T extends string>(arg: NotClick<T>{
  // 函数实现
}

虽然这个方法并不完美,而且你也可以看出,这种替代方案只能在特定上下文中使用。但鉴于类型减法的需求其实很少,TypeScript原生不支持它也说得通。

名义类型(Nominal/Branded Types)

TypeScript使用的是结构化类型系统。这意味着它只关心数据的结构,而不是它们的名字。这就是为什么TypeScript中不存在名义类型的本质原因。

但假设你想要区分绝对路径字符串和相对路径字符串。如果把它们当作可以互换的类型,后续可能会出现错误。

幸运的是,你可以通过创建“品牌化类型”来模拟名义类型:

type AbsolutePath = string & { __brand: "absolute" };
type RelativePath = string & { __brand: "relative" };

function processPath(path: AbsolutePath{
  // 处理绝对路径
}

// 错误:RelativePath不能赋值给AbsolutePath
processPath("relative/path" as RelativePath);

这是一个很巧妙的技巧,适用于所有用例。

TypeScript永远不会正式支持否定类型或名义类型,但这些替代方案仍然能取得不错的效果。

你是否知道TypeScript还有哪些特性是官方绝不会支持的?请在评论区和大家分享一下。


前端新世界
关注前端技术,分享互联网热点
 最新文章