21

我使用这样的记录方法安装了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

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

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

4

6 回答 6

12

您可以轻松扩展“淘汰赛”或任何其他 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;

有关模块和命名空间的更多信息,您可以查看关于模块命名空间的 TypeScript 文档并将它们一起使用。

干杯!

于 2017-06-29T15:08:20.867 回答
8

我发现使用语法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";
    }
}

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

于 2019-10-02T14:09:39.723 回答
3

问题是knockout键入文件使用export =语法并且它不是“增强友好”。将此作为参考。

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

declare global {
  interface KnockoutStatic {
    doSomething(): void;
  }
}
于 2016-10-04T14:40:58.983 回答
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());
于 2021-01-21T22:07:23.070 回答
0

您需要在模块之外创建界面。不要export 声明它。

module example  {
   //...do stuff
}
 
interface KnockoutStatic {
  doSomething(): void;
}

您可以将其添加到单独的文件中,例如添加界面扩展以保持干净。

于 2016-10-04T14:33:13.893 回答
0

我试图扩展 Express Request 对象,以便我可以req.log.info用来记录一些东西。以下设置对我有用

// tsconfig.json
{
  "compilerOptions": {
    ...,
    "baseUrl": ".",
    "paths": {
      "*": ["node_modules/*", "types/*"]
    }
  },
  "include": ["src/**/*"],
  "files": ["./types/express-extension.d.ts"],
  "ts-node": {
    "files": true
  }
}

// types/express-extension.d.ts
import 'express';

declare module 'express' {
  export interface Request {
    log?: {
      debug: (str: string) => void,
      info: (str: string) => void,
      warn: (str: string) => void,
      error: (str: string) => void,
    }
  }
}

我的文件结构如下所示:

src
|_ ...
types
|_ express-extension.d.ts
tsconfig.json
package.json
于 2021-11-22T04:00:39.597 回答