Nyp*_*pan 140 constructor interface typescript
我在解决界面中定义构造函数的工作方式时遇到了一些麻烦.我可能完全误解了一些事情.但是我已经寻找了很长一段时间的答案,我找不到与此相关的任何内容.
如何在TypeScript类中实现以下接口:
interface MyInterface {
new ( ... ) : MyInterface;
}
Run Code Online (Sandbox Code Playgroud)
Anders Hejlsberg在此视频中创建了一个包含类似内容的界面(大约14分钟).但对于我的生活,我无法在课堂上实现这一点.
我可能误解了一些事情,我没有得到什么?
编辑:
澄清.用"new(...)"我的意思是"任何东西".我的问题是我无法得到这个工作的最基本版本:
interface MyInterface {
new () : MyInterface;
}
class test implements MyInterface {
constructor () { }
}
Run Code Online (Sandbox Code Playgroud)
这不是为我编译我得到"类'测试'声明接口'MyInterface'但没有实现它:类型'MyInterface'需要一个构造签名,但类型'test'在尝试编译它时缺少一个.
编辑:
因此,在研究了这一点后,给出了反馈意见.
interface MyInterface {
new () : MyInterface;
}
class test implements MyInterface {
constructor () => test { return this; }
}
Run Code Online (Sandbox Code Playgroud)
是无效的TypeScript,这不能解决问题.您无法定义构造函数的返回类型.它将返回"测试".下面的签名:class test {constructor(){}}似乎是"new()=> test"(通过将"代码"粘贴在在线编辑器中,将鼠标悬停在"class"上获得).这就是我们想要的和我认为的.
任何人都可以在实际编译时提供此类或类似的示例吗?
编辑(再次......):
所以我可能想出了为什么可以在接口中定义它但不能在TypeScript类中实现的想法.以下工作:
var MyClass = (function () {
function MyClass() { }
return MyClass;
})();
interface MyInterface {
new () : MyInterface;
}
var testFunction = (foo: MyInterface) : void => { }
var bar = new MyClass();
testFunction(bar);
Run Code Online (Sandbox Code Playgroud)
那么这只是TypeScript的一个功能,可以让你接口javascript吗?或者是否可以在TypeScript中实现它而无需使用javascript实现类?
Rya*_*ugh 141
接口中的构造签名不能在类中实现; 它们仅用于定义定义"新"功能的现有JS API.这是一个涉及new可以工作的接口签名的示例:
interface ComesFromString {
name: string;
}
interface StringConstructable {
new(n: string): ComesFromString;
}
class MadeFromString implements ComesFromString {
constructor (public name: string) {
console.log('ctor invoked');
}
}
function makeObj(n: StringConstructable) {
return new n('hello!');
}
console.log(makeObj(MadeFromString).name);
Run Code Online (Sandbox Code Playgroud)
这会为您可以调用的内容创建一个实际约束makeObj:
class Other implements ComesFromString {
constructor (public name: string, count: number) {
}
}
makeObj(Other); // Error! Other's constructor doesn't match StringConstructable
Run Code Online (Sandbox Code Playgroud)
Nil*_*ils 55
在我搜索完全相同的问题时,我去看看TypeScript-Team是如何做到的......
它们声明了一个接口,然后是一个名称与接口名称完全匹配的变量.这也是键入静态函数的方法.
示例来自lib.d.ts:
interface Object {
toString(): string;
toLocaleString(): string;
// ... rest ...
}
declare var Object: {
new (value?: any): Object;
(): any;
(value: any): any;
// ... rest ...
}
Run Code Online (Sandbox Code Playgroud)
我试过了,它就像魅力一样.
小智 12
来自官方文档
这是因为当类实现接口时,仅检查类的实例端。由于构造函数位于静态端,因此它不包含在此检查中。
相反,您需要直接使用类的静态部分。在此示例中,我们定义了两个接口,用于构造函数的 ClockConstructor 和用于实例方法的 ClockInterface。然后,为了方便起见,我们定义了一个构造函数 createClock,它创建传递给它的类型的实例:
interface ClockConstructor {
new (hour: number, minute: number): ClockInterface;
}
interface ClockInterface {
tick(): void;
}
function createClock(
ctor: ClockConstructor,
hour: number,
minute: number
): ClockInterface {
return new ctor(hour, minute);
}
class DigitalClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("beep beep");
}
}
class AnalogClock implements ClockInterface {
constructor(h: number, m: number) {}
tick() {
console.log("tick tock");
}
}
let digital = createClock(DigitalClock, 12, 17);
let analog = createClock(AnalogClock, 7, 32);
Run Code Online (Sandbox Code Playgroud)
从设计的角度来看,通常不会在接口中指定构造函数要求。接口应该描述您可以对对象执行的操作。如果需要的话,应该允许实现该接口的不同类需要不同的构造函数参数。
例如,如果我有一个界面:
interface ISimplePersistence {
load(id: number) : string;
save(id: number, data: string): void;
}
Run Code Online (Sandbox Code Playgroud)
我可能有将数据存储为 cookie 的实现,它不需要构造函数参数,以及将数据存储在数据库中的版本,它需要连接字符串作为构造函数参数。
如果您仍然想在接口中定义构造函数,有一种肮脏的方法可以做到这一点,我用它来回答这个问题:
好吧,带有构造签名的接口并不意味着任何类都可以实现(乍一看,对于像我这样具有C#/ Java背景的人来说,这看起来很奇怪,但是给了机会)。略有不同。
片刻,可以将其视为带有调用签名的接口(例如Java世界中的@FunctionalInterface)。其目的是描述一种功能类型。所描述的签名应该由功能对象满足...而不仅仅是任何高级功能或方法。它应该是一个知道如何构造对象的函数,该函数在使用new关键字时会被调用。
因此,带有构造签名的接口定义了构造函数的签名!您的类的构造函数应符合接口中定义的签名(在构造函数实现接口时考虑)。就像工厂!
这是一段简短的代码,试图演示最常见的用法:
interface ClassicInterface { // old school interface like in C#/Java
method1();
...
methodN();
}
interface Factory { //knows how to construct an object
// NOTE: pay attention to the return type
new (myNumberParam: number, myStringParam: string): ClassicInterface
}
class MyImplementation implements ClassicInterface {
// The constructor looks like the signature described in Factory
constructor(num: number, s: string) { } // obviously returns an instance of ClassicInterface
method1() {}
...
methodN() {}
}
class MyOtherImplementation implements ClassicInterface {
// The constructor looks like the signature described in Factory
constructor(n: number, s: string) { } // obviously returns an instance of ClassicInterface
method1() {}
...
methodN() {}
}
// And here is the polymorphism of construction
function instantiateClassicInterface(ctor: Factory, myNumberParam: number, myStringParam: string): ClassicInterface {
return new ctor(myNumberParam, myStringParam);
}
// And this is how we do it
let iWantTheFirstImpl = instantiateClassicInterface(MyImplementation, 3.14, "smile");
let iWantTheSecondImpl = instantiateClassicInterface(MyOtherImplementation, 42, "vafli");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
75954 次 |
| 最近记录: |