gpt4 book ai didi

javascript - typescript 代理通用

转载 作者:搜寻专家 更新时间:2023-10-30 21:48:34 25 4
gpt4 key购买 nike

我正在尝试包装通过泛型类型提供的基本接口(interface),以便接口(interface)中的每个函数都有修改后的返回值。

例如:

interface IBaseInterface {
test(a?: boolean, b?: number): Promise<boolean>;
anotherTest?(a?: number): Promise<number>;
}

// to...

interface IBaseInterfaceModified {
test(a?: boolean, b?: number): Promise<boolean> | string;
anotherTest?(a?: number): Promise<number> | string;
}

我曾尝试将映射类型与泛型组合使用,但没有成功。我得到的最接近的是:

type TProxyify<T> = {
[K in keyof T]: TProxy<T[K]>;
};

type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
type TProxy<T> = {
(): ReturnType<T> | string;
};

export function wrapType<T>(): TProxyify<T> {
return 1 as any;
}

const s = wrapType<IBaseInterface>();
// s.test() tooltip outputs -> test(): string | Promise<boolean>

但是,类型建议系统删除了 BaseInterface.test 参数名称和类型。无论如何我都可以完成这个,以便我可以包装一个基本接口(interface),修改函数返回类型,并且仍然保持原始基本接口(interface)类型建议(参数名称、类型和顺序)不变?

非常感谢任何指导。谢谢。

最佳答案

3.0解决方案见下文

您可以使用类似的方法来替换返回类型答案 here

type TProxyify<T> = {
[K in keyof T]: AddReturnType<T[K], string>;
};

type IsValidArg<T> = T extends object ? keyof T extends never ? false : true : true;
type AddReturnType<T, TNewReturn> = T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E, f: infer F, g: infer G, h: infer H, i: infer I, j: infer J) => infer R ? (
IsValidArg<J> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J) => R | TNewReturn :
IsValidArg<I> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I) => R | TNewReturn :
IsValidArg<H> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H) => R | TNewReturn :
IsValidArg<G> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F, g: G) => R | TNewReturn :
IsValidArg<F> extends true ? (a: A, b: B, c: C, d: D, e: E, f: F) => R | TNewReturn :
IsValidArg<E> extends true ? (a: A, b: B, c: C, d: D, e: E) => R | TNewReturn :
IsValidArg<D> extends true ? (a: A, b: B, c: C, d: D) => R | TNewReturn :
IsValidArg<C> extends true ? (a: A, b: B, c: C) => R | TNewReturn :
IsValidArg<B> extends true ? (a: A, b: B) => R | TNewReturn :
IsValidArg<A> extends true ? (a: A) => R | TNewReturn :
() => R | TNewReturn
) : T

export function wrapType<T>(): TProxyify<T> {
return 1 as any;
}

interface IBaseInterface {
test(a?: boolean, b?: number): Promise<boolean>;
anotherTest?(a?: number): Promise<number>;
}

const s = wrapType<IBaseInterface>();

let ss = s.test(undefined, undefined); // will be string | Promise<boolean>

这种方法的问题在于,当与可选参数一起使用时,可选参数变为必需参数(并且类型为 A | undefined)。这就是为什么对测试的调用是 s.test(undefined, undefined); 而不是 s.test();

参数名称也不会保留,这可能是可读性方面的问题。

编辑

由于回答了原始问题, typescript 改进了该问题的可能解决方案。添加 Tuples in rest parameters and spread expressions我们现在不需要所有的重载:

type TProxyify<T> = {
[K in keyof T]: AddReturnType<T[K], string>;
};

type ArgumentTypes<T> = T extends (... args: infer U ) => any ? U: never;
type AddReturnType<T, TNewReturn> = T extends (...args: any[])=> infer R ? (...a: ArgumentTypes<T>) => TNewReturn | R : T;

export function wrapType<T>(): TProxyify<T> {
return 1 as any;
}

interface IBaseInterface {
test(a?: boolean, b?: number): Promise<boolean>;
anotherTest?(a?: number): Promise<number>;
}

const s = wrapType<IBaseInterface>();

let ss = s.test(undefined, undefined); // will be string | Promise<boolean>

这不仅更短而且解决了很多问题

  • 可选参数保持可选
  • 保留参数名称
  • 适用于任意数量的参数

关于javascript - typescript 代理通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50155990/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com