Vue 项目里想约束一个变量只能是 element-plus tag 的合法类型:
import type { TagType } from "element-plus";
const t: TagType = "success";
结果 TS 报错:
模块 "element-plus" 没有导出的成员 "TagType"。
你是想改用 "import TagType from 'element-plus'" 吗?
问题不是 import type 用错了,是 element-plus 根本没在主入口导出 TagType。
import type 是干嘛的
先说 import type 本身,它只导入类型信息,编译成 JS 时会完全消失:
import type { User } from "./types";
const u: User = { id: 1 }; // 编译后 import 语句被抹掉
对比普通 import:
import { User } from "./types";
// 编译后仍然 require("./types") — 运行时如果这个模块只导出类型就报错
import type 的三个作用:
- 避免运行时副作用 — 只用类型的场景不会拉进模块
- 配合
verbatimModuleSyntax— 现代 TS 项目里”类型 vs 值”必须显式区分 - 减小打包体积 — 无用运行时代码会被 tree-shake 掉
为什么 element-plus 报”没有导出的成员”
TagType 在 element-plus 内部定义:
// packages/components/tag/src/tag.ts
export type TagType = "" | "success" | "info" | "warning" | "danger";
但没转发到主入口 element-plus/es/index.d.ts。所以:
import type { TagType } from "element-plus"; // 找不到
两种解法
方案 1:自己定义(推荐)
三秒钟搞定,稳定:
type TagType = "" | "success" | "info" | "warning" | "danger";
const t: TagType = "success";
对内部类型 element-plus 后续升级也不会一言不合就改。自己定义等于 API 边界完全掌控。
方案 2:从深路径引
理论上可以:
import type { TagType } from "element-plus/es/components/tag/src/tag";
局限:
- 这是非公开 API,element-plus 版本升级可能改路径
- 需要构建工具能解析这种深路径
- 不同版本的 element-plus 目录结构可能不同(
lib/vses/vsdist/)
做工具库或第三方组件时优先方案 1,业务代码里图省事偶尔可以用方案 2。
import type 的常见变体
内联 type(TS 4.5+):
import { type User, createUser } from "./user";
// ^^^^ 只这个是类型
同一 import 里混装类型和值,编译后 User 被抹掉,createUser 保留。
全部当值 import(老式,不推荐):
import { User } from "./user";
type MyRole = User["role"]; // 运行时会真的加载模块
export type:
export type { User } from "./user";
再转发类型,同样只影响类型系统,不产生运行时依赖。
一张速查表
| 场景 | 写法 |
|---|---|
| 只用类型 | import type { X } from "..." |
| 同一 import 混装 | import { type X, y } from "..." |
| 转发类型 | export type { X } from "..." |
| 库没有导出的内部类型 | 自己定义 or 深路径引(慎用) |
verbatimModuleSyntax=true | 类型必须用 import type,否则报错 |
一句话总结
import type = 只要类型不要运行时代码。库没导出的内部类型别硬拽——自己定义一份最稳,深路径 import 只是应急。
