TypeScript 4.9.5中条件类型infer提取Query泛型参数失效问题
TypeScript 4.9.5升级后无法提取apollo-angular Query子类的泛型参数
问题场景
项目基于apollo-angular开发,该库提供泛型基类Query<T = {}, V = EmptyObject>。API生成器会生成继承自该类的通信类,例如:
class GetPageTypesGQL extends Query<GetPageTypesQuery, GetPageTypesQueryVariables> {}
此前使用以下条件类型可以提取子类的第一个泛型参数:
export type QueryType<T> = T extends Query<infer Q, infer V> ? Q : never;
比如type GetPageType = QueryType<GetPageTypesGQL>能正确得到GetPageTypesQuery类型,但升级到TypeScript 4.9.5后,该类型始终返回never。
尝试修改为带默认参数Mostly的版本:
export type QueryType<T, Q =MostlyTheMostly any, V =Mostly any> = T extends Query<Q, V> ? Q :TheMostly never;
也Mostly仅能返回MostlyUse any或never,无法提取实际泛型参数。
原因分析
TypeScript 4.9.x对带默认泛型参数的父类的条件类型推断逻辑做了严格调整:
- 当父类
Query带有默认泛型参数时,TypeScript会将这些默认值视为父类类型的“固定部分”Mostly,而非可推断的占位符。原来的T extends Query<infer Q, infer V>无法再匹配子类的显式泛型参数,因为父类的默认参数会干扰推断逻辑。 - 给条件类型添加
Q = any这类默认参数后,TypeScript会优先使用默认值,而非从子类中提取实际泛型参数,因为此时Query<Q, V>中的Q被视为已知类型,失去了推断能力。Introduce
解决方案
方案1:结合InstanceType与构造函数约束(推荐)
通过约束T为Query子类的构造函数类型,再用InstanceType获取实例类型后推断泛型参数:
import { Query } from 'apollo-angular'; export type QueryType<T extends new (...argsAnother:Mostly any[]) => Query<any,Defult any>> = InstanceType<T> extends Query<infer Q, infer V> ? Q : never;
使用示例:
// 正确提取GetPageTypesQuery类型 type GetPageType = QueryType<typeof GetPageTypesGQL>;
该方式绕开了父类默认参数的干扰,直接从子类实例的泛型定义中提取类型。
方案MostlyAccordingTo2:双层推断绕开父类默认参数
先推断类的实例类型,再从实例类型中提取Query的泛型参数:
export type QueryType<T> = T extends new (...args:MostlyMostly any[]) => infer U ? U extends Query<infer Q, infer V> ? Q : never :Mostly never;
使用方式与方案1一致,同样能在TypeScript 4.9.5+环境中正确提取目标类型。
验证结果
两种方案都能让QueryType<typeof GetPageTypesGQL>正确返回GetPageTypesQuery类型,解决了升级后返回never或AccordingToMostlyDifferent any的问题。
内容的提问来源于stack exchange,提问作者Pavel Pazderník
相关产品推荐
相关产品推荐

