Using TypeScript to create a state object in Koa

I am currently utilizing Koa () as the framework for my backend, which consists of Node.js + TypeScript.

Koa permits and recommends using the built-in `ctx.state` to store and pass data between different middleware functions. I have been adhering to this practice and it has been functioning seamlessly.

However, I am facing a challenge in implementing TypeScript with `ctx.state`, as it gets populated at runtime and I am unsure where to begin. I intend to structure `ctx.state`, particularly for the backend response, based on this interface (with various 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;
  };
}

While one approach could be importing this interface into each endpoint and employing some form of type assertion, that is precisely what I aim to avoid. I have scoured through the Koa documentation and Stack Overflow but have not come across any guidance on this matter.

Answer №1

After reviewing the Koa Type definitions, I was able to find a solution to my problem.

Within the types, they define:

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

With this information, it became simple to extend both interfaces (refer to https://www.typescriptlang.org/docs/handbook/declaration-merging.html): within my types, I added

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

  interface DefaultContext {
    customContextProp: string;
  }
}

Now, everything is properly typed throughout. Keep in mind that you can still create additional properties for both state and context within individual functions or middleware.

I hope this guidance can assist others experiencing the same issue.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

When using a function as a prop in a React component with Typescript generics, the type of the argument becomes unknown

React version 15 or 18. Typescript version 4.9.5. When only providing the argument for getData without using it, a generic check error occurs; The first MyComponent is correct as the argument of getData is empty; The second MyComponent is incorrect as t ...

How to avoid property name conflicts when extending interfaces in Typescript

Is it possible to achieve something like this using TypeScript, such as renaming a property? interface Person { name: string age: number } interface Pet { age: string } interface Zoo extends Pet, Person {} How can we prevent this error from ...

Adjusting the value of a mat-option depending on a condition in *ngIf

When working with my mat-option, I have two different sets of values to choose from: tempTime: TempOptions[] = [ { value: 100, viewValue: '100 points' }, { value: 200, viewValue: '200 points' } ]; tempTimesHighNumber: TempOpt ...

Adjusting the dimensions of the cropper for optimal image cropping

I am currently working on integrating an image cropper component into my project, using the react-cropper package. However, I am facing a challenge in defining a fixed width and height for the cropper box such as "width:200px; height:300px;" impo ...

Arranging Select Dropdown Options in a Specific Order using Angular 7 and Typescript

My select dropdown is populated dynamically with options fetched from a service using *ngFor. I am looking to customize the order of these options. Can this be achieved through Angular code? The array structure is as follows: console.log(this.paymentTyp ...

Determine whether an element is visible following a state update using React Testing Library in a Next.js application

I'm looking to test a NextJS component of mine, specifically a searchbar that includes a div which should only display if the "search" state is not empty. const SearchBar = () => { const [search, setSearch] = useState(""); const handleSear ...

Tips for scrolling ion-items vertically to the bottom and top using arrow icons in Ionic 4

I'm developing an Ionic 4 app with Angular and looking to incorporate Up and Down Arrow buttons for vertical scrolling from top to bottom and vice versa. ...

CLI package enables exporting API facilities

I have a mono repository containing a CLI package (packages/cli) and a web application (apps/web). I want to utilize the public API of the CLI within the web app. The CLI package is packaged with tsup: export default defineConfig({ clean: false, dts: ...

"Discover the power of Next.js by utilizing dynamic routes from a curated list

I am working on a Next.js application that has a specific pages structure. My goal is to add a prefix to all routes, with the condition that the prefix must be either 'A', 'B', or 'C'. If any other prefix is used, it should re ...

The number of keys in the related object must correspond to the length of the array in Advanced Generic Types

Can we achieve type safety across rows and columns by having one object define the structure of another? Starting Point: export interface TableColumn { name: string; type: "string" | "number" | "action"; id: string; } ...

Tips for ensuring that npm only creates one instance of a dependency when it is being used by multiple projects

Struggling a bit here. I am diving into npm and configuration files for the first time. The current challenge involves setting up a vue project (though it might not be directly related to the issue) with typescript and then reusing its code and components. ...

Is there a way for me to showcase a particular PDF file from an S3 bucket using a custom URL that corresponds to the object's name

Currently, I have a collection of PDFs stored on S3 and am in the process of developing an app that requires me to display these PDFs based on their object names. For instance, there is a PDF named "photosynthesis 1.pdf" located in the biology/ folder, and ...

Tips for Disabling ML5 Posenet

Looking to halt Posenet after completing app task private sketch(p: any) { p.setup = () => { this.poseNet = ml5.poseNet(p.createCapture(p.VIDEO), { outputStride: 8 }); this.poseNet.on(&apos ...

Is it advisable for a component to handle the states of its sub-components within the ngrx/store framework?

I am currently grappling with the best strategy for managing state in my application. Specifically, whether it makes sense for the parent component to handle the state for two subcomponents. For instance: <div> <subcomponent-one> *ngIf=&qu ...

Angular authentication guard does not redirect properly after returning a Promise<UrlTree>

My authentication guard is set up to control access to the /sign-in and /verify-email routes, allowing only users who are not logged in or have not verified their email: export const signInGuard: CanActivateFn = (activatedRouteSnapshot: ActivatedRouteSnap ...

What is causing the issue where search query parameters are not recognizing the initially selected option?

Hey, I'm having an issue with searchParams. The problem is that when I apply filters like "Breakfast, Lunch, Dinner", the first chosen option isn't showing up in the URL bar. For example, if I choose breakfast nothing happens, but if I choose lun ...

Creating custom disabled button styles using TailwindUI in a NextJS application

I had a NextJS application that utilized Atomic CSS and featured a button which becomes disabled if a form is left unfilled: <Button className="primary" onClick={handleCreateCommunity} disabled={!phone || !communi ...

Using TypeScript with React: Automatically infer the prop type from a generic parameter

I've developed a component that retrieves data from an API and presents it in a table. There's a prop that enables the fetched value to be displayed differently within the table. Here's how I currently have the prop types set up: // T repres ...

A guide on crafting a type definition for the action parameter in the React useReducer hook with Typescript

In this scenario, let's consider the definition of userReducer as follows: function userReducer(state: string, action: UserAction): string { switch (action.type) { case "LOGIN": return action.username; case "LOGOUT": return ""; ...

Mixing Jest and Cypress in a TypeScript environment can lead to Assertion and JestMatchers issues

When utilizing [email protected] alongside Jest, we are encountering TypeScript errors related to Assertion and JestMatchers. What is the reason for these TypeScript errors when using Jest and [email protected] in the same project? ...