抽象接口不能用作数组中的类型 - 缺少属性

时间:2018-02-13 19:24:29

标签: javascript node.js typescript typescript2.0 tsc

我有这个界面:

export interface SceEvent {
  // ...
}

export interface SceMain {

  onComplete: () => void;

  onNextEvent: (ev: SceEvent) => void;

  getRawGeneratedCode: () => string;

  getStyledGeneratedCode: () => string;

}

我在几个看起来像这样的文件中实现了这个接口:

import {SceEvent, SceMain} from "../../interfaces";

export class CodeGenerator implements SceMain {

  private rawCode = '';
  private styledCode = '';
  public static pluginName = 'java-junit';

  constructor(){

  }

  getRawGeneratedCode() {
    return this.rawCode;
  }


  getStyledGeneratedCode() {
    return this.styledCode;
  }

  onComplete(){

  }


  onNextEvent(ev: SceEvent) {

  }

}

然后在另一个文件中,我导出了所有这些实现:

import {SceMain} from "./interfaces";

// generators
import * as javajunit from './values/java-junit';
import * as javatestng from './values/java-test-ng';
import * as nodejsmocha from './values/nodejs-mocha';
import * as nodejssuman from './values/nodejs-suman';


export const plugins : Array<SceMain>= [

  javajunit.CodeGenerator,
  javatestng.CodeGenerator,
  nodejsmocha.CodeGenerator,
  nodejssuman.CodeGenerator

];

但是我收到了这个错误:

  

Codeofnerator类型中缺少属性“onComplete”

我没理解,因为我的所有CodeGenerator类都实现了这个方法。

以下是图片中的错误...

enter image description here

有谁知道这里会发生什么?

2 个答案:

答案 0 :(得分:1)

plugins常量是SceMain 构造函数的数组,而不是SceMain 实例的数组。 SceMain的实例具有类似onComplete()的方法,但构造函数不具有(除非它恰好具有带正确签名的静态方法)。编译器警告您数组的元素不是SceMain的实例。

假设您确实打算创建一个构造函数数组(正如您在评论中提到的那样),您应该键入plugins,如:

export const plugins : Array<new() => SceMain>= [    
  javajunit.CodeGenerator,
  javatestng.CodeGenerator,
  nodejsmocha.CodeGenerator,
  nodejssuman.CodeGenerator    
];

类型new() => SceMain是生成SceMain实例的无参数构造函数的类型。 (如果构造函数接受参数,那么应该修改类型。)

你的困惑很可能源于这样一个事实:在TypeScript中,当你声明一个名为class的{​​{1}}时,它会创建一个名为class Foo {}类型,对应于该类的实例,以及一个名为Foo,它是该类的构造函数。值Foo不是Foo类型。但是,它是Foo类型。您可以使用new ()=>Foo类型运算符获取更具体类型的类构造函数(包括静态方法):typeoftypeof Foo构造函数的类型。您可以在TypeScript Handbook中详细了解这一点。

类型表达式和值表达式之间的区别很难解释,特别是因为TypeScript倾向于在两种表达式中使用相同的关键字来表示不同的(并且可能只是边缘相关)事物:

Foo

我不知道这是否清除了事情或使情况变得更糟。祝你好运!

答案 1 :(得分:0)

因为插件是构造函数的数组,而不是实例数组,所以类型需要更改:

//原始

plugins: Array<SceMain>

//改进了

plugins: Array<new() => SceMain>

感谢@jcalz的回答