非常新的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: BaseClass, propertyName: string, value: any) {
...
}
理论上,我可以如下调用它,并设置4个属性中的每一个:
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条答案
按热度按时间nue99wik1#
由于JavaScript中的所有对象类型本质上都是属性包,因此可以将
assign()
编写为generic函数,该函数的第一个参数接受任何对象(而不仅仅是BaseClazz
的子类型):这里
obj
是限制为object
的泛型型别T
,而key
是限制为T
之索引键的泛型型别K
(使用thekeyof
type operator),而val
是indexed access typeT[K]
,这是obj[key]
的属性型别。如果你真的想把这个函数限制在
BaseClazz
的子类型上,你可以写T extends BaseClazz
而不是T extends object
,但是除非你需要assign()
中BaseClazz
的其他功能,否则没有太多理由这样做。让我们来确保这一点:
看起来不错。如果您传入的
key
未知存在于test
上,编译器会发出抱怨;如果您传入的value
不是与索引到test
中的键为key
的属性相对应的类型,编译器也会发出抱怨。这和TypeScript通常为泛型提供的类型安全差不多,但并不完全合理。例如,如果
key
是一个联合类型,那么value
也可以是相应的联合类型,这可能很奇怪:但是,无论好坏,这种语言都有意地存在着不健全的地方(参见关于microsoft/TypeScript#9825的评论)。还有其他方法可以将错误的内容放入属性中,因为TypeScript将对象类型视为其属性中的协变,这同样很奇怪:
因此,在将子类型化与属性赋值结合使用时要小心!
Playground代码链接