【问题标题】:How to use conditional for unknown type on Typescript如何在 Typescript 上对未知类型使用条件
【发布时间】:2020-12-23 23:00:54
【问题描述】:

我在一个对集合执行异步函数的项目上有这个无类型函数,我想指定它的类型以获得更好的 IDE 帮助 - 我希望 IDE 推断回调时的第一个参数与数组内部类型相同.

这是函数:

export async function asyncForEach(array, callback) {
    for (let index = 0; index < array.length; index++) {
        await callback(array[index], index, array);
    }
}

我添加了类似这样的明显类型,但出现了问题:

export async function asyncForEach<T>(
    items: T[],
    callback: (item: T, idx: number, items: T[]) => Promise<any>
): Promise<void> {
    for (let index = 0; index < items.length; index += 1)
        await callback(items[index], index, items);
}

之后我得到了下一个场景:

  • 当第一个参数是类型化数组[]时,第一个回调参数被正确推断为
  • 当第一个参数是普通数组 [] 时,第一个回调参数被正确推断为 any
  • 问题:当第一个参数是“any”类型变量时,第一个回调参数现在被推断为“unknown”而不是“any” 回调参数类型推断的这种变化导致遗留代码的几个构建问题,这些代码很高兴访问“任何”变量的属性,但如果变量“未知”则中断。

我希望能够在回调参数类型中指定一个三元组,这样如果它将是“未知”,而不是“任何”。

这是我做过的几次尝试之一,但没有成功 - 编译器拒绝构建并且类型推断停止工作。

export async function asyncForEach<T>(
    items: T[],
    callback: (item: T extends unknown ? any: T, idx: number, items: T[]) => Promise<any>
): Promise<void> {
    for (let index = 0; index < items.length; index += 1)
        await callback(items[index], index, items);
}

有人知道如何解决(item: T extends unknown ? any: T, 部分吗?

非常感谢。

【问题讨论】:

    标签: typescript typescript-generics


    【解决方案1】:

    我不知道您的做法是否可取;我的倾向是:如果有人传入一个故意不健全的any 类型的items 参数,该参数在任何使用它的地方都会关闭类型检查,他们必须处理后果。在这种情况下,结果是编译器不知道要为T 推断什么,因此它默认为unknown (as of TypeScript 3.5)。

    如果您想让编译器选择不同的默认值,您可以在类型参数声明中使用specify one 运算符=

    export async function asyncForEach<T = any>(
        items: T[],
        callback: (item: T, idx: number, items: T[]) => Promise<any>
    ): Promise<void> {
        for (let index = 0; index < items.length; index += 1)
            await callback(items[index], index, items);
    }
    

    注意上面的T = any。现在你得到了这种行为:

    declare const a: any;
    asyncForEach(a, async (i) => i.randomThingBecauseAnyDoesntTypeCheck); // okay
    

    这就是您想要的,而不会丢失具有更好类型的所需行为的items

    asyncForEach([a], async (i) => i.randomThingBecauseAnyDoesntTypeCheck); // okay
    asyncForEach([1, 2, 3], async (i) => i.toFixed()); // okay
    

    Playground link to code

    【讨论】:

    • @jcalz 太棒了,尽管问题很长,但对我的问题的理解非常好,完美的解决方案而不是说“这是因为使用任何,不要使用它”,而且我正在学习一种新的 TypeScript功能,泛型的默认值!非常感谢您投入的时间。
    猜你喜欢
    • 2020-09-22
    • 2021-01-03
    • 2019-02-10
    • 2012-12-31
    • 2020-08-23
    • 2021-04-12
    • 2021-08-10
    • 2020-12-14
    • 2021-02-07
    相关资源
    最近更新 更多