-
-
Notifications
You must be signed in to change notification settings - Fork 233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript extends 精读与实践 #140
Comments
你好, type A = { a: string }
type B = { readonly a: string }
type C = Equal1<A, B> // true
type D = Equal2<A, B> // false 这个要怎么解释呀 |
Equal1 的判断方式相对宽松,Equal2 的判断方式更为严谨。这个 case 单从语义的结果上说,Equal2 应该是符合我们预期的。。 |
云云牛批,云云能否解释下Equal2的工作原理,以前有个大佬在知乎回答过,但现在他删答案了,找不到了 |
细节可以参考这篇 How does the |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
|
我想知道的是这个实现中,为什么 函数类型 extends 函数类型时,两个函数类型会被判定为必须相等才返回true,如果按你的解释,其实把泛型T去掉,换成any就行了, 但是换成any是不行的 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
那只是一个例子,请仔细理解这句话:
|
首先感谢你的热心,其次我觉得你先解答一下我之前那条回复的疑问,再让我仔细理解你那句需要我通读多次再找到需要无视的冗余文字才能正常理解的话更好一点(实际上我再次仔细理解之后,依然无法解释为什么换成any之后,结果不如预期,你的“那只是一个例子”,给我的感觉好像是你觉得你的解释不需要覆盖所有的例子?当然也可能是我cpu不大行?)。最后,我再强调一下我的根本问题:为什么 函数类型 extends 函数类型时,两个函数类型会被判定为必须相等才返回true,我的意思是ts内部实现的时候,出于什么原因考虑专门这么做 |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
您好,方案二改成这样行不行: type ParseFun<U> = <T>() => T extends U ? 1 : 2
type Equal2<X, Y> = ParseFun<X> extends ParseFun<Y> ? true : false type T = Equal2<{x:1} & {y:2}, {x:1, y:2}> // true |
TypeScript extends 精读与实践
在大多数程序中,我们必须根据输入做出决策。TypeScript 也不例外,使用条件类型可以描述输入类型与输出类型之间的关系。
用于条件判断时的 extends
当 extends 表示条件判断时,可以总结出以下规律
===
,可以参考如下例子:在泛型类型中使用 extends
考虑如下 Demo 类型定义:
结合用于条件判断时的 extends,可知
'a' | 'b' | 'c' extends 'a'
是 false, 因此Demo<'a' | 'b' | 'c', 'a'>
结果是'a' | 'b' | 'c'
么?查阅官网,其中有提到:
即当条件类型作用于泛型类型时,联合类型会被拆分使用。即
Demo<'a' | 'b' | 'c', 'a'>
会被拆分为'a' extends 'a'
、'b' extends 'a'
、'c' extends 'a'
。用伪代码表示类似于:此外根据 never 类型的定义 —— never 类型可分配给每种类型,但是没有类型可以分配给 never(除了 never 本身)。即
never | 'b' | 'c'
等价于'b' | 'c'
。因此
Demo<'a' | 'b' | 'c', 'a'>
的结果并不是'a' | 'b' | 'c'
而是'b' | 'c'
。工具类型
心细的读者可能已经发现了 Demo 类型的声明过程其实就是 TypeScript 官方提供的工具类型中
Exclude<Type, ExcludedUnion>
的实现原理,其用于将联合类型 ExcludedUnion 排除在 Type 类型之外。基于 Demo 类型定义,进一步地还可以实现官方工具类型中的
Omit<Type, Keys>
,其用于移除对象 Type中满足 keys 类型的属性值。
逃离舱
如果想让
Demo<'a' | 'b' | 'c', 'a'>
的结果为'a' | 'b' | 'c'
是否可以实现呢? 根据官网描述:如果不想遍历泛型中的每一个类型,可以用方括号将泛型给括起来以表示使用该泛型的整体部分。
在箭头函数中使用 extends
在箭头函数中使用三元表达式时,从左向右的阅读习惯导致函数内容区若不加括号则会让使用方感到困惑。比如下方代码中 x 是函数类型还是布尔类型呢?
在 eslint 规则 no-confusing-arrow 中,推荐如下写法:
在 TypeScript 的类型定义中,若在箭头函数中使用 extends 也是同理,由于从左向右的阅读习惯,也会导致阅读者对类型代码的执行顺序感到困惑。
因此在箭头函数中使用 extends 建议加上括号,对于进行 code review 有很大的帮助。
结合类型推导使用 extends
在 TypeScript 中,一般会结合 extends 来使用类型推导 infer 语法。使用它可以实现自动推导类型的目的。比如用其来实现工具类型
ReturnType<Type>
,该工具类型用于返回函数 Type 的返回类型。结合 extends 与类型推导还可以实现与数组相关的
Pop<T>
、Shift<T>
、Reverse<T>
工具类型。Pop<T>
:Shift<T>
:Reverse<T>
使用 extends 来判断两个类型完全相等
我们也可以使用 extends 来判断 A、B 两个类型是否完全相等。当前社区上主要有两种方案:
方案一: 参考 issue。
目前该方案的唯一缺点是会将 any 类型与其它任何类型判为相等。
方案二: 参考 issue。
目前该方案的唯一缺点是在对交叉类型的处理上有一点瑕疵。
以上两种判断类型相等的方法见仁见智,笔者在此抛砖引玉。
The text was updated successfully, but these errors were encountered: