Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using strict in a project tsconfig.json makes requestContext.get(string) possibly undefined #93

Closed
2 tasks done
silenceisgolden opened this issue Dec 16, 2021 · 5 comments
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers

Comments

@silenceisgolden
Copy link
Contributor

silenceisgolden commented Dec 16, 2021

Prerequisites

  • I have written a descriptive issue title
  • I have searched existing issues to ensure the bug has not already been reported

Fastify version

3.25.0

Plugin version

2.2.0

Node.js version

16.x

Operating system

macOS

Operating system version (i.e. 20.04, 11.3, 10)

12.0.1 Monterey

Description

With a project using fastify and fastify-request-context, the user could get confused because

declare module 'fastify-request-context' {
    interface RequestContextData {
       a: number;
    }
}

const value = request.requestContext.get('string');

and value is set to number | undefined. In the documentation it states that the value should be set to a type of number, but this is not always the case.

Steps to Reproduce

Create a new folder/nodejs project with these files.

package.json

{
  "name": "fastify-request-context-typescript",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "fastify": "^3.25.0",
    "fastify-request-context": "^2.2.0"
  },
  "devDependencies": {
    "@types/node": "^17.0.0"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "strict": true // the cause of the issue
    }
}

app.ts

import fastify, { FastifyLoggerInstance } from 'fastify';
import { fastifyRequestContextPlugin } from 'fastify-request-context';

import { simpleController } from './a';

declare module 'fastify-request-context' {
    interface RequestContextData {
        logger: FastifyLoggerInstance;
    }
}

const server = fastify();

server.register((app) => {
    app.get('/', {
        handler: simpleController
    });
}, {
    prefix: '/helloworld',
})

server.register(fastifyRequestContextPlugin, {
    defaultStoreValues: {
        logger: server.log,
    },
});

a.ts

import { RouteHandler } from 'fastify';

export const simpleController: RouteHandler = async (req, reply) => {
    const logger = req.requestContext.get('logger');
    
    // logger is possibly undefined, so this is a typescript error
    logger.info('do a thing');

    reply.code(204);
};

The issue is due to this typing I think:

https://github.com/fastify/fastify-request-context/blob/master/index.d.ts#L8

Since the type is RequestContextData[K] | undefined, in strict typing mode I think that this causes logger above in a.ts to be FastifyLoggerInstance | undefined. This is not the case if you add "strictNullChecks": false to the tsconfig.json.

Expected Behavior

Could the .get method just be typed as get<K extends keyof RequestContextData>(key: K): RequestContextData[K]? This seems to work with "strictNullChecks" set to either true (implicitly by "strict": true), or with "strict": true and "strictNullChecks": false.

@silenceisgolden silenceisgolden changed the title Using strict in a project tsconfig.json makes requestContext.get(string) possibly undefined Using strict in a project tsconfig.json makes requestContext.get(string) possibly undefined Dec 16, 2021
@climba03003
Copy link
Member

@silenceisgolden
Copy link
Contributor Author

silenceisgolden commented Dec 16, 2021

Thanks for the quick response! So that sort of tells me that the docs should at least be updated then? https://github.com/fastify/fastify-request-context/blob/master/README.md where it says

// Type is string
const foo = requestContext.get('foo')
// Type for unspecified keys is any
const bar = requestContext.get('bar')

maybe there could be a comment added that this is only the case when "strictNullChecks": false?

@climba03003 climba03003 added documentation Improvements or additions to documentation good first issue Good for newcomers labels Dec 16, 2021
@climba03003
Copy link
Member

climba03003 commented Dec 16, 2021

Would you like to send a Pull Request to improve the documentation?

@silenceisgolden
Copy link
Contributor Author

For other folks who run into this issue, I am sort of fixing this by redefining the type:

declare module 'fastify-request-context' {
  interface RequestContextData {
    val: string;
    val2?: string;
  }

  interface RequestContext {
    get<K extends keyof RequestContextData>(key: K): RequestContextData[K];
  }
}

I think this is valid because I am setting correctly typed defaults:

import fastify from 'fastify';
import { fastifyRequestContextPlugin } from 'fastify-request-context';

const server = fastify();

server.register(fastifyRequestContextPlugin, {
  defaultStoreValues: {
    val: '',
    // Since `val2` is typed as possibly undefined, we can leave it undefined here.
  },
});

If you decide to set defaultStoreValues with this type fix, you should be fine since TS will error until you get the correctly typed defaults into the defaultStoreValues object for each property. However, if you do not set defaultStoreValues, you can have a situation where the types are telling you that the value will always be defined, but in fact start out as undefined.

@silenceisgolden
Copy link
Contributor Author

Closing this issue now that the pull request has been merged and it is link to from the README. Please ping me on this thread though if anyone has a better idea of how to work around this issue. Thanks @climba03003 for the discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants