TypeScript中Exclude泛型赋值报错解析:为何存在特殊场景?
为什么泛版函数报错,用具体类型却正常?
这事儿核心在于TypeScript对泛型条件类型的处理逻辑,咱们掰开了说:
先搞懂两个Exclude类型的关系
你定义的两个类型:
ExcludeString<T>:把T里的string类型去掉,剩下的就是它ExcludeStringAndBoolean<T>:把T里的string和boolean都去掉,剩下的才是它
逻辑上后者肯定是前者的子集——毕竟它多排除了一种类型嘛。按道理子集类型能安全赋值给父集,但泛型场景下TypeScript的编译器不认这个理儿。
泛型函数test1报错的真相
在test1里,泛型参数T是完全未约束的(啥类型都能传)。对于这种未约束的泛型条件类型(比如这里的Exclude),TypeScript不会做“逻辑预判”——它不会去想“不管T是什么,排除更多类型的结果肯定是另一个的子集”。
编译器此时只会把Exclude<T, string | boolean>和Exclude<T, string>当成两个独立的、还没解析的类型表达式,没法确定它们之间的子类型关系,所以直接抛出赋值错误。
具体类型test2为啥没问题
当你用CertainType = string | number | boolean这种具体类型时,编译器可以直接算出两个Exclude的最终结果:
ExcludeString<CertainType>→ 结果是number | booleanExcludeStringAndBoolean<CertainType>→ 结果是number
明眼人都能看出来number是number | boolean的子类型,赋值完全安全,所以编译器当然不会报错。
总结一下:泛型场景下编译器“看不到”条件类型的最终形态,只能看到抽象的表达式;而具体类型场景下,编译器能直接算出明确的类型结果,自然能判断出赋值是否安全。
内容的提问来源于stack exchange,提问作者Andrei Kovalev
相关产品推荐
相关产品推荐

