gpt4 book ai didi

javascript - 基于输入参数的 Typescript 函数重载

转载 作者:行者123 更新时间:2023-12-01 01:23:32 27 4
gpt4 key购买 nike

我正在寻找一种方法来覆盖或重载一组特定的函数。

这是一个例子

const operationA = ({a, b, c}) => 'alpha';
const operationB = ({a, b }) => 'beta';
const operationC = ({a}) => 'gamma';

const operation = compose([operationA, operationB, operationC]);

operation({a}) // 'gamma'
operation({a, b}) // 'beta'
operation({a, b, c}) // 'alpha'

有没有办法在 typescript 中执行此功能?

最佳答案

(下面我使用的是 TypeScript 3.2)

如果我理解的话,你的问题的主要问题是在运行时选择正确的重载的困难。是not one of TypeScript's goals (参见非目标#5)将类型信息从 TypeScript 编译为 JavaScript。 TypeScript 添加的类型系统在运行时被完全删除。因此,如果您想编写 compose() 来获取函数列表,则必须能够在运行时检查这些函数,以确定应该对特定参数调用哪个函数。但 JavaScript 中确实不存在该功能。好吧,你可以使用 length函数的属性来查看它需要多少个参数,但在您给出的示例中,每个函数只接受一个参数。所以我们不能在这里使用这种方法。

一种可能的方法是添加 property到每个功能。此属性将是一个方法,它接受一组潜在的参数,如果这些参数对于该函数有效,则返回 true ,如果无效,则返回 false 。本质上,您是在手动添加语言中缺少的必要检查功能。

如果我们这样做,我们可以使 compose() 接受此类“参数验证函数”的列表,如下所示:

type ArgValidatingFunction =
((...args: any[]) => any) & { validArgs(...args: any): boolean };

type UnionToIntersection<U> =
(U extends any ? (k: U) => void : never) extends
((k: infer I) => void) ? I : never;

function compose<F extends ArgValidatingFunction[]>(...fn: F): UnionToIntersection<F[number]>;
function compose(...fn: ArgValidatingFunction[]): Function {
return Object.assign(
(...args: any[]) => (fn.find(f => f.validArgs(...args))!(...args)),
{ validArgs: (...args: any[]) => fn.some(f => f.validArgs(...args)) }
);
}

compose 的类型签名接受 ArgValidatingFunction 参数列表并返回 intersection of its elements 。 TypeScript 代表 overloads作为依赖于顺序的签名交集。我不能 100% 保证编译器会产生与传入的函数相同的重载顺序,但它似乎在我的测试中有效。

compose 的实现利用了 ArgValidatingFunctionvalidArgs 方法,并执行 find()在传入的函数上选择正确的函数。我还在返回的函数上实现了一个 validArgs() 方法,以便 compose() 的返回值也是一个 ArgValidatingFunction (这很好因为类型签名声称它是)。

现在我们可以尝试使用它,但这并不简单......我们必须添加这些方法:

const operationA = ({ a, b, c }: { a: any, b: any, c: any }): 'alpha' => 'alpha';
operationA.validArgs = (...args: any[]) =>
(args.length === 1) && ('a' in args[0]) && ('b' in args[0]) && ('c' in args[0]);

const operationB = ({ a, b }: { a: any, b: any }): 'beta' => 'beta';
operationB.validArgs = (...args: any[]) =>
(args.length === 1) && ('a' in args[0]) && ('b' in args[0]);

const operationC = ({ a }: { a: any }): 'gamma' => 'gamma';
operationC.validArgs = (...args: any[]) =>
(args.length === 1) && ('a' in args[0]);

我们开始:

const operation = compose(operationA, operationB, operationC);

const beta = operation({ a: 3, b: 3 }); // "beta" at compile time;
console.log(beta); // "beta" at runtime

看起来它在编译时和运行时都有效。

<小时/>

所以这是一种方法。这并不容易或漂亮,但也许它适合您(或某人)的用例。希望有帮助。祝你好运!

关于javascript - 基于输入参数的 Typescript 函数重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54028491/

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