2017-05-03 148 views
1

我试图扩展Telerik的Kendo UI类之一,Window小部件。我正在使用TypeScript 2.2.2。在TypeScript中扩展Kendo UI窗口

仅供参考,这是Window的定义。我只包括与这个问题相关的部分。

class Window extends kendo.ui.Widget { 
    static extend(proto: Object): Window; 
    constructor(element: Element, options?: WindowOptions); 
    content(): string; 
    content(content?: string): kendo.ui.Window; 
    content(content?: JQuery): kendo.ui.Window; 
} 

我想重写content(string)方法。我正在使用this example作为我的代码的基础。所以,我有以下几点:

export class AngularizedWindow extends kendo.ui.Window { 
    constructor(element: Element, options?: kendo.ui.WindowOptions) { 
     super(element, options); 
    } 

    content(content?: string) : kendo.ui.Window { 
     console.log("Setting content"); 
     return super.content(content); 
    } 
} 

但是,它给了我这个错误:

ts\widgets\AngularizedWindow.ts(2,18): error TS2415: Class 'AngularizedWindow' incorrectly extends base class 'Window'.
Types of property 'content' are incompatible.
Type '(content?: string) => Window' is not assignable to type '{(): string; (content?: string): Window; (content?: JQuery): Window; }'.
Type 'Window' is not assignable to type 'string'.

我在做什么错误?我不明白如何解释这个错误。

回答

1

的“不能分配给”错误消息类型,正确格式化的时候,是

{ 
    (): string; 
    (content?: string): Window; 
    (content?: JQuery): Window; 
} 

这是具有3个所谓的callable signatures一个类型,它描述的东西,可以以三种方式之一调用:

  • 不带参数,返回一个字符串
  • 可选字符串参数,使用可选的JQuery argume返回窗口
  • NT,返回窗口

这是打字稿如何代表函数重载 - 就在剑道Window宣布content的实际类型,因为它有3个重载的变种:

content(): string; 
content(content?: string): kendo.ui.Window; 
content(content?: JQuery): kendo.ui.Window; 

JavaScript没有函数重载,所以打字稿会尽可能地模拟它,当你使用重载的方法时它会有效。

但是,当你正在实现(或覆盖)重载方法时,typescript是没有帮助的。您只能有一个实现,并且它必须在运行时处理所有可能的参数组合。所以,你的扩展类必须重复所有重载的声明content(),并提供一个实现中,与所有申报变种兼容,能够处理所有的人,在这里的例子说明:https://www.typescriptlang.org/docs/handbook/functions.html#overloads

我有剑道UI没有经验,所以我只是做了小例子,基于有关与打字稿2.3编译和node.js中运行代码:

base.ts

export class Widget {} 
export class Element {} 
export class WindowOptions {} 
export class JQuery {} 

export namespace kendo { 
    export namespace ui { 

     export class Window extends Widget { 
      static extend(proto: Object): Window {return null} 
      constructor(element: Element, options?: WindowOptions) { super() } 
      content(): string; 
      content(content?: string): Window; 
      content(content?: JQuery): Window; 
      content(content?: string | JQuery): Window | string { 
       return null; 
      } 
     } 

    } 
} 

d。TS

import { WindowOptions, JQuery, kendo } from './base'; 

export class AngularizedWindow extends kendo.ui.Window { 
    constructor(element: Element, options?: WindowOptions) { 
     super(element, options); 
    } 

    content(): string; 
    content(content?: string): kendo.ui.Window; 
    content(content?: JQuery): kendo.ui.Window; 

    content(content?: string | JQuery) : kendo.ui.Window | string { 
     if (typeof content === 'undefined') { 
      console.log('implementation 1'); 
      return super.content(); 

     } if (typeof content === 'string') { 
      console.log('implementation 2'); 
      return super.content(content); 


     } else { // ought to be jQuery 
      console.log('implementation 3'); 
      return super.content(content); 
     } 
    } 
} 

let a = new AngularizedWindow(null); 

a.content(); 
a.content('b'); 
a.content({}); 

编译和运行

./node_modules/.bin/tsc base.ts d.ts 
node d.js 

它打印

implementation 1 
implementation 2 
implementation 3 

现在,当你看一下例子代码,它引出了一个问题:是否content()真的需要所有这些超载声明?它看起来像实现,即采用联合类型并返回联合类型的实现,足以处理所有用例。

但是,如果不超载,此代码不能编译:

let s: string = a.content(); 

错误:

d.ts(32,5): error TS2322: Type 'string | Window' is not assignable to type 'string'. 
    Type 'Window' is not assignable to type 'string'. 

所以,重载允许描述参数类型之间的关系和返回类型。但是,这种关系不是由编译器在实施中强制执行的。这是值得商榷的额外超载带来的复杂性是值得的,因为在this comment by one of typescript developers表示:

Realistically, JavaScript does not have function overloading and in general I advise people to just not use overloading at all. Go ahead and use union types on parameters, but if you have multiple distinct behavioral entry points, or return types that differ based on inputs, use two different functions! It ends up being clearer for callers and easier for you to write.

+0

所以,如果我理解你,我需要将三个重载(没有任何实现)添加到我的课,然后加入'content()'的实现方法?是对的吗? – Amy

+0

是的。我在答案中增加了一个例子。 – artem