我用Typescript 写,也用type-festNPM包.

在我的代码中,出于文档目的,我有时喜欢添加两个类型确实相等或不相等的断言.例如,如下所示:

const b: IsEqual<{a: 1}, {a: 1}> = true;
console.log(b);

如果传递给IsEqual的类型不相等,则在TS编译器进行类型判断期间,上述代码的第一行将失败.第二行只是为了消除TS错误variable b is defined but not used.

到目前一切尚好.

现在,我想创建一个小实用程序,使我能够更简洁地断言两种类型的等价性,如下所示:

function type_fest_is_equal_assertion<T, S>(): void {
      let R: IsEqual<T, S> = true; // * 
      console.log(R);
}


 // with the idea that I can then simply write:
type_fest_is_equal_assertion<{a: number}, {a: number}>()

遗憾的是,在编译过程中,上面的代码在标有星号(*)的行上失败:

类型‘Boolean’不能赋值给类型‘IsEqual&lt;T,S&>’.

操场是here号.

有没有办法实现我想要的东西?

顺便说一句,我也在要求澄清上述this related question中的错误消息.

推荐答案

唯一可行的方法是,如果你的generic函数constrains是它的一个类型参数,那么IsEqual<T, S>就是true.这有可能使您的约束非法循环,因此我们必须小心.一种方法看起来像是

function typeFestIsEqualAssertion<
  T extends IsEqual<T, S> extends true ? unknown : never,
  S extends IsEqual<T, S> extends true ? unknown : never
>(): void {
  console.log(true);
}

幸运的是,它编译时没有错误.

从本质上讲,TS都被限制为IsEqual<T, S> extends true ? unknown : never.当您调用函数并指定TS时,如果IsEqual<T, S>true,则此约束看起来像T extends unknown, S extends unknown,它将始终起作用,因为unknown是TypeScrip中的通用超类型.另一方面,如果IsEqual<T, S>不是true,那么这个约束看起来像T extends never, S extends never,almost总是失败,因为never是TypeScrip中的通用子类型.唯一可分配给never的类型是never本身.这意味着只要ST中至少有一个没有指定为never,您就会得到预期的行为.如果bothnever,那么IsEqual<never, never>大概是true,你会很高兴它被接受的:

typeFestIsEqualAssertion<{ a: 1 }, { a: 1, b: 2 }>(); // error
typeFestIsEqualAssertion<{ a: 1 }, { a: 1 }>(); // okay
typeFestIsEqualAssertion<{ a: 1 }, { b: 2 }>(); // error

typeFestIsEqualAssertion<{ a: 1 }, never>(); // error
typeFestIsEqualAssertion<never, { a: 1 }>(); // error
typeFestIsEqualAssertion<never, never>(); // okay

请注意,错误消息都会显示指定的类型不满足约束never,这对于您的用例来说可能是可接受的,也可能是不能接受的.如果您需要更具描述性的内容,则需要解决TypeScrip中缺少"无效类型"或"抛出类型"的问题.关于这一点的讨论,请看microsoft/TypeScript#23689.

Playground link to code

Typescript相关问答推荐

将对象属性路径描述为字符串数组的类型

如何在方法中定义TypeScript返回类型,以根据参数化类型推断变量的存在?

node—redis:如何在redis timeSeries上查询argmin?

typescribe不能使用值来索引对象类型,该对象类型满足具有该值的另一个类型'

为什么typescript要把这个空合并转换成三元?

`((PrevState:NULL)=>;NULL)|null`是什么意思?

React typescribe Jest调用函数

扩展函数签名中的参数类型,而不使用泛型

类型脚本类型字段组合

带switch 的函数的返回类型的类型缩小

如何使默认导出与CommonJS兼容

为什么有条件渲染会导致material 自动完成中出现奇怪的动画?

使用Dockerfile运行Vite React应用程序时访问env变量

笛卡尔产品类型

正交摄影机正在将渲染的场景切成两半

无法将从服务器接收的JSON对象转换为所需的类型,因此可以分析数据

如何使用泛型函数参数定义类型脚本函数

Typescript泛型验证指定了keyof的所有键

React中的效果挂钩在依赖项更新后不会重新执行

Next 13 + React 18 createContext 类型的构建问题