Typescript 为什么允许这样做?常量nums:number[]={…[1,2,3]}
刚刚在我的typescript代码库中发现了一个关键错误,因为这是允许的:Typescript 为什么允许这样做?常量nums:number[]={…[1,2,3]},typescript,Typescript,刚刚在我的typescript代码库中发现了一个关键错误,因为这是允许的: const nums: number[] = { ...[1, 2, 3] } // should have been [ ...[1,2,3] ] a.join('-') // runtime error: a.join is not a function 为什么一个数组被解构为一个对象,可以分配给一个数组,而这个数组会导致一个容易预防的运行时异常?这是TypeScript的一个设计限制;看 类型系统无法将接口成
const nums: number[] = { ...[1, 2, 3] } // should have been [ ...[1,2,3] ]
a.join('-')
// runtime error: a.join is not a function
为什么一个数组被解构为一个对象,可以分配给一个数组,而这个数组会导致一个容易预防的运行时异常?这是TypeScript的一个设计限制;看 类型系统无法将
接口
成员标记为“自有”或可枚举,因此编译器假定所有成员都是通过扩展运算符复制的。作为一种启发式方法,这通常是足够的,但对于原型上设置的任何成员(如类的方法),这都是错误的:
interface Whoops {
foo(): void;
a: number;
b: string;
}
class Oops implements Whoops {
foo() { }
a = 1;
b = "";
}
const oopsie = (w: Whoops) => ({ ...w });
oopsie(new Oops()).foo(); // no compiler error
// runtime error: oopsie(...).foo is not a function!
如果您直接编写类
声明,编译器将假定方法声明不可扩展:
declare class Whoops {
foo(): void;
a: number;
b: string;
}
const oopsie = (w: Whoops) => ({ ...w });
oopsie(new Whoops()).foo(); // compiler time error as expected
// foo does not exist on {a: number; b: string};
但不幸的是,这并不是一个好消息。因此,当您将数组扩展到一个对象中时,编译器认为所有的array
属性和方法都被复制,因此生成的对象符合array
接口,因此具有一个join()
方法。哎呀
Maaay也许有人可以更改标准库,这样就不再使用
interface Array
和interface ArrayConstructor
和declare var Array:ArrayConstructor
了,我们刚刚使用了declare class Array
,然后join()
将不再被认为是可扩展的,但我不确定。当我在自己的系统上本地尝试它时,它似乎可以工作,但我不能在操场或其他在线IDE中轻松地复制它,而且我无论如何都不喜欢使用内置类型,如数组
或者Maaaybe可以更改语言,以便在接口
s上标记非自有或不可枚举的属性,但我不会指望它(请参阅)
目前,这是TypeScript的设计限制。如果您对此有强烈的感受,可以访问microsoft/TypeScript#34780并对其进行测试