typescript 类型脚本:rest.someMethod()不是函数

hmae6n7t  于 2022-11-18  发布在  TypeScript
关注(0)|答案(1)|浏览(80)

以下TypeScript脚本不能与TypeScript 4.5.5或4.6.4一起使用:

class Thing {
    someProperty = 42;
    someMethod() {
        console.log('bar')
    }
}

function foo<T extends Thing>(x: T) {
    let { someProperty, ...rest } = x;
    rest.someMethod();
}

var t = new Thing()
t.someMethod()
foo(t)

我有两个问题:
1.在4.6.4中,错误是Property 'someMethod' does not exist on type 'Omit<T, "someProperty" | "someMethod">'.这是由于this breaking change in TypeScript 4.6。但是,有人能解释一下什么是不可扩展的成员吗?
1.在4.5.5版本中,错误是rest.someMethod is not a function。为什么在上述TypeScript 4.6中断更改之前出现此错误?

yptwkmov

yptwkmov1#

**简短版本:**在typescript 4.6中,讨论中的更改更多的是一个错误修复,而不是一个破坏性的更改,typescript编译器在与泛型结合使用时没有正确地键入反结构化赋值。
详细版本:

让我们来看看spread在typescript中是如何工作的,现在让我们举一个更简单的例子

const t =  {
    someProperty : 42,
    someProperty2 : 4
}
const { someProperty, ...rest } = t;

我们可以看到它在4.5和4.6中编译成完全相同的javascript,你可以通过交换版本并将输出粘贴到一个diff编辑器中来确保这一点。(这也正是你提供的例子的情况)

对等的javascript代码有何作用?

我们不需要100%了解它的功能,但快速浏览一下就会发现它使用

for (var p in s)

就像

for(var property in object)

这将允许它在对象中的属性(而不是方法)上循环,我们可以在js控制台中快速检查这一点,并看到只打印了属性(而不是方法)

class Thing {
    someProperty = 42;
    property2 = 3;
    someMethod() {
        console.log('bar')
    }
}
x = new Thing();
for( var p in x){console.log(p)}

返回原始示例的修补版本

这个例子应该给我们同样的行为从编译器,对不对?

class Thing {
    someProperty = 42;
    someMethod() {
        console.log('bar')
    }
}
var t = new Thing()
let { someProperty, ...rest } = t;
rest.someMethod();

但事实上,它并不像typescript 4.5那样识别出rest对象上没有方法,并引发错误

您提供的示例有何不同?

这个示例直接在对象上使用反结构化,而您的示例在泛型上使用反结构化。
"虫子在哪里"
简单地说,使用泛型使得typescript在反结构化时无法检测到方法的“删除”,因此这段讨厌的代码使它通过了编译...错误仍然存在,而您在运行时看到了它,这是一个大问题,因为typescript应该在发布应用程序时提供信心(特别是类型安全)。
希望这对你有帮助

相关问题