如何扩展在外部库中声明的接口d.ts?

时间:2016-10-04 13:37:20

标签: typescript typescript2.0

我使用这样的文档化方法安装了knockout个定义。

npm install @types/knockout

效果很好,我可以在任何地方导入它。

import * as ko from "knockout";

但是,我坚持使用某些自定义内容扩展KnockoutStatic界面。我正在尝试迁移基于<reference ... />namespace的大型TS应用程序以使用模块。在此之前,我轻松地将扩展接口声明为并且声明已合并。假设我的扩展名看起来像这样。

interface KnockoutStatic {
  doSomething(): void;
}

我尝试创建一个KnockoutExtensions.d.ts文件,我将其声明为这样。

import "knockout";

declare module "knockout" {
  export interface KnockoutStatic {
    doSomething(): void;
  }
}

但是当我在某处导入knockout和我的扩展程序时,TS仍然无法解析doSomething次来电。

import * as ko from "knockout";
import "./KnockoutExtensions";

ko.doSomething(); // error

使用TypeScript 2.0和新的d.ts子系统扩展库接口的正确方法是什么?

我正在使用安装了TypeScript 2.0的Visual Studio 2015 Update 3。

5 个答案:

答案 0 :(得分:3)

问题是knockout输入文件使用的是export =语法,而且它不是&#34;增强友好&#34;。请参阅this作为参考。

对我来说最简单的解决方案是将扩展名包装在declare global { }中,因为knockout输入文件会声明全局范围内的所有内容。

declare global {
  interface KnockoutStatic {
    doSomething(): void;
  }
}

答案 1 :(得分:2)

您可以轻松扩展'knockout'或任何其他TypeScript命名空间。

示例:创建knockout-extension.d.ts文件

/// <reference path="<path-to-typings-dir>/knockout/index.d.ts" />

declare module 'knockout' {

  export interface CustomType {

    customField: string;

    customMethod(arg1: number, arg2: boolean): boolean;
  }

  namespace customNamespace {

    export interface AnotherCustomType {
      customField1: string;
      customField2: boolean;
    }
  }

  // NOTE: extending existing interface
  export interface KnockoutStatic {
    customMethod(): void;
  }
}
  

注意:确保TypeScript编译器选择此文件。

使用扩展模块中新定义的类型。

// one way
import { CustomType } from 'knockout';

const foo: CustomType;

// second way
import * as kc from 'knockout';

const foo: kc.CustomType;
const bar: kc.customNamespace.AnotherCustomType;

有关模块和命名空间的更多信息,您可以检查ModulesNamespaces上的TypeScript文档并使用它们together

干杯!

答案 2 :(得分:0)

您需要在模块外部创建界面。 通过导出声明它。

module example { //...do stuff }

interface KnockoutStatic { doSomething(): void; }

您可以在文件中添加界面扩展名以保持其清洁。

答案 3 :(得分:0)

我发现winston使用export =语法也有同样的问题。当发现react做同样的事情:https://www.credera.com/blog/technology-solutions/typescript-adding-custom-type-definitions-for-existing-libraries/时,我发现此页面很有帮助。

他们推荐的解决方案是这样的:

import 'react';

declare module 'react' {
    interface OlHTMLAttributes<T> {
        type?: "1" | "a" | "A" | "i" | "I";
    }
}

只需导入模块,然后声明它即可允许此声明块中的任何接口扩展现有接口,并且在代码的其他部分,您可以像往常一样继续使用该接口;也就是说,您仍将导入reactwinstonknockout,并且您会看到这些新的界面成员。您不必开始引用自定义界面或类似的东西。

答案 4 :(得分:0)

此代码适用于我

// observable.ts
export class Observable<T> {
  // ... implementation left as an exercise for the reader ...
}

// map.ts
import { Observable } from "./observable";
declare module "./observable" {
  interface Observable<T> {
    map<U>(f: (x: T) => U): Observable<U>;
  }
}
Observable.prototype.map = function (f) {
  // ... another exercise for the reader
};

// consumer.ts
import { Observable } from "./observable";
import "./map";
let o: Observable<number>;
o.map((x) => x.toFixed());