You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新Node.js包后jsonwebtoken.sign()无法使用环境变量作为expiresIn参数的类型错误问题

更新Node.js包后jsonwebtoken.sign()无法使用环境变量作为expiresIn参数的类型错误问题

我之前升级jsonwebtoken包后也碰到过一模一样的情况——之前运行正常的代码,升级后只要用环境变量传expiresIn就报类型错误,硬编码具体值就一切正常。这其实是因为新版本的jsonwebtoken对TypeScript类型检查的约束变得更严格了,尤其是对SignOptions配置项里的expiresIn参数和密钥参数的类型定义做了更精确的限制。

问题根源

升级后的jsonwebtoken包,把expiresIn的类型从宽泛的string | number | undefined细化成了更严格的类型(要求是符合JWT时长格式的字符串,比如"100d"、"24h"这类);而process.env里的变量默认被TypeScript推断为string | undefined,哪怕做了空值合并处理,TS也无法确认这个字符串是否符合expiresIn要求的格式,所以会抛出类型不匹配的错误。另外你的错误信息里还提到了密钥的问题,是因为新版本对secretOrPrivateKey的类型也做了收紧,直接传process.env.JWT_KEY as string已经不符合它的类型要求了。

解决方法

我试过几个可行的方案,你可以参考:

方案1:明确断言为对应类型(最简单直接)

先从jsonwebtoken导入对应的类型定义,然后把环境变量的值断言为SignOptions['expiresIn'],同时把密钥断言为Secret类型:

import jwt, { SignOptions, Secret } from 'jsonwebtoken';

// 生成JWT的代码
const user_jwt = jwt.sign(
  { user_id: user_id.uuid },
  process.env.JWT_KEY as Secret,
  {
    expiresIn: (process.env.JWT_EXPIRES_IN ?? '100d') as SignOptions['expiresIn'],
  }
);

方案2:用类型守卫缩小类型范围(更严谨)

如果担心环境变量的值格式不符合要求,可以加个类型守卫来校验,让TypeScript信任这个值的合法性:

import jwt, { SignOptions, Secret } from 'jsonwebtoken';

// 校验JWT过期时间格式是否合法的类型守卫函数
function isValidJwtExpiry(value: string): value is SignOptions['expiresIn'] {
  // 匹配类似"100d"、"24h"、"30m"的标准时长格式
  return /^\d+(s|m|h|d|w|M|Y)$/i.test(value);
}

// 先处理环境变量
const rawExpiresIn = process.env.JWT_EXPIRES_IN ?? '100d';
const expiresIn = isValidJwtExpiry(rawExpiresIn) ? rawExpiresIn : '100d';

// 生成JWT
const user_jwt = jwt.sign(
  { user_id: user_id.uuid },
  process.env.JWT_KEY as Secret,
  { expiresIn }
);

方案3:用环境变量解析工具(长期维护更友好)

如果你的项目里有很多环境变量需要处理,可以用zod、envalid这类工具来统一解析环境变量,它们能自动给变量加上符合要求的TypeScript类型:
比如用envalid的示例:

import { cleanEnv, str } from 'envalid';
import jwt, { SignOptions } from 'jsonwebtoken';

// 解析环境变量并生成强类型的配置
const env = cleanEnv(process.env, {
  JWT_KEY: str(),
  JWT_EXPIRES_IN: str({ default: '100d' }),
});

// 生成JWT
const user_jwt = jwt.sign(
  { user_id: user_id.uuid },
  env.JWT_KEY,
  {
    expiresIn: env.JWT_EXPIRES_IN as SignOptions['expiresIn'],
  }
);

为什么之前的空值合并没用?

因为新版本的jsonwebtoken类型定义里,expiresIn不再接受任意字符串,只接受符合特定时长格式的字符串。空值合并只是给了变量一个默认值,但TypeScript还是把它当成普通string类型,无法通过更严格的类型校验,所以需要我们明确告诉TS这个值是符合要求的。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 12:13:04