tsconfig target从es2017升级到ES2022后类属性初始化为undefined问题
类实例属性默认值变更问题:从空对象到带undefined属性
问题重现
将tsconfig的target从es2017升级到ES2022后,类实例的表现发生了明显变化:
class Test { a: number b: string } const c = new Test()
- 旧配置下,实例
c是空对象{}; - 新配置下,
c变为{a: undefined, b: undefined},导致单元测试和Object.assign等逻辑失效。
新旧tsconfig配置如下:
旧配置
{ "compilerOptions": { "target": "es2017", "module": "Node16", "noImplicitAny": false, "moduleResolution": "node16", "forceConsistentCasingInFileNames": true, "types": ["jest", "node"], "outDir": "./dist", "esModuleInterop": true, "sourceMap": true, "allowSyntheticDefaultImports": true, "strict": false, "skipLibCheck": true, "experimentalDecorators": true, "emitDecoratorMetadata": true }, "include": ["**/*.ts"] }
新配置
{ "compilerOptions": { "target": "ES2022", "module": "ES2022", "noImplicitAny": false, "moduleResolution": "node", "forceConsistentCasingInFileNames": true, "types": ["jest", "node"], "outDir": "./dist", "esModuleInterop": true, "sourceMap": true, "allowSyntheticDefaultImports": true, "strict": false, "skipLibCheck": true, "experimentalDecorators": true, "emitDecoratorMetadata": true }, "include": ["**/*.ts"] }
原因与背景
- 这是TypeScript针对ES2022原生语法的适配变更:ES2022正式引入了类字段声明的原生语法,允许在类中直接声明实例字段并设置默认值。
- 当
target设为ES2022及以上时,TypeScript默认启用useDefineForClassFields: true,会将类中未初始化的实例属性编译为原生类字段。这些字段在实例创建时会被自动初始化为undefined,成为对象的自有属性,因此实例不再是空对象。 - 而
target低于ES2022时,TypeScript不会生成原生类字段代码,类中的属性仅作为类型声明存在,不会被添加到实例对象上,所以实例表现为空对象。
解决方案
要保留ES2022的target配置,同时恢复旧的实例行为,只需在compilerOptions中添加useDefineForClassFields: false:
修改后的新配置:
{ "compilerOptions": { "target": "ES2022", "module": "ES2022", "noImplicitAny": false, "moduleResolution": "node", "forceConsistentCasingInFileNames": true, "types": ["jest", "node"], "outDir": "./dist", "esModuleInterop": true, "sourceMap": true, "allowSyntheticDefaultImports": true, "strict": false, "skipLibCheck": true, "experimentalDecorators": true, "emitDecoratorMetadata": true, "useDefineForClassFields": false }, "include": ["**/*.ts"] }
这个配置会强制TypeScript回到旧的类属性编译逻辑,不使用原生类字段语法,未初始化的属性不会被添加到实例上,实例将恢复为空对象{}。
内容的提问来源于stack exchange,提问作者cnikia
相关产品推荐
相关产品推荐

