如何将TypeScript类实例转换为普通JavaScript对象?
嘿,这个问题我之前也踩过坑!你用JSON序列化那套确实能临时解决,但确实有点“取巧”——不仅绕,要是类里有函数、Symbol属性或者不可序列化的值,还会丢失数据。下面给你几个更靠谱的方案,按需选择:
方案1:手动实现转换方法(最可控)
直接在类里加一个toPlainObject方法,手动定义要转换的属性。这种方式完全由你掌控,想转什么、怎么转都能自定义,还能处理嵌套的类实例:
class A { test: string; constructor(test: string) { this.test = test; } // 自定义转换方法 toPlainObject() { return { test: this.test, // 要是有其他属性,直接在这里添加就行 }; } } const a = new A("hi"); const plainObj = a.toPlainObject(); // 输出:{ test: 'hi' }
方案2:展开语法/Object.assign(快速简洁)
如果你的类只有实例自身的可枚举属性,用对象展开语法或者Object.assign是最快的方式,一行代码搞定:
const a = new A("hi"); // 方式1:展开语法 const plainObj1 = { ...a }; // 方式2:Object.assign const plainObj2 = Object.assign({}, a);
⚠️ 注意:这种方法只会复制可枚举的自有属性,原型链上的属性、不可枚举属性会被忽略。如果你的类结构简单,这个方案完全够用。
方案3:自动遍历所有自有属性(适合复杂场景)
如果需要处理不可枚举属性,或者不想手动写每个属性,可以用Reflect.ownKeys遍历实例的所有自有属性,过滤掉函数后生成普通对象:
function convertToPlainObject<T>(instance: T): Record<string | symbol, unknown> { const plainObj: Record<string | symbol, unknown> = {}; // 遍历所有自有属性(包括不可枚举、Symbol属性) Reflect.ownKeys(instance).forEach(key => { const value = (instance as any)[key]; // 过滤掉类的方法,只保留数据属性 if (typeof value !== 'function') { plainObj[key] = value; } }); return plainObj; } const a = new A("hi"); const plainObj = convertToPlainObject(a); // 输出:{ test: 'hi' }
方案4:类装饰器(批量处理多个类)
如果你有很多类需要转换,可以写一个装饰器,给类自动添加转换方法,不用每个类都重复写代码:
// 定义装饰器 function PlainConvertible<T extends { new(...args: any[]): {} }>(constructor: T) { return class extends constructor { toPlainObject() { const plainObj: Record<string | symbol, unknown> = {}; Reflect.ownKeys(this).forEach(key => { const value = (this as any)[key]; if (typeof value !== 'function') { plainObj[key] = value; } }); return plainObj; } }; } // 给类加上装饰器 @PlainConvertible class A { test: string; constructor(test: string) { this.test = test; } } const a = new A("hi"); const plainObj = a.toPlainObject(); // 输出:{ test: 'hi' }
最后总结一下
- 简单类用展开语法/Object.assign,快捷高效;
- 需要精确控制转换逻辑用手动实现toPlainObject;
- 处理不可枚举属性或复杂类用Reflect.ownKeys工具函数;
- 多个类需要转换用装饰器批量处理。
内容的提问来源于stack exchange,提问作者NoKey
相关产品推荐
相关产品推荐

