Vue + TSX 中使用 class 报错 解决方法

遇到一个问题:

问题回顾

在 Vue 3 + TSX 项目中,可能会这样写:

html 复制代码
<div class="container" style={{ height: '100px' }}>Hello</div>

TypeScript 会提示:

属性"class"在类型"DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>"上不存在。你是否指的是"className"?

这在普通 Vue 模板中完全合法,但在 .tsx 文件中,TypeScript 的类型定义默认认为:

  • JSX 中只允许使用 className,不认识 class;
  • 这是因为 JSX 的类型系统最早源自 React,它沿用了 className 语法;
  • Vue 虽然在运行时支持 class,但 TS 类型声明中有时缺少该属性,尤其在自定义 jsx 模式下。

于是,TypeScript 就会报错提示你把 class 改为 className。

**本质:**是类型安全校验阻止把一个具有 class 字段的 props 对象赋给 JSX.IntrinsicElements['div']。运行时代码不一定会失败(取决于运行时是否接受该属性),但类型层面会阻止编译或 IDE 的类型检查。

解决方法

方法一:修改代码

在 TSX 中统一使用 className(Vue TSX 也支持 className)。对代码风格友好,类型正确。

方法二:添加声明文件(侧重)
  1. src/types 目录下新增一个文件,例如:

src/types/shim-jsx-class.d.ts

javascript 复制代码
// src/types/shim-jsx-class.d.ts
import 'vue';

declare module 'vue' {
  interface HTMLAttributes {
    /**
     * 允许在 TSX/JSX 中使用 `class` 属性(兼容 string / object / array)
     * - string: "a b"
     * - Record<string, boolean>: { active: true }
     * - Array<string | Record<string, boolean>>
     */
    class?: string | Record<string, boolean> | Array<string | Record<string, boolean>>;

    /** 也允许 className(可选,但推荐保留) */
    className?: string | Record<string, boolean> | Array<string | Record<string, boolean>>;
  }
}

这段代码的意思是:扩展 Vue 内部的 HTMLAttributes 类型,为它添加一个 class 属性定义,从而让 TypeScript 在 TSX 中识别它。

  1. 修改 tsconfig.json,确保 TypeScript 能识别这个声明文件。

打开项目根目录的 tsconfig.json,在 include 中加上 src/types:

javascript 复制代码
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "jsx": "preserve",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src", "src/types/**/*.d.ts"]
}

如果 include 已经包含 src,通常不用改。确保声明文件路径在 include 范围内。

⚠️ 注意:skipLibCheck 不是必须,但在部分场景下能避免第三方类型冲突。

  1. 重启编辑器 / TypeScript 服务

VSCode 用户可执行命令:TypeScript: Restart TS Server 或者直接重启编辑器。

此时重新打开 .tsx 文件,报错应该已经消失。

为什么这能解决问题?

Vue TSX 的类型定义(在 vue 包内)通过 HTMLAttributes 控制 HTML 元素的可用属性。默认声明没有 class,所以 TSX 编译器认为它不存在。

通过 declare module 'vue' {} 的方式"合并声明",为 HTMLAttributes 增加 class 字段。TypeScript 会自动合并这部分扩展声明,达到了"类型补丁"的效果。

这不会影响 Vue 的运行逻辑,仅扩展了静态类型检查范围。

最后:Vue 在 TSX 环境中实际上同时兼容 class 与 className,但推荐保持一致风格:在 TSX 中依然用 class,不要混用 className。

相关推荐
人工智能训练43 分钟前
前端框架选型破局指南:Vue、React、Next.js 从差异到落地全解析
运维·javascript·人工智能·前端框架·vue·react·next.js
李纲明2 天前
WordPress外贸成品网站的免费获取渠道
vue·php
加洛斯2 天前
前端小知识002:ref 与 reactive 详解
前端·vue
计算机毕设vx_bysj68692 天前
计算机毕业设计必看必学~Springboot教学进度管理系统,原创定制程序、单片机、java、PHP、Python、小程序、文案全套、毕设成品等!
java·spring boot·vue·课程设计·管理系统
小贺要学前端3 天前
【无标题】
前端·javascript·vue·技术趋势
IT教程资源C4 天前
(N_141)基于springboot,vue网上拍卖平台
mysql·vue·前后端分离·拍卖系统·springboot拍卖
IT教程资源C4 天前
(N_144)基于微信小程序在线订餐系统
mysql·vue·uniapp·前后端分离·订餐小程序·springboot订餐
合作小小程序员小小店4 天前
web网页开发,在线短视频管理系统,基于Idea,html,css,jQuery,java,springboot,mysql。
java·前端·spring boot·mysql·vue·intellij-idea
aiguangyuan4 天前
Vue 3.0 源码解读
vue·前端开发
IT教程资源D7 天前
[N_144]基于微信小程序在线订餐系统
mysql·vue·uniapp·前后端分离·订餐小程序·springboot订餐