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

TypeScript泛型约束问题:Unsafe assignment of an any value警告排查

问题描述

代码运行正常,但TypeScript对to: message.user.email,这行代码抛出Unsafe assignment of an any value警告,想排查原因。

相关代码:
发送邮件函数:

const sendWelcomeEmaill = async <T>(message: T) => {
  try {
    const result = await transporter.sendMail({
      from: `"⚡ Magic NextAuth" ${env.EMAIL_FROM}`,
      to: message.user.email,
      subject: 'Welcome to Magic NextAuth! 🎉',
      html: `<div>HELLO</div>`
    }
    );
    const failed = result.rejected.concat(result.pending).filter(Boolean);
    if (failed.length) {
      throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
    }
  } catch (error) {
    console.log(error);
  }
}

函数调用场景(next-auth的events配置):

events: {
    createUser: async (message) => {
      await sendWelcomeEmail<typeof message>(message)
      // typeof message is equal to {user: User}
    },
},
问题原因

你给sendWelcomeEmail定义了泛型<T>,但没给这个泛型加任何类型约束,TypeScript没法推断出message里user和email属性的具体类型,所以把message.user.email判定为any类型,触发了不安全赋值的警告。

虽然调用时传了<typeof message>,但这个类型没有被TypeScript正确关联到函数内部的泛型T上,导致函数内部还是识别不了属性类型。

解决方案

方案1:给泛型添加类型约束

先定义和createUser事件参数匹配的类型,让TypeScript明确知道T的结构:

// 定义事件参数的类型结构
type CreateUserMessage = {
  user: {
    email: string;
  };
};

const sendWelcomeEmail = async <T extends CreateUserMessage>(message: T) => {
  try {
    const result = await transporter.sendMail({
      from: `"⚡ Magic NextAuth" ${env.EMAIL_FROM}`,
      to: message.user.email, // 类型不再是any
      subject: 'Welcome to Magic NextAuth! 🎉',
      html: `<div>HELLO</div>`
    });
    const failed = result.rejected.concat(result.pending).filter(Boolean);
    if (failed.length) {
      throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
    }
  } catch (error) {
    console.log(error);
  }
}

方案2:直接使用具体类型代替泛型

既然你明确知道传入的是{user: User}类型,没必要用泛型,直接指定参数类型:

// 假设User类型已定义,包含email字段
const sendWelcomeEmail = async (message: { user: User }) => {
  try {
    const result = await transporter.sendMail({
      from: `"⚡ Magic NextAuth" ${env.EMAIL_FROM}`,
      to: message.user.email,
      subject: 'Welcome to Magic NextAuth! 🎉',
      html: `<div>HELLO</div>`
    });
    const failed = result.rejected.concat(result.pending).filter(Boolean);
    if (failed.length) {
      throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
    }
  } catch (error) {
    console.log(error);
  }
}

方案3:使用next-auth内置的事件类型

next-auth已经为事件参数提供了内置类型,直接导入使用更准确:

import type { CreateUserEvent } from "next-auth/events";

const sendWelcomeEmail = async (message: CreateUserEvent) => {
  try {
    const result = await transporter.sendMail({
      from: `"⚡ Magic NextAuth" ${env.EMAIL_FROM}`,
      to: message.user.email,
      subject: 'Welcome to Magic NextAuth! 🎉',
      html: `<div>HELLO</div>`
    });
    const failed = result.rejected.concat(result.pending).filter(Boolean);
    if (failed.length) {
      throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`);
    }
  } catch (error) {
    console.log(error);
  }
}

// 调用时无需再传泛型
events: {
  createUser: async (message) => {
    await sendWelcomeEmail(message);
  },
},

内容的提问来源于stack exchange,提问作者John John

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:17:49