You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何声明无法赋值给索引签名类型的完全Opaque type?

解决TypeScript完全不透明类型被索引签名类型兼容的问题

通常我们会用以下方式声明完全不透明类型(非品牌类型):

declare const sym: unique symbol;
type O = { [sym]: true };

但这种类型存在一个问题:它会被带有字符串索引签名的类型(比如Record<string, number>)兼容,示例如下:

type T = { [key: string]: number };
const o: O = {} as O;
const t: T = o; // 无报错,不符合仅O自身可赋值的预期

原因在于TypeScript的结构类型系统中,带字符串索引的类型兼容空对象,而O的实例可以赋值给空对象,进而被T兼容。

要实现O仅能赋值给自己和any,可以采用以下几种声明方式:

方式一:添加冲突的never类型字符串索引

给O添加一个字符串索引签名,类型设为never,这样任何带字符串索引的类型(只要其索引值类型不是never)都无法兼容O:

declare const sym: unique symbol;
type O = {
  [sym]: true;
  [key: string]: never; // 新增字符串索引,类型为never
};

type T = { [key: string]: number };
const o: O = {} as O;
const t: T = o; // 报错,符合预期

这种方式下,O只能赋值给自己或者any,其他类型要么不匹配symbol属性,要么索引签名类型冲突。

方式二:交叉unknown类型的品牌

将O与unknown交叉,利用unknown的严格特性,让它无法赋值给除自身和any外的其他类型:

declare const sym: unique symbol;
type O = unknown & { [sym]: true };

type T = { [key: string]: number };
const o: O = {} as O;
const t: T = o; // 报错,符合预期

这种方式下,O因为交叉了unknown,除自身和any外,无法赋值给包括空对象在内的任何其他类型。

内容的提问来源于stack exchange,提问作者Yevgeniy P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 17:52:41