TypeScript:测试条件类型相等 - 理解语法
TypeScript: testing conditional type equality - understanding the syntax
我一直在尝试比较 TypeScript 中类型的相等性。我偶然发现了这种方法:
type SomeType = {
property: string;
}
type OtherType = {
property: string;
}
/**
* The two types passed are evaluated for equivalence; returning true if they
* are equivalent types and false if not
*
* Based upon Matt McCutchen's comment:
* https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
*/
type Equals<Type1, Type2> =
(<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match") extends
<Type2Match>() => Type2Match extends Type2 ? "match!" : "not a match"
? true
: false;
type IsTrue<T extends true> = T
/**
* This expression will evaluate that our types match; note
* the underscore at the start which indicates this is expected
* to be an unused type
*/
type test = IsTrue<Equals<SomeType, OtherType>
我正在阅读和重新阅读上面的 Equals
,我对 (<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match")
开头的 <Type1Match>() =>
感到有些困惑。
这里似乎没有混合功能;还是那里,我错过了什么?这只是引入新泛型的后门方式吗?
根据 Titians 的精彩回答更新
Titian 的更新(和更清晰)方法的不幸之处在于它不能很好地处理所有类型等价性检查。考虑提香 Equals2
未能发现差异的 any
比较。我放在一起的另一个简化的Equals3
也是如此。
但是 Equals
确实成功检测到了这些问题。我心中的问题是“为什么这行得通?”还有“我可以依靠这个前进吗?”。所以,如果我有依赖于能够执行此相等性检查的代码,那么我是否在此处建立在流沙之上?这种方法是否依赖于将来可能会改变的编译器实现细节?
type SomeType = {
property: any;
}
type OtherType = {
property: string;
}
/**
* The two types passed are evaluated for equivalence; returning true if they
* are equivalent types and false if not
*
* Based upon Matt McCutchen's comment:
* https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
*/
type Equals<Type1, Type2> =
(<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match") extends
<Type2Match>() => Type2Match extends Type2 ? "match!" : "not a match"
? true
: false;
type Equals2<Type1, Type2> =
(<Type1Match extends Type1>() => Type1Match) extends (<Type2Match extends Type2>() => Type2Match)
? true
: false;
type Equals3<Type1, Type2> =
[Type1] extends [Type2] ? (
[Type2] extends [Type1] ? true : false
) : false;
type IsTrue<T extends true> = T
/**
* This expression will evaluate that our types match; note
* the underscore at the start which indicates this is expected
* to be an unused type
*/
type test = IsTrue<Equals<SomeType, OtherType>> // errors as the types are not equivalent
type test2 = IsTrue<Equals2<SomeType, OtherType>> // unfortunately does not error
type test3 = IsTrue<Equals3<SomeType, OtherType>> // unfortunately does not error
<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match"
实际上是函数签名,Type1Match
是函数签名的类型参数。从 return 类型中删除条件类型使其更加清晰 <Type1Match>() => SomeReturnType
。 return 类型是条件类型 Type1Match extends Type1 ? "match!" : "not a match"
(这确实使它确实很难阅读)。
所有这一切的原因是TS在非常有限的地方使用了等价比较。这是其中之一,在涉及类型参数的条件类型中。
我一直在尝试比较 TypeScript 中类型的相等性。我偶然发现了这种方法:
type SomeType = {
property: string;
}
type OtherType = {
property: string;
}
/**
* The two types passed are evaluated for equivalence; returning true if they
* are equivalent types and false if not
*
* Based upon Matt McCutchen's comment:
* https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
*/
type Equals<Type1, Type2> =
(<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match") extends
<Type2Match>() => Type2Match extends Type2 ? "match!" : "not a match"
? true
: false;
type IsTrue<T extends true> = T
/**
* This expression will evaluate that our types match; note
* the underscore at the start which indicates this is expected
* to be an unused type
*/
type test = IsTrue<Equals<SomeType, OtherType>
我正在阅读和重新阅读上面的 Equals
,我对 (<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match")
开头的 <Type1Match>() =>
感到有些困惑。
这里似乎没有混合功能;还是那里,我错过了什么?这只是引入新泛型的后门方式吗?
根据 Titians 的精彩回答更新
Titian 的更新(和更清晰)方法的不幸之处在于它不能很好地处理所有类型等价性检查。考虑提香 Equals2
未能发现差异的 any
比较。我放在一起的另一个简化的Equals3
也是如此。
但是 Equals
确实成功检测到了这些问题。我心中的问题是“为什么这行得通?”还有“我可以依靠这个前进吗?”。所以,如果我有依赖于能够执行此相等性检查的代码,那么我是否在此处建立在流沙之上?这种方法是否依赖于将来可能会改变的编译器实现细节?
type SomeType = {
property: any;
}
type OtherType = {
property: string;
}
/**
* The two types passed are evaluated for equivalence; returning true if they
* are equivalent types and false if not
*
* Based upon Matt McCutchen's comment:
* https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
*/
type Equals<Type1, Type2> =
(<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match") extends
<Type2Match>() => Type2Match extends Type2 ? "match!" : "not a match"
? true
: false;
type Equals2<Type1, Type2> =
(<Type1Match extends Type1>() => Type1Match) extends (<Type2Match extends Type2>() => Type2Match)
? true
: false;
type Equals3<Type1, Type2> =
[Type1] extends [Type2] ? (
[Type2] extends [Type1] ? true : false
) : false;
type IsTrue<T extends true> = T
/**
* This expression will evaluate that our types match; note
* the underscore at the start which indicates this is expected
* to be an unused type
*/
type test = IsTrue<Equals<SomeType, OtherType>> // errors as the types are not equivalent
type test2 = IsTrue<Equals2<SomeType, OtherType>> // unfortunately does not error
type test3 = IsTrue<Equals3<SomeType, OtherType>> // unfortunately does not error
<Type1Match>() => Type1Match extends Type1 ? "match!" : "not a match"
实际上是函数签名,Type1Match
是函数签名的类型参数。从 return 类型中删除条件类型使其更加清晰 <Type1Match>() => SomeReturnType
。 return 类型是条件类型 Type1Match extends Type1 ? "match!" : "not a match"
(这确实使它确实很难阅读)。
所有这一切的原因是TS在非常有限的地方使用了等价比较。这是其中之一,在涉及类型参数的条件类型中。