0

I’m writing a Mongoose user schema in TypeScript, and inside the schema methods, I want to generate JWT access tokens and refresh tokens.

I installed the required packages using:

npm i jsonwebtoken  
npm i -D @types/jsonwebtoken

However, when I call jwt.sign(), I get this TypeScript error:

I wrote this code inside my Mongoose user schema method to generate an access token:

userSchema.methods.generateAccessToken = function (
  this: IUseSchema & mongoose.Document,
): string {
  if (!this._id) {
    throw new ApiError(400, "Payload ID is missing");
  }

  if (!env.ACCESS_TOKEN_KEY) {
    throw new ApiError(400, "ACCESS_TOKEN_KEY is missing in env");
  }

  if (!env.ACCESS_TOKEN_EXPIRY) {
    throw new ApiError(400, "ACCESS_TOKEN_EXPIRY is missing in env");
  }

  const secretKey = env.ACCESS_TOKEN_KEY as Secret;
  const expiresIn = env.ACCESS_TOKEN_EXPIRY as string;

  return jwt.sign({ id: this._id }, secretKey, { expiresIn });
};

But I get an error on the line with jwt.sign.

I don’t understand what type safety I am missing here. Can someone explain what might be wrong?

No overload matches this call.
  Overload 1 of 5, '(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: null, options?: (SignOptions & { algorithm: "none"; }) | undefined): string', gave the following error.
    Argument of type 'Secret' is not assignable to parameter of type 'null'.
      Type 'string' is not assignable to type 'null'.
  Overload 2 of 5, '(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: Buffer<ArrayBufferLike> | Secret | PrivateKeyInput | JsonWebKeyInput, options?: SignOptions | undefined): string', gave the following error.
    Type 'string' is not assignable to type 'number | StringValue | undefined'.
  Overload 3 of 5, '(payload: string | object | Buffer<ArrayBufferLike>, secretOrPrivateKey: Buffer<ArrayBufferLike> | Secret | PrivateKeyInput | JsonWebKeyInput, callback: SignCallback): void', gave the following error.
    Object literal may only specify known properties, and 'expiresIn' does not exist in type 'SignCallback'.

I’m passing the arguments like this (example):

jwt.sign(payload, process.env.JWT_SECRET, { expiresIn: process.env.ACCESS_TOKEN_EXPIRY });

I created a jwt.sign, and in that, I added process.env.ACCESS_TOKEN_KEY and process.env.ACCESS_TOKEN_EXPIRY. But the issue is that it's not working properly in JWT. Even though I added safety measures, it still doesn't work as expected. So, I tried doing it like this: expiresIn: "30d". But since these are secure credentials (like a private key), they should be stored safely.

So my issue is: Why is it not working when I use process.env? I'm getting a "no overload" error.

14
  • It seems process.env.JWT_SECRET has the type string | undefined that's why you need to get the secret into a string variable like const secret = process.env.JWT_SECRET ?? '123' and pass it to jst like this jwt.sign('111', secret, {}) Commented Jun 2 at 20:08
  • Possibly incorrect payload. I don't see a id available in JWT specification. Commented Jun 2 at 20:37
  • @Dorado The payload can be any object Commented Jun 2 at 22:53
  • 1
    @Phil That wouldn't explain the error with const secretKey = env.ACCESS_TOKEN_KEY as Secret though. Commented Jun 3 at 1:51
  • 1
    @Phil I've reopened the question because I don't think it's a problem with the environment variable being undefined. See my answer for a better explanation Commented Jun 4 at 20:42

1 Answer 1

3

Your problem is not with the secretKey or with using environment variables (which you've cast to non-undefined types just fine).

Your problem is the type of the expiresIn option, which you have specified as string but whose type declaration says

expiresIn?: StringValue | number;

This matches your error message

Type 'string' is not assignable to type 'number | StringValue | undefined'.

which unfortunately does not specify that it relates to the type of the expiresIn property of the options parameter.

The StringValue type you're seeing is not any string, it's a template literal type from the vercel/ms package which node-jsonwebtoken uses for its options1:

  • expiresIn: expressed in seconds or a string describing a time span vercel/ms.

    Eg: 60, "2 days", "10h", "7d". A numeric value is interpreted as a seconds count. If you use a string be sure you provide the time units (days, hours, etc), otherwise milliseconds unit is used by default ("120" is equal to "120ms").

So to fix your problem, use

const expiresIn = env.ACCESS_TOKEN_EXPIRY as StringValue; // import("ms").StringValue

1: the type declaration changed from string to StringValue with PR 71721 in January 2025.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.