用途:解决 TypeScript 结构化类型无法区分语义不同原始值的问题。当 string 或 number 含义各异(如绝对路径与相对路径、米与秒、UserId 与 PostId),或需要名义类型时使用。
主要能力:给原始类型添加幻影品牌属性,使其成为互不可赋值的独立类型。品牌仅存在于类型系统,无运行时开销,强制显式转换或校验。可用类型守卫收窄,可让非法状态不可表示。
基本用法: type Brand<T, B extends string> = T & { _brand: B }; type UserId = Brand<string, 'userId'>; type Meters = Brand<number, 'meters'>; 配合类型守卫(如 isAbsolutePath(path: string): path is AbsolutePath)或工厂函数(const meters = (n: number) => n as Meters)产生品牌值。
常见模式:单位(Meters、Seconds、MetersPerSecond)、已校验字符串(SanitizedHTML、Email)、类型安全 ID、已排序数组 SortedList。更强方案可用 unique symbol 或类私有字段。防止向量混用可用 z?: never。
限制:算术运算会丢失品牌(如 d * 2 结果为 number)。获取品牌值只能通过返回品牌类型的函数、类型守卫收窄或类型断言。基于《Effective TypeScript》第 64 条。