typescriptkoa

Koa state object with typescript


I'm using Koa (https://koajs.com/) as framework for my backend (NodeJs + TS).

It allows and suggest to use the built in ctx.state to save an pass data between different middlewares: I'm following this rule and it works perfectly from a functional point of view.

Btw, I can't figure out how to implement Typescript using this ctx.state, because it's populated in runtime and I don't know were to start. I want to format this ctx.state, especially the backend response, using this interface (and different extensions):

export interface ResObj {
  auth: any;
  data: any;
  dataTot?: number;
  error: {
    stack: string;
    code: number;
    message: string;
  };
  extra: any;
  message: string;
  status: number;
  tech: {
    needRefresh: boolean;
  };
}

Of course I could import this interface into every single endpoint and use some sort of type assertion, but that's just what I want to avoid. I've searched the Koa documentation and here on SO but can't find anything to guide me.


Solution

  • I finally found a solution looking at the Koa Type definitions.

    Inside types they declare:

    declare namespace Application {
        type DefaultStateExtends = any;
        /** This interface can be augmented by users to add types to Koa's default state */
        interface DefaultState extends DefaultStateExtends {}
        
        type DefaultContextExtends = {};
        /** This interface can be augmented by users to add types to Koa's default context */
        interface DefaultContext extends DefaultContextExtends {
          /** Custom properties. */
          [key: string]: any;
        }
    }
    

    Having this it's really easy to augment both interfaces (see https://www.typescriptlang.org/docs/handbook/declaration-merging.html) : inside my types I put

    declare module 'koa' {
      interface DefaultState {
        customStateProp: string;
      }
    
      interface DefaultContext {
        customContextProp: string;
      }
    }
    

    And now everything, everywhere, is typed correctly. Note that this system does not prevent you from creating additional properties for both state and context within individual functions or middleware.

    Hope this can help others who are facing the same problem.