如何在TypeScript中循环遍历类的属性? 以下面的课程为例:
export class Task implements Itask {
public Id: number = 0;
public Name: string;
public Description: string;
public Completed: boolean = false;
public TaskType: TaskType;
}
我想检索属性,因此:[" Id",Name"," Description"," Completed"," TaskType& #34;]
尝试
GetTaskHeaders = () => {
const _self = this;
const tHead = $('<thead />').append('<tr />');
for (let i = 0; typeof TodoApp.Task.arguments; i++) {
const th = $('<th />');
th.append(TodoApp.Task.arguments[i]);
tHead.append(th);
}
console.log(tHead);
return tHead;
};
不幸的是,没有成功,我知道使用&#34; TodoApp.Task.arguments&#34;是不正确的。 但是,有人能告诉我正确的方法吗?
答案 0 :(得分:11)
让我们考虑所有&#34;未定义&#34;属性,即在typescript类中定义的所有属性,如(我写了&#34;未定义&#34;而不是undefined
,原因将在下面明确说明)
class A {
prop1: string
prop2: number
}
任何Object.keys
或this.hasOwnProperty(k)
都不会枚举,因为autogen javascript不知道这些属性。 创建typescript类时,只有一个选项,即将所有属性初始化为默认值,如
class A {
prop1: string
prop2: number
prop3: B
constructor() {
this.prop1="";
this.prop2=-1;
this.prop3=null;
}
}
此时,您将获得A
实例的所有属性,例如在字典中的映射迭代中
var a = new A();
for (var i in properties) {
if (a.hasOwnProperty(i)) {
a[i]=properties[i];
}
}
如果您不喜欢默认值解决方案,您仍然可以使用神奇的undefined
javascript关键字执行此操作,以便执行以下操作:
class A {
prop1: string = undefined
prop2: number = undefined
}
此时,javascript对应项将包含模型中的所有属性,您将使用Object.keys(this)
进行迭代,或通过this.hasOwnProperty
答案 1 :(得分:9)
请参阅How do I loop through or enumerate a JavaScript object?
在您的情况下,例如:
for (var i in TodoApp.Task) {
if (TodoApp.Task.hasOwnProperty(i)) {
var th = $('<th />').append(TodoApp.Task[i]);
tHead.append(th);
}
}
答案 2 :(得分:1)
这是我的回答,基于以下解释的问题:
<块引用>如何在运行时迭代 TypeScript 声明的类或其他声明的接口(甚至对象类型)的(公共)属性的枚举?
而且问题可以是使用私有类成员,因为它们可以在任一范围内访问。
答案:做不到。很遗憾。您可以做的唯一一件事就是接近它。这有望解释此处 Q/As 之间的歧义,以及一些 TS 开发人员可能真正想做的事情:
(在 TS 游乐场 here 上检查/运行下面的代码)
interface IFoo {
firstProp: number
secondProp: number
}
class Foo implements IFoo {
readonly firstProp = 100;
readonly secondProp = 200;
someOtherProp = "bar";
}
enum IFooProps {
firstProp,
secondProp
}
for (key in Object.keys(IFooProps)) { // or at best IFoo, not needing to use an enum
// ... do something with interface keys
}
请注意,目前还没有任何方法可以在编译时检查 IFooProps
和 IFoo
是否实际匹配(TS 功能请求...)。
而且,上面的方法不太好用,因为枚举对象的键也包括它的值 ...
但是,现在要解决这个问题,我们可以这样做:
const foo = new Foo();
Object.keys(IFooProps).forEach(prop => {
if (!isNaN(Number(prop))) return;
console.log(foo[prop]) // prints value of all IFoo implementations
});
// OR (this is just a "nicer" way to effectively run the same code as above here ^)
// can only be done with "runtime alive" objects (enums are, but class/interface are types not objects,
// but enums are also types too ;))
function enumKeys<O extends object, K extends keyof O = keyof O>(obj: O): K[] {
return Object.keys(obj).filter(k => Number.isNaN(+k)) as K[];
}
enumKeys(IFooProps).forEach(prop => {
console.log(foo[prop])
})
如果 TypeScript 允许检查 IFooProps
是否实际枚举了 IFoo
的属性(或者编译器允许从任何声明的接口显式或隐式地声明/生成这样的枚举),那么这实际上是类型安全的(而且方便)。
目前,这是一个相当笨拙的解决方法,需要“两次”声明接口(在枚举中是多余的)。
归功于:https://www.petermorlion.com/iterating-a-typescript-enum/
(用于帮助 enumKeys
助手)
编辑:
对这个问题的另一种可能解释(或确保澄清我们上面所说的内容):
<块引用>在编译时使用接口键的枚举(仅)
是的,可以枚举接口,但不能在运行时:
(在 TS playground here 中运行)
interface IBar {
firstThing: [string, string]
secondThing: [number, number]
}
function doThatWithTypedThing<Key extends keyof IBar>(someDeclaredThingKey: Key, someDeclaredThing: IBar[Key]) {
console.log(someDeclaredThingKey, someDeclaredThing)
}
const bar: IBar = {
firstThing: ["bli", "bla"],
secondThing: [400, 500]
}
doThatWithTypedThing("firstThing", bar.firstThing) // prints: firstThing [ "bli", "bla" ]
doThatWithTypedThing("secondThing", bar.secondThing) // prints: secondThing [ 400, 500 ]
doThatWithTypedThing("firstThing", bar.secondThing) // <- compiler error 2345
doThatWithTypedThing("notFirstThing", bar.secondThing) // <- other compiler error 2345
答案 3 :(得分:0)
我在从 javascript 迁移到 typescript 时遇到了类似的问题,并且我的 javascript 代码在对象的属性上循环。
较旧的答案给出了类型安全的解决方案,这个答案不是类型安全的,只是使用类型转换避免了打字稿错误。这意味着如果您分配无效的属性或为属性分配错误类型的值,typescript 不会产生错误。
循环属性的 javascript 示例:
function loop_over_props(object) {
for (let k in object)
console.log(object[k]);
}
做同样事情的打字稿:
interface HashMap<T> {
[key: string]: T;
};
type SomeType = {
field1: number;
field2: string;
field3: number;
};
function loop_over_props(object: SomeType) {
var casted_object: HashMap<any> = <HashMap<any>>object;
for (let k in casted_object)
console.log(casted_object[k]);
}
对于像我这样的情况,您正在迁移现有的 javascript 并且没有很多需要不安全代码的情况,那么将代码转换为 typescript 可能有足够的好处来接受一些不安全的情况。