0

I am trying to setup a debugging environment on an 2019 project so I added the following script to my package.json

"dev:debug": "tsc-watch --onFirstSuccess \"node --inspect -r ts-node/register src/app.ts\"",

Running it would give me the following

> node-api-starter@1.0.0 start:dev D:\p\my-project
> tsc-watch --onFirstSuccess "node --inspect -r ts-node/register src/app.ts"

7:18:10 AM - Starting compilation in watch mode... 


7:18:27 AM - Found 0 errors. Watching for file changes.
Debugger listening on ws://127.0.0.1:9229/b9a130c4-473d-4b55-a512-50ae9cff15a3
For help, see: https://nodejs.org/en/docs/inspector
D:\p\my-project\node_modules\ts-node\src\index.ts:423
    return new TSError(diagnosticText, diagnosticCodes)
           ^
TSError: ⨯ Unable to compile TypeScript:
src/api/auth/auth.controller.ts:580:29 - error TS2339: Property 'auth' does not exist on type 'Request<ParamsDictionary>'.

580     user.refreshToken = req.auth.refreshToken; 
                                ~~~~
src/api/auth/auth.controller.ts:581:23 - error TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary>'.

581     user.userId = req.user.id;
                          ~~~~
src/api/auth/auth.controller.ts:617:82 - error TS2339: Property 'auth' does not exist on type 'Request<ParamsDictionary>'.

617     const user = await userService.getUserInfoByCustomColumn("refreshToken", req.auth.refreshToken);

                                  ~~~~
src/api/auth/auth.controller.ts:782:76 - error TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary>'.

782     const user = await userService.getUserInfoByCustomColumn("userId", req.user.id, true);        

                            ~~~~
src/api/auth/auth.controller.ts:800:46 - error TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary>'.

800     await userService.updateUserPassword(req.user.id, insertedNewPassword);
                                                 ~~~~

    at createTSError (D:\p\my-project\node_modules\ts-node\src\index.ts:423:12)
    at reportTSError (D:\p\my-project\node_modules\ts-node\src\index.ts:427:19)
    at getOutput (D:\p\my-project\node_modules\ts-node\src\index.ts:554:36)
    at Object.compile (D:\p\my-project\node_modules\ts-node\src\index.ts:760:32)
    at Module.m._compile (D:\p\my-project\node_modules\ts-node\src\index.ts:839:43)
    at Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Object.require.extensions.(anonymous function) [as .ts] (D:\p\my-project\node_modules\ts-node\src\index.ts:842:12)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)

Example of one error

auth.controller.ts - Line 577

const refresh = async (req: Request, res: Response, next: NextFunction) => {
  try {
    const user = new User();
    user.refreshToken = req.auth.refreshToken;
    ...
}

Request being a part of the Express library

    interface Request<P extends core.Params = core.ParamsDictionary> extends core.Request<P> { }

There are 2 files that declare Express namespace and export Request interfaces with different varibales (see below)

request.d.ts

declare namespace Express {
  export interface Request {
    user?: any;
    auth?: any;
  }
}

declarations.d.ts

declare module 'draftjs-to-html';

declare namespace Express {
  export interface Request {
    availableCountries: number[];
    language: string;
    pagination: {
      pageSize: number;
      pageNumber: number;
    };
  }
}

So what happens here is that the first compilation using tsc-watch is done successfully but then some errors in the project pop up.

  • Does that mean that ts-node tries to recompile ?
  • If so, why does it fail? does it compile with a different configuration than tsc-watch?
  • Is there a flag that I could use to skip checking these errors
Rami
  • 328
  • 1
  • 13
  • Can you show the relevant code and the types `Request` and `ParamsDictionary` –  Apr 30 '20 at 05:59
  • @MikeS. Just updated the description, `Request` is basically the standard Express `Request` – Rami Apr 30 '20 at 06:06
  • Well, is it right? Or is there a property `auth` on type `Request` –  Apr 30 '20 at 06:11
  • Actually there is a `request.d.ts` file with the content declaring the namespace Express and adds `user` and `auth` to its `Request` interface. Also there's another file called `declarations.d.ts` which does exactly the same thing but for different variables. (Added their contents to the description). – Rami Apr 30 '20 at 06:33

1 Answers1

0

First, ts-node rebuilds your sources, so you do the compilation job twice. Not sure if the problem is caused by it, maybe ts-node is unable to locate your tsconfig.

As an immediate fix I'd suggest merging the existing express.Request declaration, whatever it is in your case, with your own. Basically, you put that declaration from request.d.ts somewhere in your source code where it is available for your controller functions and update with proper types where needed (or roll with any):

declare global {
    export namespace Express {
        export interface Request {
            user?: any;
            auth?: {refreshToken: string};
        }
    }
}

Now Request sports a properly typed refreshToken.

x1n13y84issmd42
  • 890
  • 9
  • 17
  • Thank you for the TypeScript fix suggestions. We ended up using nodemon without ts-node. I am still not getting why ts-node couldn't locate the the same tsconfig. But that's a subject for the summer :) – Rami May 21 '20 at 00:02