网站搜索

通过新的定义文件向现有库 TypeScript 类型添加


我正在使用这个库 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/**/*"
  ]
}

答案#1

你可以尝试模块增强。你不必声明一个新模块。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"]
 ...

在项目根目录的新 typings 文件夹中添加一个 index.d.ts 文件,并将内容放入其中。

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

重要的是先添加第一个导入,因为然后会将 Koa 类型导入到你的全局文件中,然后你就可以覆盖它们。

答案#2

向 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 模块类型。

相关文章