网站搜索

在 TypeScript 2.0 中,如何为 @types npm 命名空间(DefinitelyTyped 仓库)中不可用的模块创建一个单独的声明文件?


在一个 TypeScript 项目中,我需要使用 bytewise npm 模块。这个包在 DefinitelyTyped npm 命名空间中没有类型定义,所以我不能使用 TypeScript 文档中描述的方法:

npm install --save-dev @types/bytewise

由于该模块没有类型声明,因此无法使用它,因为 tsc 会报错:error TS2307: Cannot find module 'bytewise'。

为了解决这个问题,我为 bytewise 编写了一个声明文件,并将其添加到 node_modules/@types/bytewise/index.d.ts,效果非常好。

然而,这是一个繁琐的常见模式:我使用一个没有 @types 声明的小型 npm 库,在 node_modules/@types 下创建一个目录,添加一个包含该库声明的 index.d.ts 文件,然后在 git 中强制添加该文件(因为 node_modules 默认被忽略)。

显然,我并不打算永远在我的私有 node_modules 目录下维护这些声明,最终我希望能将它们贡献回 DefinitelyTyped,以便以后更容易安装,但我不想为每个正在使用的库创建单独的目录/文件,我更希望在项目根目录下有一个包含所有 npm 上不可用声明的 vendor.d.ts 文件。大概像这样(这是我目前在项目中使用的):

import bl = require("bl");
import {Stream} from "stream";

declare module "bytewise" {
  export function encode(val: any): bl;
  export function decode(val: bl): any;
  export const buffer: boolean;
  export const type: string;
}

declare module "JSONStream" {
  export function parse(patternOrPath?: string): Stream;
  export function stringify(open?: string, sep?: string, close?: string);
}

问题是:我如何使这些声明对我项目中的所有文件可用?我已经尝试修改 tsconfig.json,在入口点之前包含它:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "noImplicitAny": false,
    "removeComments": true,
    "preserveConstEnums": true,
    "outDir": "out",
    "sourceMap": true
  },
  "files": [
    "vendor.d.ts",
    "index.ts"    
  ]
}

但在我有 import * as bytewise from "bytewise"; 的文件中仍然会出现 error TS2307: Cannot find module 'bytewise'.。我也尝试添加一个指向 vendor.d.ts 的 /// <reference path="..." /> 注释,但得到了同样的错误。我真的需要为每个 npm 模块都有一个单独的声明文件,还是我遗漏了什么?

答案#1

只需在你的项目中包含 vendor.d.ts,无需特殊配置,但有一个关键修改:将顶部的两个导入移动到该行之后

declare module "bytewise" {

任何未在声明中列出的导出或导入都会导致失败,并出现类似这样的隐晦信息:

Error:(3, 16) TS2665:Invalid module name in augmentation. Module 'bytewise' resolves to an untyped module at 'my-project/node_modules/bytewise/bytewise.js'.