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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:32:17