2016-08-05 45 views
3

我已經創建了一個自定義Knockout擴展器,並且我無法擴展由Knockout定義文件提供的現有接口。如何在定義需要導入語句時擴展現有接口?

擴展器/ Numeric.ts

import * as ko from "knockout"; 

function Extender(target: KnockoutObservable<number>, options: IOptions = {}): KnockoutObservable<number> { 
    // ... 
}; 

interface IOptions { 
    // ... 
} 

export {Extender as NumericExtender, IOptions as INumericExtenderOptions} 

Boot.ts

import * as ko from "knockout"; 
import {NumericExtender} from "./Extenders/Numeric"; 

class Boot {  
    public constructor() { 
     ko.extenders.numeric = NumericExtender; 
    } 
} 

爲了讓有關ko.extenders.numeric編譯器,我需要延長現有的接口:

interface KnockoutExtenders { 
    numeric(target: KnockoutObservable<number>, options?: INumericExtenderOptions): KnockoutObservable<number>; 
} 

現在我在這裏遇到麻煩。爲了訪問INumericExtenderOptions,我需要一個import聲明:

import {INumericExtenderOptions} from "./Extenders/Numeric"; 

但是,當添加一個import語句,則該文件被認爲是一個模塊,which makes it impossible to extend an existing interface

有沒有辦法做到這一點,或將我需要移動IOptions到定義文件,以避免import

回答

2

看起來你正在使用全局版本的挖空聲明文件。我不認爲可以從模塊聲明文件中擴展全局範圍中定義的接口。有幾種解決方案:

  • 我認爲最簡單的解決方法是把你的界面到全局命名空間爲好。對於IOptions變爲:

    // index.d.ts 
    interface IOptions { 
        // ¯\_(ツ)_/¯ 
    } 
    
    interface KnockoutExtenders { 
        numeric(target: KnockoutObservable<number>, options?: IOptions): KnockoutObservable<number>; 
    } 
    

    現在,你可以在任何地方訪問IOptions和KnockoutExtenders具有數字功能,如申報文件仍然是全球性的。

  • 另一種解決方案是在模塊版本拉(我覺得這是我的首選解決方案,只是因爲你沒有污染的所有淘汰賽類型的全局命名空間)。在淘汰賽的情況下:typings install --save knockout。然後,只要需要,您就必須專門導入所需的類型。例如。你的numeric.ts變成

    // src/numeric.ts 
    import { Observable } from "knockout" 
    
    export function Extender(target: Observable<number>, options: IOptions = {}): Observable<number> { 
        // ¯\_(ツ)_/¯ 
    }; 
    
    export interface IOptions { 
        // ¯\_(ツ)_/¯ 
    } 
    

    然後你可以增加另一個聲明文件中的挖空模塊。例如:

    // index.d.ts 
    import { Observable } from "knockout" 
    import { IOptions } from './src/numeric' 
    
    declare module "knockout" { 
        interface Extenders { 
        numeric(target: Observable<number>, options?: IOptions): Observable<number> 
        } 
    } 
    

    那麼你應該能夠在你的應用程序的任何地方使用增強的擴展程序接口:

    // src/boot.js 
    import { extenders } from "knockout" 
    import { Extender } from "./numeric" 
    
    class Boot { 
        public constructor() { 
        extenders.numeric = Extender 
        } 
    } 
    
  • 一個最終的解決方案,可能是最好的解決你的問題,是使用模塊化的聲明文件,但要擴充全局模塊。你的數字。TS保持不變,你的聲明文件就變成了:

    import { IOptions } from './src/numeric' 
    
    declare global { 
        interface KnockoutExtenders { 
        numeric(target: KnockoutObservable<number>, options?: IOptions): KnockoutObservable<number> 
        } 
    } 
    

欲瞭解更多信息,看看在page on declaration merging from the typescript handbook.

+0

設法找到了一些時間來過這,我結束了使用第三解。目前沒有模塊版本的Knockout可用,所以第二種解決方案對於這種情況不起作用。 – Stijn

+0

奇怪。 'typings安裝knockout'肯定會安裝一個模塊淘汰聲明文件。但是,也許這不是你想要的文件? –

+0

我的意思是實際的圖書館:)不是類型。除非我誤解了事情,並且有一種方法可以「模塊化」圖書館? – Stijn