类型防护不能使预期的通用类型变窄。可以使用与“数字”无关的任意类型实例化“ T”

时间:2020-08-08 05:42:50

标签: typescript generics

我有一个内插值的函数,该值用于为对象设置动画。值可以是数字,数字数组或包含数字/数字数组的对象,尽管这对于即将描述的问题并不重要。

这里是源的骨架,可以在此TS playground link上找到:

function lerpGeneric<T>(from: T, to: T, progress: number): T {
    if (typeof from !== typeof to) {
        throw Error(`The types of 'from' and 'to' do not match. Got ${typeof from} and ${typeof to}`);
    }

    switch (typeof from) {
        case 'number':
            if (typeof to === 'number')
                return lerpNumber(from, to, progress); // Error! 'T' could be instantiated with an arbitrary type which could be unrelated to 'number'.
            else
                throw Error(`Expected type of 'to' to be number but got ${typeof to}.`);
        case 'object':
            // If array, clone and iterate over each item.
            // If object, clone and recurse over properties.
        default:
            // not lerp-able, throw error.
    }

}

// Linearly interpolates a value. Progress is a number from 0 to 1.
function lerpNumber(start: number, end: number, progress: number): number {
    return start + (end - start) * progress;
}

在标有 // Error!的行上。编译器抱怨返回的类型。对我来说,switchif的类型检查应(有效地)将T的类型缩小到number,但这不会发生。编译器说'T' could be instantiated with an arbitrary type which could be unrelated to 'number'.有趣的是,VSCode建议将fromto的类型设为T & number,而不是我所期望的number。无论如何,编译器警告什么?我想不出任何类型T,其中typeof T === 'number'仍返回number可能会导致运行时错误。这里有一种方法可以纠正句柄类型,还是我只需要在这里执行类型断言?

1 个答案:

答案 0 :(得分:1)

TypeScript错误地推断from的类型为T & number,而实际上此时只能为number。它看起来像是TypeScript错误,您肯定not the first注意到了它。

在修复此TypeScript错误之前,请使用if代替switch