TypeScript+Babel下TypeORM报ColumnTypeUndefinedError问题求助
问题描述
尽管已安装babel-plugin-transform-typescript-metadata,运行时仍抛出如下报错:
ColumnTypeUndefinedError: Column type for Exercise#name is not defined and cannot be guessed. Make sure you have turned on an "emitDecoratorMetadata": true option in tsconfig.json. Also make sure you have imported "reflect-metadata" on top of the main entry file in your application (before any entity imported). If you are using JavaScript instead of TypeScript you must explicitly provide a column type.
已确认完成以下配置:
- tsconfig.json中已开启
emitDecoratorMetadata: true - 项目入口最顶部已引入
import 'reflect-metadata'; - 项目使用TypeScript开发,未使用纯JS编写实体类
- 已尝试参考社区Babel装饰器元数据保留方案配置,问题仍未解决
相关配置与代码
Exercise.tsx 实体定义
import {Entity,Column, PrimaryGeneratedColumn} from "typeorm/browser"; @Entity("Exercise") export class Exercise{ @PrimaryGeneratedColumn() id!:number; @Column() name!: Text; @Column() notes:Text; @Column() imageJSON:Text; }
.babelrc 配置
{ "plugins": [ "babel-plugin-transform-typescript-metadata", ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose": true }], ], "presets": [ "@babel/preset-typescript" ] }
package.json 依赖片段
... "devDependencies": { "@babel/core": "^7.12.9", "@types/node": "^18.0.0", "@types/react": "~17.0.21", "@types/react-native": "~0.66.13", "babel-plugin-transform-typescript-metadata": "^0.2.2", "typescript": "~4.3.5" }, ...
tsconfig.json 配置
{ "compilerOptions": { "experimentalDecorators": true, "emitDecoratorMetadata":true, }, "extends": "expo/tsconfig.base", "compileOnSave": true, "include":[ "entities" ] }
问题原因
这个报错的本质是TypeORM运行时拿不到实体字段的类型元数据,无法自动推断列类型,由4个配置和写法问题共同导致:
- Babel插件顺序错误:Babel插件按数组顺序从后往前执行,当前配置把
babel-plugin-transform-typescript-metadata放在插件数组最前面,意味着它最先执行、最后处理AST,根本拿不到装饰器插件处理后的节点,完全无法生成类型元数据。 - 插件版本bug:安装的
babel-plugin-transform-typescript-metadata@0.2.2是老旧版本,对带!非空断言的类属性无法正确提取类型,代码里的name!: Text正好命中这个缺陷。 - 文件后缀问题:实体类文件使用了
.tsx后缀,React Native/Expo的Metro打包器对TSX文件的转译规则和TS文件有差异,容易丢失装饰器元数据,实体类本身没有JSX内容,不需要用TSX后缀。 - 字段类型写法错误:代码用了浏览器内置的DOM类型
Text做字段类型,TypeORM无法将这个类型映射到数据库列类型,TS中对应数据库文本列的原生类型应该是string。
修复步骤
按以下顺序调整配置和代码,即可解决问题:
- 修正
.babelrc的插件执行顺序,将元数据插件移到装饰器、类属性插件之后,保证它能拿到处理完成的AST节点:
{ "plugins": [ ["@babel/plugin-proposal-decorators", { "legacy": true }], ["@babel/plugin-proposal-class-properties", { "loose": true }], "babel-plugin-transform-typescript-metadata" ], "presets": [ "@babel/preset-typescript" ] }
- 升级
babel-plugin-transform-typescript-metadata到最新稳定版,修复非空断言属性的类型识别bug:
# npm npm install babel-plugin-transform-typescript-metadata@latest --save-dev # yarn yarn add babel-plugin-transform-typescript-metadata@latest -D
- 修正实体类代码:将文件后缀从
.tsx改为.ts,同时把所有字段的类型从DOM内置的Text替换为TS原生string类型:
import {Entity,Column, PrimaryGeneratedColumn} from "typeorm/browser"; @Entity("Exercise") export class Exercise{ @PrimaryGeneratedColumn() id!:number; @Column() name!: string; @Column() notes!: string; @Column() imageJSON!: string; }
- 清除项目缓存后重新启动,Expo/React Native环境缓存优先级很高,不清理会继续使用旧的转译结果:
# Expo项目 expo start -c # 原生React Native项目 npx react-native start --reset-cache
如果调整后仍有偶发的元数据丢失问题,可以直接在@Column()装饰器中显式声明列类型,完全绕开元数据自动推断逻辑:
@Column({type: "text"}) name!: string;
内容的提问来源于stack exchange,提问作者m2h9
相关产品推荐
相关产品推荐

