bounty将在14小时后过期。回答此问题可获得+50声望奖励。brillout希望吸引更多人关注此问题。
下面是我的第一次尝试:(Playground链接)
/** Trigger a compiler error when a value is _not_ an exact type. */
declare const exactType: <T, U extends T>(
draft?: U,
expected?: T
) => T extends U ? T : 1 & 0
declare let a: any[]
declare let b: [number][]
// $ExpectError
exactType(a, b)
7条答案
按热度按时间xienkqul1#
啊,type-level equality operator. @MattMcCutchen提出了一个涉及泛型条件类型的解决方案,它在检测两个类型何时完全相等(而不仅仅是相互可赋值)方面做得很好。在一个完美的类型系统中,“相互可赋值”和“相等”可能是同一回事,但TypeScript并不完美。特别是,
any
类型既可赋值给任何其它类型,也可从任何其它类型赋值,这意味着string extends any ? true : false
和any extends string ? true: false
都求值为true
,尽管string
和any
不是相同类型。这里有一个
IfEquals<T, U, Y, N>
类型,如果T
和U
相等,它的计算结果为Y
,否则为N
。让我们来看看它的工作原理:
好的,这些被识别为不同的类型。可能还有一些其他的边缘情况,你认为相同的两个类型被视为不同的,反之亦然:
无论如何,给定这个类型,我们可以创建一个生成错误的函数,除非这两个类型以这种方式相等:
每个参数都有一个类型
T
或U
(用于泛型参数的类型推断)与IfEquals<T, U>
相交,因此除非T
和U
相等,否则将出现错误。我认为这给出了您想要的行为。注意,这个函数的参数不是可选的,我不知道为什么你希望它们是可选的,但是(至少在
--strictNullChecks
打开的情况下)它削弱了这样做的检查:这取决于你
总之,希望能有所帮助,祝你好运!
mum43rcc2#
edit:最完善的版本可以在here中找到
以下是我迄今为止找到的最强大的解决方案:
感谢@jcalz为我们指明了正确的方向!
rt4zxlrg3#
我写了一个库,tsafe,它可以让你这样做。
感谢@jcalz,您的回答帮助我们实现了这一目标!
k3fezbri4#
到目前为止,我所见过的最健壮的
Equals
(尽管还不完美)是:例如,对于
Equals<[any, number], [number, any]>
,它会失败。可在此处找到:https://github.com/Microsoft/TypeScript/issues/27024#issuecomment-845655557
yshpjwxd5#
我有点恼火的是,其他命题暗示我只得到
false
,没有任何细节来理解它为什么失败。这是我如何解决我的用例(它给出可读错误):
0qx6xfy66#
如果您正在寻找一个没有任何第三方库依赖性的纯typescript解决方案,那么这个解决方案应该适合您
和用法如
eoxn13cs7#
我们应该根据不同的问题采取不同的方法,例如,如果我们知道我们要与任何一个数字进行比较,我们可以使用
typeof()
。例如,如果我们要比较接口,我们可以使用以下方法: