首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么这是允许的?number[] ={.[1,2,3] }

为什么这是允许的?number[] ={.[1,2,3] }
EN

Stack Overflow用户
提问于 2020-05-11 23:57:30
回答 1查看 81关注 0票数 3

刚刚在我的打字本代码库中发现了一个重要的错误,因为这是允许的:

代码语言:javascript
复制
const nums: number[] = { ...[1, 2, 3] } // should have been [ ...[1,2,3] ]
a.join('-')
// runtime error: a.join is not a function 

游乐场

为什么一个数组被解构为一个对象,分配给数组,在那里它可以导致一个很容易预防的运行时异常?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-12 01:29:35

这是TypeScript的一个设计限制;参见微软/打字稿#34780

类型系统没有将interface成员标记为“属于”或可枚举的方法,因此编译器假定所有成员都是通过扩展运算符复制的。作为一种启发式,这通常是足够的,但是它对原型上的任何成员都是错误的,就像类的方法一样:

代码语言:javascript
复制
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!

如果直接编写class声明,编译器将假设方法声明不可扩展:

代码语言:javascript
复制
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};

但不幸的是,interface并不是class。因此,当将数组扩展到对象时,编译器认为所有的Array属性和方法都是复制的,因此得到的对象符合Array接口,因此有一个join()方法。奥普西。

如果有人可以更改标准库,那么我们就可以使用interface Array<T>interface ArrayConstructordeclare var Array: ArrayConstructor,而不是declare class Array<T>,然后join()就不再被看作是可扩展的了,但我不确定。当我在自己的系统上在本地试用时,它似乎很有效,但我无法在游乐场或其他在线IDE中轻松地复制它,而且与Array这样的内置类型混为一谈也不是我喜欢做的事情。

或者可以更改语言,以便在interfaces上标记非自有或不可枚举的属性,但我不指望它(见微软/打字稿#9726)。

目前,这是TypeScript的一个设计限制。如果你对此有强烈的感觉,你可以转到microsoft/TypeScript#34780,给它一个并描述你是如何被它咬的,但我不知道它会有多大的好处。

好吧,希望这能帮上忙,祝你好运!

操场链接到代码

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61741437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档