Typescript - 如何禁止两个解析为相同类型的类型别名互换使用?
Posted
技术标签:
【中文标题】Typescript - 如何禁止两个解析为相同类型的类型别名互换使用?【英文标题】:Typescript - How to disallow two type aliases that resolve to the same type to be used interchangeably? 【发布时间】:2020-08-20 12:10:34 【问题描述】:假设我有两个或多个类型别名,例如:
declare type A = string;
declare type B = string;
我有这些类型的变量,以及对它们进行操作的函数。
const a1: A = "example of a";
const b1: B = "example of b";
function withA(a: A)
console.log(a);
function withB(b: B)
console.log(b);
我希望以下代码出错,但它不会:
withA(b1);
withB(a1);
我怎样才能做到这一点?我还需要能够使用字符串初始化变量(我假设使用强制转换)。但是,一旦初始化,我不希望这些类型是“隐式等效的”,并且希望编译器禁止它们的可互换使用。
我也不想使用类,如下所述: TypeScript - specific string types
【问题讨论】:
【参考方案1】:顾名思义,类型别名不会向它们的别名类型添加任何内容。所以就 TS 而言,A
和 B
是同一类型,即 string
。
您可以做的是使用品牌类型。这是一种技术,您采用基本类型(在本例中为string
)并将其与具有属性的对象类型相交,以便从编译器的角度使该类型在结构上与其他任何东西不兼容。该属性不需要在运行时存在,它只是作为编译器的标记:
type A = string & __brand: "A";
type B = string & __brand: "B";
const a1: A = makeA("example of a");
const b1: B = makeB("example of b");
function makeA(s: string)
return s as A
function makeB(s: string)
return s as B
function withA(a: A)
console.log(a);
function withB(b: B)
console.log(b);
withA(b1); // error
withB(a1); // error
实用函数makeA
和makeB
不是绝对必要的,您可以在分配string
时使用类型断言,但它们会使DX 更好。
注意:在类型系统中形式化这种技术有两个提议(Structural tag type
brands 和 Nominal unique type
brands ),但在撰写本文时都没有合并,也许在未来的 TS 版本中我们将获得其中之一。
【讨论】:
感谢您的回答。我正在尝试将您描述为索引参数类型的品牌类型用于对象,但我很高兴:An index signature parameter type must be either 'string' or 'number'.ts(1023)
。你知道我怎么能解决这个问题吗?我的财产看起来像这样:foos: Readonly< [key: A]: Foo >;
@vasia 不可能,TS 要求索引是字符串或数字,甚至禁止string | number
。以上是关于Typescript - 如何禁止两个解析为相同类型的类型别名互换使用?的主要内容,如果未能解决你的问题,请参考以下文章