TypeScript类库与Angular Web应用对象实例化差异:属性缺失
问题原因与解决方案
核心原因:TypeScript编译配置差异
出现这种差异的关键是**useDefineForClassFields编译选项**的设置不同:
- 类库项目中,该选项大概率为
false,TypeScript会将类的属性声明编译为构造函数内对实例的赋值(如this.firstName = undefined),因此实例会包含这些属性键,Object.keys能正常获取。 - 常规Angular Web应用默认开启了
useDefineForClassFields: true(尤其当target设置为ES2022及以上时),此时类属性会被编译为ES6+原生类字段,未显式初始化的属性不会被添加到实例对象中,所以Object.keys返回空数组,控制台显示空对象。
此外,Angular类库与Web应用的默认tsconfig配置本身存在差异:类库的tsconfig.lib.json通常为了兼容更多环境,会采用更保守的编译设置;而Web应用更倾向于使用现代JS特性,默认启用该选项。
解决方案
方案1:修改Web应用的TypeScript配置
在Web项目的tsconfig.json(或tsconfig.app.json)中添加/修改以下配置:
{ "compilerOptions": { "useDefineForClassFields": false } }
修改后重新编译项目,类实例会自动带上未初始化的属性键,行为将和类库一致。
方案2:显式初始化类属性
如果不想修改全局编译配置,可以在类的属性声明时显式赋值undefined,确保属性被添加到实例中:
class User { firstName: string = undefined!; lastName: string = undefined!; }
这里的!是非空断言,用于规避TypeScript的严格初始化检查(如果开启了strictPropertyInitialization)。
方案3:运行时获取类属性的替代方式
如果需要在useDefineForClassFields: true的前提下获取类的属性列表,可以提前定义类的属性名数组,手动为实例添加属性:
// 提前定义属性列表 const USER_PROPERTIES = ['firstName', 'lastName']; function instantiate<T extends Object>(constructor: new () => T, properties: string[]) : T { const obj = new constructor(); // 手动为实例添加属性 properties.forEach(key => obj[key as keyof T] = undefined); console.log('Object is:', obj); console.log('Keys are:', Object.keys(obj)); return obj; } // 使用时传入属性列表 instantiate(User, USER_PROPERTIES);
内容的提问来源于stack exchange,提问作者Wouter Vandenputte
相关产品推荐
相关产品推荐

