简体   繁体   English

如何在 Typescript 上对未知类型使用条件

[英]How to use conditional for unknown type on Typescript

I have this untyped function on a project which executes an async function over a collection, and I want to specify its typings for better IDE assistance - I want the IDE to infer that first parameter at callback is same as the array internal type.我在一个通过集合执行异步函数的项目上有这个无类型函数,我想指定它的类型以获得更好的 IDE 帮助 - 我希望 IDE 推断回调时的第一个参数与数组内部类型相同。

This is the function:这是函数:

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

I added obvious typings like this but a problem arose:我添加了这样的明显类型,但出现了一个问题:

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);
}

After that I got next scenario:之后我得到了下一个场景:

  • when first parameter was a typed array <T>[], first callback param was correctly inferred as <T>当第一个参数是类型化数组 <T>[] 时,第一个回调参数被正确推断为 <T>
  • when first parameter was a plain array [], first callback param was correctly inferred as any当第一个参数是一个普通数组 [] 时,第一个回调参数被正确推断为任何
  • PROBLEM: when first parameter was an "any" typed variable, first callback param now was inferred as "unknown" instead of "any" This change in the callback parameter type inferring lead to several build problems with legacy code which was happy accesing properties on the "any" variable but breaks if the variable is "unknown".问题:当第一个参数是“任何”类型变量时,第一个回调参数现在被推断为“未知”而不是“任何”回调参数类型推断的这种变化导致遗留代码的几个构建问题,这些代码很高兴访问属性“任何”变量,但如果变量“未知”则中断。

I'd like to be able to specify a ternary on the callback parameter typing so if it's going to be "unknown", instead of that be "any".我希望能够在回调参数输入上指定一个三元组,所以如果它是“未知”,而不是“任何”。

This is one of the several attempts I did, without success - compiler refuses to build and type inferring stops working.这是我做过的几次尝试之一,但没有成功 - 编译器拒绝构建并且类型推断停止工作。

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);
}

Anyone knows how to solve the (item: T extends unknown ? any: T, part?任何人都知道如何解决(item: T extends unknown ? any: T, part?

Lots of thanks in advance.非常感谢提前。

I don't know if what you're doing is advisable;我不知道你的做法是否可取; my inclination would be: if someone passes in an items parameter of the intentionally unsound any type that turns off type checking wherever it's used, they have to deal with the consequences.我的倾向是:如果有人传入故意不健全的any类型的items参数,无论在何处使用它都关闭类型检查,他们必须处理后果。 In this case, the consequences are that the compiler has no idea what to infer for T , and so it defaults to unknown ( as of TypeScript 3.5 ).在这种情况下,结果是编译器不知道要为T推断什么,因此它默认为unknown从 TypeScript 3.5 开始)。

If you would like to have the compiler choose a different default, you can specify one using the = operator in the type parameter declaration:如果您希望编译器选择不同的默认值,可以在类型参数声明中使用=运算符指定一个

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);
}

Note the T = any above.注意上面的T = any Now you get this behavior:现在你得到这个行为:

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

which is what you want, without losing the desired behavior with more well-typed items :这就是您想要的,而不会丢失更多类型良好的items所需的行为:

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

Playground link to code Playground 链接到代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM