0

First of all, I know this topic looks really similar to this other topic talking about extending Express Request object using Typescript

Basically, I try to do the same thing but with Polka this time

Has anyone managed to do this?

The path I followed is similar to this

At project root lever I created this folder structure :

app/
├─ src/
│  ├─ @types/
│  │  ├─ polka/
│  │  │  ├─ index.d.ts

And I add this in index.d.ts

import * as polka from "polka";

declare global {
  namespace polka {
    interface Request {
      foo: string;
    }
  }
}

I also updated my tsconfig.json by adding this :

"typeRoots": [ "@types" ]

The middlware where I assign a value to the request looks like this

import type { Middleware } from "polka";

export const dummyMiddleware: Middleware = (req, res, next) => {

  req.foo = "hello";
  next();
};

By doing this I have this Typescript error :

Property 'foo' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs,

When I look at the Polka Middleware definition I see this type in generic.

I tried to do something like this

import type { Middleware } from "polka";

export const dummyMiddleware: Middleware<{foo : string}> = (req, res, next) => {

  req.foo = "hello";
  next();
};

But the error message only turns into this

Property 'foo' does not exist on type 'Request<{ foo: string; }, any, any, ParsedQs, Record<string, any>>'.ts(2339)

So, question, is declaration merging the best way to achieve this ? If yes, do you have a proper way to achieve this ?

A bit of context, this middle ware will be use for seeding Sapper session data.

Versions :

  • "typescript": "^4.0.3"
  • "polka": "next"
  • "@types/polka": "^0.5.2",

Full TypeScript config :

{
        "extends": "@tsconfig/svelte/tsconfig.json",
        "compilerOptions": {
         "module": "esnext",
            "lib": ["DOM", "ES2017", "WebWorker", "ESNext"],
            "strict": true
        },
        "include": ["src/**/*", "src/node_modules/**/*"],
        "exclude": ["node_modules/*", "__sapper__/*", "static/*"],
        "typeRoots": [ "@types" ]
    }

Disclaimer :

I am a novice in polka and typescript so it is not impossible that I missed something obvious

Volubyl
  • 25
  • 1
  • 6

1 Answers1

0

I settled with first casting IncomingMessage to Request.

import { IncomingMessage, ServerResponse } from 'node:http';
import polka, { Next, Request } from 'polka';

function one(req:IncomingMessage, res:ServerResponse, next:Next) {
  (req as Request).foo = 'world';
  next();
}

function two(req:IncomingMessage, res:ServerResponse, next:Next) {
  //req.foo = '...needs better demo ';
  next();
}

const app = polka();
app.use(one, two);
app.get('/users/:id', (req:IncomingMessage, res) => {
  console.log(`~> Hello, ${(req as Request).foo}`);
  res.end(`User: ${(req as Request).params.id}`);
});
app.listen(3000, (err:any) => {
  if (err) throw err;
  console.log(`> Running on localhost:3000`);
});

Then in index.d.ts try this:

declare global{
  module 'polka' {
    interface Request {
      foo: string;
    }
  }
}

Not great, but something to work with.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
gwest7
  • 1,556
  • 19
  • 26
  • So far, the solution you proposed works well for me ! Thanks you very much. I just hope it won't become a "moving" problem as can [the isssue with express](https://stackoverflow.com/questions/37377731/extend-express-request-object-using-typescript/) be For my own knowledge, when you say "not great", could you tell me more about why you don't think it's great ? I have the same feeling but I can't really say why. But so far so good ! – Volubyl May 09 '21 at 13:10