TypeScript中如何实现TSetTypeArgument以正确指定泛型参数?
TypeScript泛型包装类型的参数替换实现
需求说明
现有不可修改的基础TypeScript类型:
type TProps<TK extends string, T> = { a: TK; b: T };
需要为其创建包装类型TWrap,要求在根层级指定TK,在字段层级指定T。由于TypeScript不允许为类型字段直接添加泛型参数,因此采用函数包装的方式实现:
type TWrap<TR> = { func: <T>() => TProps<TR, T>; otherFunc: <T>() => TOtherProps<TR, T>; // 省略其他类型字段 }
尝试方案及问题
尝试编写TSetTypeArgument类型来实现参数替换,但未达到预期效果:
type tf<R> = () => R; type to<A1,A2> = {}; type TSetTypeArgument<T, A> = T extends tf<infer R> ? R extends to<infer X, infer Y> // 1 ? to<X, A> & R // 2 : never : never; type TRes = TSetTypeArgument<TWrap['func'], number>;
测试时发现变量b的类型为unknown,而非预期的number:
const t3: TRes = { a: '', b: 7 }; const b = t3.b; // 预期b为number,实际为unknown
实际使用场景
- application-api.ts:
export type makeApplicationApi<TLocale, TState, TAction> = { form: <TForm>() => TProps<TLocale, TForm>; request: <TRequest>() => TOtherProps<TLocale, TRequest>; // ... selector: (state: TState, action: TAction) => string | number; }
- orders-api.ts:
type TAppTypes = makeApplicationApi<TOrderLocale, TOrderState, TOrderAction>; export type TOrderForm = TSetTypeArgument<TAppTypes['form'], TOrderFormsDictionary>; export type TOrderRequest = TSetTypeArgument<TAppTypes['request'], TOrderRequestsDictionary>; export type TOrderSelector = TAppTypes['selector'];
可行解决方案
要实现正确的参数替换,需要精准匹配函数返回的泛型类型结构,提取已固定的第一个泛型参数,再将第二个泛型参数替换为指定类型。以下是修正后的TSetTypeArgument类型:
针对特定类型的实现
如果只需要处理TProps和TOtherProps这类结构一致的类型,可以直接匹配:
type TSetTypeArgument<T, A> = // 匹配返回TProps的函数 T extends <TIn>() => TProps<infer TK, infer _> ? TProps<TK, A> : // 匹配返回TOtherProps的函数 T extends <TIn>() => TOtherProps<infer TK, infer _> ? TOtherProps<TK, A> : never;
通用化实现
如果有更多类似的双泛型参数类型,可以通过匹配类型结构来实现通用替换:
type TSetTypeArgument<T, A> = T extends <TIn>() => infer R ? R extends { a: infer TK, b: infer _ } // 匹配TProps的结构 ? { a: TK, b: A } : R extends { /* 这里填入TOtherProps的结构特征 */ } ? { /* 对应替换TOtherProps的第二个参数 */ } : never : never;
测试修正后的类型:
type TRes = TSetTypeArgument<TWrap['func'], number>; const t3: TRes = { a: 'test', b: 7 }; const b = t3.b; // 现在b的类型为number,符合预期
说明
原方案的问题在于使用了空的to类型进行匹配,无法正确关联到TProps的实际结构,导致类型推断失败。修正后的方案直接匹配目标类型的结构或泛型参数定义,确保能正确提取并替换指定的泛型参数。
内容的提问来源于stack exchange,提问作者gdbdable
相关产品推荐
相关产品推荐

