Next.js/TypeScript/Webpack报错:未处理的拒绝(ReferenceError): XYZ未定义
这是个典型的TypeScript与Next.js模块打包交互时的坑,我来给你拆解一下核心原因:
TypeScript类型会被完全擦除
你定义的SomeType是纯TypeScript类型,在编译为JavaScript的过程中会被彻底移除,不会留下任何运行时代码。比如你的SomeType.ts文件编译后会变成一个空的JS模块,而some-stuff.ts里导入的SomeType在运行时实际是undefined。Next.js对pages模块的导出有严格处理
Next.js会把pages目录下的所有文件当作页面或页面依赖模块来打包,当你在some-stuff.ts中导出SomeType时,即使index.ts没有导入它,Webpack打包器也会保留这个导出项。但因为SomeType在运行时根本不存在(已经被TS擦除),模块加载时就会触发ReferenceError: SomeType is not defined的报错。
这里有几个靠谱的解决方案,按推荐程度排序:
1. 使用TypeScript的类型专属导出(推荐)
从TypeScript 3.8版本开始,支持type关键字标注纯类型的导出/导入,这样TS编译器会明确知道这是类型,编译时会完全移除,不会生成任何运行时代码:
修改some-stuff.ts的导出部分:
import SomeType from './SomeType' const someValue: SomeType = { a: 11, b: 22 } export { someValue, // 用type标注这是纯类型导出 type SomeType }
或者也可以用类型重导出的方式:
// some-stuff.ts import type SomeType from './SomeType' const someValue: SomeType = { a: 11, b: 22 } export { someValue } export type { SomeType }
2. 将类型文件移出pages目录
Next.js对pages目录的文件有特殊的路由和打包逻辑,纯类型文件不应该放在这里。建议在项目根目录创建types文件夹,把SomeType.ts移进去,然后修改导入路径:
// some-stuff.ts import SomeType from '../types/SomeType'
这样Next.js就不会把类型文件当作页面模块处理,避免不必要的打包问题。
3. 只导出运行时需要的内容
如果你不需要在其他文件中复用SomeType类型,那就直接移除SomeType的导出,就像你发现的那样,这样模块在运行时就不会有无效的导出项,自然不会报错。
内容的提问来源于stack exchange,提问作者Natasha

