You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 16:48:30