默认情况下,Typescript 可以防止这种情况发生,因此如果您这样做:
class A {}
let a = A();
你会得到一个错误:
类型值typeof A
不可调用。你的意思是包括
'新的'?
然而,有些对象可以在不使用new
关键字,基本上都是原生类型。
如果您查看 lib.d.ts,您可以看到不同构造函数的签名,例如:
字符串构造函数 https://github.com/Microsoft/TypeScript/blob/master/lib/lib.d.ts#L445:
interface StringConstructor {
new (value?: any): String;
(value?: any): string;
...
}
数组构造函数 https://github.com/Microsoft/TypeScript/blob/master/lib/lib.d.ts#L1243:
interface ArrayConstructor {
new (arrayLength?: number): any[];
new <T>(arrayLength: number): T[];
new <T>(...items: T[]): T[];
(arrayLength?: number): any[];
<T>(arrayLength: number): T[];
<T>(...items: T[]): T[];
...
}
正如你所看到的,无论有没有演员,总是有相同的演员new
关键词。
如果您愿意,当然可以模仿这种行为。
重要的是要理解,虽然 typescript 会检查以确保这种情况不会发生,但 javascript 不会检查,因此如果有人编写将使用您的代码的 js 代码,他可能会忘记使用new
,所以这种情况还是有可能的。
很容易检测到这种情况是否在运行时发生,然后按照您认为合适的方式处理它(抛出错误,通过使用返回实例来修复它new
并记录下来)。
这是一篇讨论它的帖子:创建实例而不使用 new https://muffinresearch.co.uk/js-create-instances-without-new/(普通 js),但 tl;dr 是:
class A {
constructor() {
if (!(this instanceof A)) {
// throw new Error("A was instantiated without using the 'new' keyword");
// console.log("A was instantiated without using the 'new' keyword");
return new A();
}
}
}
let a1 = new A(); // A {}
let a2 = (A as any)(); // A {}
(操场上的代码 https://www.typescriptlang.org/play/#src=class%20A%20%7B%0D%0A%09constructor()%20%7B%0D%0A%09%09if%20(!(this%20instanceof%20A))%20%7B%0D%0A%09%09%09return%20new%20A()%3B%0D%0A%09%09%7D%0D%0A%09%7D%0D%0A%7D%0D%0A%0D%0Alet%20a1%20%3D%20new%20A()%3B%20%2F%2F%20A%20%7B%7D%0D%0Alet%20a2%20%3D%20(A%20as%20any)()%3B%20%2F%2F%20A%20%7B%7D)
Edit
据我所知,不可能让编译器理解这一点A
可以在没有new
关键字而不强制转换它。
我们可以做得比把它投射到更好一点any
:
interface AConstructor {
new(): A;
(): A;
}
let a2 = (A as AConstructor)(); // A {}
我们不能做那些正在做的事情的原因是(即)Array
in lib.d.ts
:
interface Array<T> {
...
}
interface ArrayConstructor {
...
}
declare const Array: ArrayConstructor;
他们在这里使用吗Array
一次作为类型,一次作为值,但类既是类型又是值,因此尝试执行此技巧将以:
重复的标识符“A”