在Typescript中,为库中的类创建扩展方法

时间:2017-07-31 08:48:27

标签: typescript ionic-framework

我想为来自库的现有类添加一些方法。

已知某些基本类型,例如StringElement可以通过interface进行扩展,并添加prototype

interface String {
 extFunc():Function;
}

String.prototype.extFunc = function () {
  //blabla
};

"a".extFunc();

我也找到了添加Observable<T>扩展方法的方法。

declare module 'rxjs/Observable' {
  interface Observable<T> {
    foo: String;
  }
}
Observable.prototype.foo= "bar";
console.log(Observable.of("a").foo);

但是当我尝试对NavController(来自离子的lib)做同样的事情时,它会将整个NavController覆盖到我声明的接口。

declare module 'ionic-angular' {
  interface NavController {
    replace(page: Page): Promise<any>;
  }
}
navCtrl.replace(...); //ok
navCtrl.push(...); //original function => "not exist"

有谁知道在这些课程中添加扩展方法的最佳方法是什么?感谢〜

修改 有实际的代码

import {Component} from '@angular/core';
import {NavController} from 'ionic-angular';

import {GuidePage} from '../guide/guide.component';

@Component({
  selector: 'page-home',
  templateUrl: 'home.component.html'
})
export class HomePage {
  pageName = "home";

  // navCtrl is come from angular2's Dependency Injection,
  // it may not suitable to extend NavController
  constructor(public navCtrl: NavController) {}

  gotoGuide(): void {
    //wanna replace this
    this.navCtrl.push(GuidePage).then(() => {
      let index = this.navCtrl.getActive().index;
      this.navCtrl.remove(index - 1);
    });

    //with this custom extension method 
    //this.navCtrl.replace(GuidePage);
  }
}

2 个答案:

答案 0 :(得分:1)

好的,我引用this answer并使用以下代码解决我的问题。

polyfill.ts

import {Page} from 'ionic-angular/navigation/nav-util';
// the class we wanna create extension method
import {NavController} from 'ionic-angular/navigation/nav-controller';
// ionic provide this as NavController
import {NavControllerBase} from 'ionic-angular/navigation/nav-controller-base';

// add extension method on both class via interface
declare module "ionic-angular/navigation/nav-controller" {
  interface NavController {
    // replacePage?: typeof replacePage;
    replacePage(page: Page, data?: any);
  }
}
declare module "ionic-angular/navigation/nav-controller-base" {
  interface NavControllerBase {
    // replacePage?: typeof replacePage;
    replacePage(page: Page, data?: any);
  }
}

// define extension method 
function replacePage(this: NavController, page: Page, data?: any): Promise<any> {
  return this.push(page, data).then(() => {
    let index = this.getActive().index;
    this.remove(index - 1);
  });
}

// finally add this function to the class that ionic provide
NavControllerBase.prototype.replacePage = replacePage;

用法:

constructor(private navCtrl: NavController)
foo(){
    this.navCtrl.replacePage(HomePage, {nextPage: OtherPage});
}

这种方法可以在其他类上添加扩展方法,希望这能帮到别人。

答案 1 :(得分:0)

您的问题是如何扩展类,但您的代码显示了接口。

如何从库扩展类:

class LibraryThing {
    // this is a class from a library
    doSomething(){
    }
}

class MyThing extends LibraryThing {
    // here you can add your own methods to the existing class
    doMyThing(){
    }
}

现在您可以创建一个MyThing实例,它将包含所有库方法和您自己的方法:

let t = new MyThing();
t.doSomething();
t.doMyThing();

如果您想使用接口,您可以简单地实现它们。您可以实现现有的库接口,并使用您自己的接口补充它们

interface LibraryInterface {}
interface MyOwnInterface {}

class CoolThing implements LibraryInterface, MyOwnInterface {
    // this class uses methods from the library interface and your own
}

使用打字稿时不需要原型。

修改

我没试过,如果这样可行,但是你可以传递自己的扩展navcontroller的类,而不是在构造函数中传递navcontroller。

import {Component} from '@angular/core';

import {CustomController} from '../mystuff/customcontroller';    
import {GuidePage} from '../guide/guide.component';

@Component({
  selector: 'page-home',
  templateUrl: 'home.component.html'
})
export class HomePage {
  pageName = "home";

  // here we receive our own CustomController
  constructor(public navCtrl: CustomController) {}

  gotoGuide(): void {
    this.navCtrl.myOwnCustomStuff();
  }
}

在CustomController中,您可以导入Navcontroller并对其进行扩展:

import { Injectable } from '@angular/core'
import {NavController} from 'ionic-angular'

@injectable()
export class CustomController extends NavController {
}

我还没有测试过这是否允许使用离子成分!

您还必须注册自己的新注射剂作为角度DI的提供者,请按照your link

中的步骤进行操作