能否基于泛型参数将TypeScript泛型类型映射为另一类型?
TypeScript关联泛型类型的参数复用方案问题
我有一组包含多种相关泛型类型(及关联泛型约束)的API,下面是简化的示例,用常见类型模拟结构:
在使用这些类型时,我希望基于某个已有的具体类型创建相关的新类型,直接复用被引用类型的泛型参数,不用手动重复声明。目前我用的临时方案是在泛型接口里添加仅用于类型推导的假属性,但这种方式存在明显问题。
type Properties = { [name: string]: string } interface SomeGeneric<A,B extends Properties,C extends HTMLElement> { someConcreteMethod: () => A someOtherConcreateMethod: (b: B) => void aConcreteProperty: C // 仅用于类型推导的假属性,运行时不存在,这种方式很糟糕,有没有更好的办法? relatedInterface?: RelatedInterface<A,B> anotherRelatedInterface?: AnotherRelatedInterface<A,C> thirdRelatedInterface?: ThirdRelatedInterface<A,B,C> } interface RelatedInterface<A,B extends Properties> { yetAnotherMethod: (a: A, b: B) => void } interface AnotherRelatedInterface<A,C extends HTMLElement> { oneMoreMethod: (c: C) => A } interface ThirdRelatedInterface<A,B extends Properties,C extends HTMLElement> { thirdMethod: (a: A, b: B, c: C) => () => void // 同样是假属性 relatedInterface?: RelatedInterface<A,B> anotherRelatedInterface?: AnotherRelatedInterface<A,C> } type ConcreteB = { name: string }; interface SomeConcreteType extends SomeGeneric<string,ConcreteB,HTMLDivElement> {} // 这些类型都属于同一关联体系,但并非只有一个"主类型",它们各自都有独立使用场景 // 如果把所有类型都基于SomeGeneric来定义,会导致创建独立类型时不得不声明无用的参数,所以不可行 // 手动重复泛型参数的写法,太繁琐 interface SomeConcreteRelatedInterfaceVerbosely extends RelatedInterface<string,ConcreteB> {} interface AnotherConcreteRelatedInterfaceVerbosely extends AnotherRelatedInterface<string,HTMLDivElement> {} interface ThirdConcreteRelatedInterfaceVerbosely extends ThirdRelatedInterface<string,ConcreteB,HTMLDivElement> {} // 目前找到的唯一不用重复参数的方式:通过假属性推导类型 // 但所有关联类型都要加这类假属性,很不合理 type SomeConcreteRelatedInterfaceDeclaratively = SomeConcreteType["relatedInterface"] type AnotherConcreteRelatedTypeDeclaratively = SomeConcreteType["anotherRelatedInterface"] type ThirdConcreteTypeDeclaratively = SomeConcreteType["thirdRelatedInterface"] type DerivedFromThirdTypeDeclaratively = ThirdConcreteTypeDeclaratively["anotherRelatedInterface"]
当前方案的核心问题
编译器会认为这些假属性是对象的真实属性,但实际上它们完全是为了类型推导凭空添加的,这会造成类型定义的误导。
已排查的思路
- 映射类型不适用,它的作用是遍历类型键,和我的需求无关
- 了解到可以用
infer提取泛型参数(比如从数组类型中提取元素类型的示例),但不清楚如何将其应用到我的场景中,实现从已有类型提取泛型参数并转换为相关类型的效果:
export type ArrayElement<ArrayType extends readonly unknown[]> = ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
- 查找过一些泛型约束相关的问题,但大多局限于单个类型内部的约束,没有找到跨类型泛型参数复用的方案。
内容的提问来源于stack exchange,提问作者David P. Caldwell
相关产品推荐
相关产品推荐

