TypeScript如何通过字符串名称设置对象属性?(替代C#反射)
TypeScript中通过属性字符串名称设置对象属性(类似C#反射)
问题描述
我刚接触TypeScript,正在移植C#代码,需要实现通过属性字符串名称设置对象实例属性的功能。在C#中我用反射实现该功能,想了解TypeScript里的实现方式?
以下是简化示例代码:
class BaseClazz { baseA?: string; baseB?: string; } class DerivedClazz extends BaseClazz { derived1?: number; derived2?: number; array1?: number[]; array2?: number[]; }
我需要一个能通过字符串名称设置各类属性的函数:
function assign(clazz: BaseClazz, propertyName: string, value: any) { // 实现逻辑 }
期望调用方式:
const test: BaseClazz = new DerivedClazz(); assign(test, "baseA", "a"); assign(test, "baseB", "b"); assign(test, "derived1", 1); assign(test, "derived2", 2); assign(test, "array1", [1, 2, 3, 4]); assign(test, "array2", [5, 6, 7, 8]);
实现方法
1. 基础实现(简单直接)
TypeScript编译后是JavaScript,JS对象本身支持通过索引器动态设置属性,无需像C#那样依赖反射API,直接赋值即可:
function assign(clazz: BaseClazz, propertyName: string, value: any) { // 类型断言绕过编译检查,直接赋值 (clazz as any)[propertyName] = value; }
这个方法简单,但缺点是无类型校验——传入不存在的属性名或类型不匹配的值时,TypeScript不会提前报错,可能引发运行时问题。
2. 类型安全的实现(推荐)
要保留TypeScript的类型优势,避免错误的属性名或值类型,可以用泛型+键类型约束优化函数:
function assign<T extends BaseClazz>(clazz: T, propertyName: keyof T, value: T[keyof T]) { clazz[propertyName] = value; }
优势说明:
keyof T会自动推导T的所有属性名(包括继承自父类的属性),传入不存在的属性名会直接在编译时报错T[keyof T]会匹配对应属性的类型,传入错误类型的值也会触发编译报错
比如调用assign(test, "wrongProp", "xxx")或assign(test, "derived1", "string"),TypeScript会立即提示错误,提前规避问题。
3. 通用版本(支持任意对象)
如果想让函数不局限于BaseClazz,可进一步泛化为支持任意对象:
function assign<T>(obj: T, propertyName: keyof T, value: T[keyof T]) { obj[propertyName] = value; }
这个版本可以安全处理任何TypeScript对象,包括自定义类、字面量对象等。
注意事项
- 私有属性(用
private修饰)无法通过这种方式设置,因为TypeScript编译后会限制外部访问私有成员 - 只读属性(
readonly)会触发编译报错,因为无法修改只读成员
内容的提问来源于stack exchange,提问作者DAufderh
相关产品推荐
相关产品推荐

