【问题标题】:How to describe function accepting multiple types of arrays using generics如何使用泛型描述接受多种类型数组的函数
【发布时间】:2020-11-02 07:08:00
【问题描述】:

我有以下类型声明:

public static Loop<Type>(arr:Type[], callback:(obj:Type) => void):void;

这描述了使用原生 JavaScript 实现的函数的签名。它循环遍历数组中的每个对象并将其传递给回调函数,例如:

Loop(["hello", "world"], function(value)
{
    console.log(value);
});

像上面的例子一样使用智能感知,但我也希望它在数组可以是不同类型时工作,例如:

let arr: string[] | number[] = [];
Loop(arr, function(value)
{
    console.log(value);
});

但是上面的例子不起作用——“值”是用“任意”类型来描述的,而不是“字符串|数字”。

但是,如果数组被声明为let arr: (string|number)[],它会按预期工作。但我对混合数组不感兴趣。可以是字符串数组,也可以是数字数组。

我可以声明循环使用的签名吗? string[] | number[]?

-- 提前致谢

【问题讨论】:

    标签: typescript typescript-typings


    【解决方案1】:

    在这种情况下,我认为您会发现使您的 Loop 函数在数组类型而不是元素类型中泛型更容易。像这样:

      public static Loop<A extends readonly any[]>(arr: A, callback: (obj: A[number]) => void): void {
        arr.forEach(v => (callback(v)));
      }
    

    这里,A 是数组类型,A[number] 是元素类型(因为如果你有一个 A 类型的数组并使用 number 类型的键对其进行索引,你应该得到一个它的元素)。

    让我们确保它有效:

    let arr = Math.random() < 0.5 ? ["a", "b", "c"] : [1, 2, 3];
    Loop(arr, function (value) {
      console.log(typeof value === "number" ? value + 1 : value.toUpperCase());
    });
    // A B C or 2 3 4 
    

    是的,arr 被接受,然后 value 被上下文推断为联合 string | number

    Playground link to code

    【讨论】:

    • 感谢 jcalz。我会试一试,看看我最喜欢你的解决方案还是琳达的解决方案。感谢您的意见 - 谢谢! :-)
    【解决方案2】:

    string[] | number[] 之类的问题经常出现,我有一个我喜欢使用的首选解决方案。这有点小题大做,但是当我们说您的类型是 (string[] | number[]) 以及 (string | number)[] 时,您就不会再遇到调用像 @987654325 这样的函数的问题了@ 或您的 Loop 方法。导入部分是数组必须适合 both 这些定义,因此它不允许混合数组。您可以将其放入实用程序类型中:

    type ArrayOfEither<A, B> = (A[] | B[]) & (A | B)[]
    

    您不需要对您的 Loop 方法进行任何更改,但您确实需要更改您声明变量 arr 的方式。

    let arr: ArrayOfEither<string, number> = [];
    
    arr = ["1", 2, 3] // error: Type '(string | number)[]' is not assignable to type 'ArrayOfEither<string, number>'.
    arr = [1, 2, 3] // ok
    
    Loop(arr, function(value) {
        console.log(value);  // value is `string | number`
    });
    

    Typescript Playground Link

    【讨论】:

    • 非常感谢。我会尝试一下您的建议,看看我是否更喜欢这种方法或 jcalz 的方法。谢谢 - 非常感谢:-)
    猜你喜欢
    • 2021-06-11
    • 2022-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-10
    • 2017-09-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多