【问题标题】:Typescript - adding an extra function parameter打字稿 - 添加额外的函数参数
【发布时间】:2021-11-30 08:09:23
【问题描述】:

我正在尝试创建一个可以转换类型函数的辅助类型

type Func1 = (id: string) => void;

type Func2 = (id: string, conf: { extraArg: boolean }) => void;

我发现 this answer 确实有效,但是它将第一个参数命名为 head 并且如果我要应用我的示例,则以下参数将命名为 id非常具有误导性。

为了我的目的,我稍微修改了这段代码

type Cons<T extends readonly any[], H> =
        ((head: H, ...tail: T) => void) extends ((...cons: infer R) => void) ? R : never;

type Push<T extends readonly any[], V>
        = T extends any ? Cons<T, void> extends infer U ?
            { [K in keyof U]: K extends keyof T ? T[K] : V } : never : never;

export type FunctionWithExtraArgument<F extends (...args: any[]) => any, Arg, R> = (...args: Push<Parameters<F>, Arg>) => R;

但是我仍然无法获得解决命名问题的完整解决方案。

【问题讨论】:

    标签: typescript type-inference typescript-generics variadic-tuple-types


    【解决方案1】:

    现在不需要使用上述答案中的代码。在撰写本文时this answer 还没有variadic tuple types

    现在您只需一个工具即可实现它:

    type Func1 = (id: string) => void;
    
    
    type Func2 = (id: string, conf: { extraArg: boolean }) => void;
    
    type AddArgument<
      Fn extends (...args: any[]) => any,
      NextArg
      > =
      Fn extends (...arg: [...infer PrevArg]) => infer Return
      ? (...args: [...PrevArg, NextArg]) => Return
      : never;
    
    // type Result = (args_0: string, args_1: {
    //     extraArg: boolean;
    // }) => void
    type Result = AddArgument<Func1, { extraArg: boolean }>
    

    Playground

    如果您愿意,您将始终对一个参数函数进行操作,您可以使用以下代码:

    type Func1 = (id: string) => void;
    
    
    type Func2 = (id: string, conf: { extraArg: boolean }) => void;
    
    type AddArgument<
      Fn extends (arg: any) => any,
      Conf
      > =
      Fn extends (id: infer Id) => infer Return
      ? (id: Id, conf: Conf) => Return
      : never;
    
    // type Result = (id: string, conf: {
    //     extraArg: boolean;
    // }) => void
    type Result = AddArgument<Func1, { extraArg: boolean }>
    

    如果我必须“硬编码”“conf”之前的每个变量,因为我在某些情况下使用 2-3 个变量

    你可以期待第二个通用参数作为一个元组:

    type Func1 = (id: string) => void;
    
    
    type Func2 = (id: string, conf: { extraArg: boolean }) => void;
    
    type AddArgument<
      Fn extends (...args: any[]) => any,
      NextArg extends any[]
      > =
      Fn extends (...arg: [...infer PrevArg]) => infer Return
      ? (...args: [...PrevArg, ...NextArg]) => Return
      : never;
    
    // type Result = (args_0: string, args_1: {
    //     extraArg: boolean;
    // }) => void
    type Result = AddArgument<Func1, [{ extraArg: boolean }, { anotherArg: 42 }]>
    

    【讨论】:

    • 感谢您的回答!我试着用上面提到的可变元组类型来做。然而,使用这个功能仍然给我同样的问题 - 即使变量不再被错误命名(这很好),它会篡改它们的名称,使它们无法识别。
    • 第二个例子似乎更适合我的情况,但我想知道我是否必须“硬编码”“conf”之前的每个变量,因为我在几个案例中使用了 2-3 个变量
    • @Rinta 我更新了。如果您对参数的名称感到困惑 - 您不必太担心,它不会影响类型本身。
    • 在我的情况下,可变元组类型似乎不是理想的方式。我希望能够看到我应该传递给函数的变量的名称,特别是如果它们的数量是可变的。虽然您建议的类型确实有效,但不幸的是它仍然不够。如果不扩展您提供的第二个变体,可能无法实现我现在的目标,这是对参数名称进行硬编码
    猜你喜欢
    • 1970-01-01
    • 2016-05-17
    • 1970-01-01
    • 1970-01-01
    • 2019-12-12
    • 1970-01-01
    • 2012-11-16
    • 2021-09-17
    • 2015-08-27
    相关资源
    最近更新 更多