TypeScript中Extend异常行为及Effect Ts类型逻辑疑问
关于Effect Ts中类型定义的疑问
问题背景
我在使用Effect Ts库时,遇到一段难以理解的类型定义:
export declare const typeSymbol: unique symbol export type typeSymbol = typeof typeSymbol type FilterIn<A> = A extends any ? typeSymbol extends keyof A ? A : never : never type FilterOut<A> = A extends any ? typeSymbol extends keyof A ? never : A : never
疑问1:A extends any的分支作用是什么?
我测试了所有常见类型,包括never、unknown、void等,都没有找到会让A extends any条件为false的情况:
type t1 = undefined extends any ? 1 : 0 // 结果:1 type t2 = void extends any ? 1 : 0 // 结果:1 type t3 = null extends any ? 1 : 0 // 结果:1 type t4 = never extends any ? 1 : 0 // 结果:1 type t5 = unknown extends any ? 1 : 0 // 结果:1 type t6 = Function extends any ? 1 : 0 // 结果:1 type t7 = object extends any ? 1 : 0 // 结果:1
解答
确实不存在任何类型能让A extends any的条件为false,因为any是TypeScript的顶级类型,所有类型都可以赋值给any。这里使用A extends any的核心目的是触发分布式条件类型。
当泛型参数A是联合类型时,分布式条件类型会自动将联合类型拆分为单个成员,分别代入条件进行计算,最后把结果重新合并为联合类型。举个例子:
如果A是{ [typeSymbol]: number } | string | boolean,FilterIn<A>会分别对每个成员判断:
{ [typeSymbol]: number }:满足typeSymbol extends keyof A,保留该类型string:不满足,返回neverboolean:不满足,返回never
最终FilterIn<A>的结果是{ [typeSymbol]: number }。
如果去掉A extends any的外层条件,直接写typeSymbol extends keyof A ? A : never,当A是联合类型时,整个条件会被当作一个整体判断,无法实现拆分筛选的效果。
疑问2:为什么K<never>返回never而非1?
我发现一个奇怪的现象:
type t = never extends any ? 1 : 0 // 结果:1 type K<A> = A extends any ? 1 : 0 type u = K<never> // 结果:never
解答
这是分布式条件类型的特殊规则导致的:当泛型参数传入never时,分布式条件类型会直接返回never。
- 直接写
never extends any ? 1 : 0不属于分布式条件类型(没有泛型参数的分发逻辑),所以TypeScript会正常判断never extends any为true,返回1。 - 而
K<never>中,A extends any触发了分布式条件类型,但never是一个空的联合类型,没有任何成员可以分发,因此整个类型计算直接返回never。
内容的提问来源于stack exchange,提问作者martinjerome
相关产品推荐
相关产品推荐

