使用新的定义文件将其添加到现有的库打字稿类型中

时间:2018-07-12 05:01:50

标签: typescript types koa

我正在使用此库https://github.com/chentsulin/koa-bearer-token,该库向koa库请求对象(如ctx.request.token)添加了额外的属性。因此,如果我直接使用koa类型,则会收到一条错误消息,告诉我token上没有ctx.request.token属性。

我当前的解决方案

我创建了一个名为koa-bearer-token.d.ts的类型定义文件,其中包含库的类型并导出了扩展的koa上下文/请求类型:

declare module 'koa-bearer-token' {
    import {Context, Request, Middleware} from 'koa';

    interface Options {
        queryKey?: string;
        bodyKey?: string;
        headerKey?: string;
        reqKey?: string;
    }

    interface RequestWithToken extends Request {
        token?: string
    }

    interface ContextWithToken extends Context {
        request: RequestWithToken
    }

    export default function bearerToken(options?: Options): Middleware;
    export {RequestWithToken, ContextWithToken};
}

然后我在其他文件中使用它,

import {ContextWithToken} from 'koa-bearer-token';
const someFunction = (ctx: ContextWithToken) => {
    const token = ctx.request.token; // <-- No longer errors
};

为什么我要问这个问题

现在可以使用,但是我担心这不是最好的方法,因为如果将来我需要添加更多属性,那么它将无法使用,理想情况下,我只想创建一个添加以下内容的koa.d.ts文件到库类型,然后我可以继续使用import {Context} from 'koa';而不是import {ContextWithToken} from 'koa-bearer-token';,但是当我创建koa.d.ts时,它将覆盖所有库类型,而不是在它们之上添加。

这是我的tsconfig.json,以防万一

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "paths": {
      "*": [
        "node_modules/*",
        "src/@types/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ]
}

3 个答案:

答案 0 :(得分:4)

您可以尝试使用模块扩充。您不必声明新模块。 Typescript将要合并这两个模块,因此您应该具有传统的koa类型以及新的类型。

import * as koa from "koa"
declare module 'koa'{
    interface Request {
        token: string;
    }
}

declare const c: koa.Request;
c.token = 'tre';

棘手的是,必须在导入koa之后立即放置它。因此,我建议将此新更改设置在单独的文件中,以便轻松将更改应用于所有地方。

import * as koa from "koa";
import '<path to>koachanges';

希望有帮助

关于您所说的,我会说有可能。

更改您的tsconfig,以添加全局d.ts文件。

 ...
 "typeRoots": ["./node_modules/@types", "./typings"]
 ...

在项目的根目录下的这个新的types文件夹中添加index.d.ts文件,并将其放置在其中。

import * as Koa from 'koa';
declare module 'koa'{
    interface Request {
        token: string;
    }
}

重要的是添加第一个导入,然后再将koa类型导入到全局文件中,然后您可以覆盖它们。

答案 1 :(得分:0)

将类型添加到koa-bearer-token.d.ts的另一种可扩展性更强的解决方案是添加类似koa-extensions.d.ts的文件,并在其中添加任何其他属性,如下所示:

import {Context, Request} from 'koa';

declare namespace KoaExtensions {
    interface KoaRequest extends Request {
        token?: string
    }

    interface KoaContext extends Context {
        request: KoaRequest
    }
}

export = KoaExtensions;

然后可以导入扩展类型:

import {KoaContext} from './@types/koa-extensions';
const someFunction = (ctx: KoaContext) => {
    const token = ctx.request.token; // <-- No longer errors
};

这是我最初的解决方案的一项改进,但看起来我仍然应该能够在本地koa.d.ts文件中全局扩展Koa模块类型。

答案 2 :(得分:0)

我需要做同样的事情才能向淘汰赛中添加东西。我创建了一个my-ko-additions.d.ts文件,并以完成Knockout声明的相同方式实现了该文件:

interface KnockoutStatic {
    additionalFunc1(input: string): string;
    additionalFunc2(input: string): string;
}

declare var ko: KnockoutStatic;

declare module "knockout" {
    export = ko;
}

然后我只需说ko.additionaFunc1('abc')就可以实现和使用这些功能。