有两个接口,一个具有一些可选属性,而另一个则没有:
interface ISTATE {
events?: {
[key in HookName]?: EventFunc
},
transitions?: {
[transName: string]: TransFuncStr
},
store?: {
[key: string]: any
}
}
interface IVALIDSTATE {
name: string
events: {
[key in HookName]?: EventFunc
},
transitions: {
[transName: string]: TransFuncStr
},
store: {
[key: string]: any
}
}
我想将ISTATE
转换为IVALIDSTATE
。对于ISTATE
中的每个属性,我必须检查它是否存在,并将值复制到IVALIDSTATE
对象:
function resolveStates(iStates: { [name: string]: ISTATE }): { [name: string]: IVALIDSTATE } {
const ret: { [name: string]: IVALIDSTATE } = {}
for (const i in iStates) {
ret[i] = {} as IVALIDSTATE
ret[i].name = i
if (!iStates[i].events) {
ret[i].events = {}
} else {
ret[i].events = iStates[i].events as any
}
if (!iStates[i].transitions) {
// same if statement like'events'
}
if (!iStates[i].store) {
// same if statement like'events'
}
}
return ret
}
if (!iStates[i].property) {}
语句过多,我可以使用for ... in
语句代替许多重复的语句吗? (因为... in需要运行时,所以keyof
可以做到吗?)as any
以避免类型检查。答案 0 :(得分:2)
所以,也许您正在寻找类似的东西:
ret[i] = {} as IVALIDSTATE
ret[i].name = i
// new stuff below
const keys: (keyof ISTATE)[] = ['events','transitions','store'];
keys.forEach(k => {
const iStateK = iStates[i][k];
ret[i][k] = iStateK || {};
});
要点:
keys
数组被声明为类型为keyof ISTATE
的数组,因此当我们在其上执行forEach()
时,编译器对ret[i][k]
和{ {1}}。
临时变量iStates[i][k]
在运行时不是必需的,但它可以帮助编译器执行control flow analysis。与iStateK
中一样,有一个limitation in the compiler that prevents control flow anlaysis from happening when you check a property using bracket notation。解决方法是将iStates[i][k]
的值分配给新变量,然后进行检查。
将iStates[i][k]
分配给iStateK || {}
之所以有效,是因为编译器使用控制流分析来认识到,如果ret[i][k]
为truthy,则该值将为short-circuit并且表达式不能是未定义的;否则(如果iStateK
为falsy),则表达式将为iStateK
,这也是未定义的。因此,编译器对您正在为{}
分配有效值感到满意。
希望有帮助。祝你好运!