Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding to existing library typescript types with a new definition file

I’m using this library https://github.com/chentsulin/koa-bearer-token which adds an extra property to the koa libraries request object like ctx.request.token. So if I use the koa types directly I get an error which tells me the token property doesn’t exist on ctx.request.token.

My current solution

I created a type definition file called koa-bearer-token.d.ts which contains types for the library and exports for the extended koa context/request type:

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};
}

Then I use this in other files like:

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

Why I'm asking this question

This works now but I’m concerned it isn’t the best way because it wouldn’t work if I need to add more properties in the future, ideally I want to just create a koa.d.ts file that adds to the libraries types then I can carry on using import {Context} from 'koa'; instead of import {ContextWithToken} from 'koa-bearer-token'; but when I create koa.d.ts it overwrites all the library types instead of adding on top of them.

Here is my tsconfig.json in case it helps

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "noImplicitAny": true,
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist",
    "baseUrl": ".",
    "paths": {
      "*": [
        "node_modules/*",
        "src/@types/*"
      ]
    }
  },
  "include": [
    "src/**/*"
  ]
}
like image 583
Dan Webb Avatar asked Jul 12 '18 05:07

Dan Webb


2 Answers

You can try with module augmentation. You don't have to declare a new module. Typescript is going to merge both modules and you should have the legacy koa typings plus your new ones.

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

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

The tricky thing is that it has to be placed just after the koa import. So, I would suggest to set this new change in a separated file so it is easy to apply your change everywhere.

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

Hope that helps

Regarding you have said, I would say it is possible.

Change your tsconfig in order to add a global d.ts file.

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

Add an index.d.ts file in this new typings folder in the root directory of your project and place in it.

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

It is important to add the first import as then is importing the koa typings to your global file and then you can override them.

like image 116
kimy82 Avatar answered Sep 20 '22 13:09

kimy82


An alternate more extensible solution to adding the types to koa-bearer-token.d.ts would be to add a file like koa-extensions.d.ts and add any extra properties there like so:

import {Context, Request} from 'koa';

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

    interface KoaContext extends Context {
        request: KoaRequest
    }
}

export = KoaExtensions;

Then the extended types can be imported:

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

This is an improvement on my initial solution but it still seems like I should be able to globally augment the Koa module types in a local koa.d.ts file.

like image 37
Dan Webb Avatar answered Sep 19 '22 13:09

Dan Webb