我在打字稿上有以下对象来控制体育比赛的结果:
export interface IResult {
[day: string]: IResultDay;
}
interface IResultDay {
[matchId: string]: IMatch;
}
interface IMatch {
teams: ITeam[];
winner: ITeam;
winnerScore: number;
loserScore: number;
}
我之所以这样构建它,是因为它可以过滤“天”和“ matchId”中要查看的匹配项。
问题是,当我要构建该对象时,需要继续验证每个级别上的对象是否不是undefined
。如果我不这样做,则会发生以下情况:
const result: IResult = {}; // init the first level
result['2020-09-30']['2020093012344321'] = {
teams: [
{
teamId: '1234',
teamName: 'Lakers'
},
{
teamId: '4321',
teamName: 'Miami Heat'
}
],
winner: {
teamId: '1234',
teamName: 'Lakers'
},
winnerScore: 117,
loserScore: 107
};
错误:
TypeError: Cannot set property '2020093012344321' of undefined
当我深入嵌套对象时,情况变得更糟。是否有一种无需初始化每个级别即可构建该对象的方法?
在python中,字典上有此技巧,可让我们同时启动多个级别:
from collections import defaultdict
my_dict = defaultdict(lambda: defaultdict(dict))
我想要做完全相同的事情(或具有相同行为的事情)。在创建对象之前不断初始化每个级别确实很奇怪。
javascript / typescript上有类似的东西吗?
答案 0 :(得分:1)
没有内置任何内容,但是您可以使用Proxy
来拦截属性访问,并在属性不存在时插入默认值。也许是这样的:
function defaultDict<T>(cb: (k: PropertyKey) => T): { [k: string]: T } {
return new Proxy({} as any, {
get(target, p, receiver) {
if (!(p in target)) {
target[p] = cb(p);
}
return target[p];
}
})
}
我不知道回调函数是否关心传入的密钥,但无论哪种方式都没有关系。然后,您可以像这样制作result
:
const result: IResult = defaultDict(() => ({}));
它实际上只需要有一个defaultDict()
,因为设置result[day][match] = ...
您实际上只需要定义result[day]
。然后,我想这就是您所期望的:
result['2020-09-30']['2020093012344321'] = {
teams: [
{
teamId: '1234',
teamName: 'Lakers'
},
{
teamId: '4321',
teamName: 'Miami Heat'
}
],
winner: {
teamId: '1234',
teamName: 'Lakers'
},
winnerScore: 117,
loserScore: 107
};
这没有错误,然后就可以了:
for (let day in result) {
for (let match in result[day]) {
console.log(JSON.stringify(result[day][match]))
}
}
/* {"teams":[{"teamId":"1234","teamName":"Lakers"},{"teamId":"4321","teamName":"Miami Heat"}],
"winner":{"teamId":"1234","teamName":"Lakers"},"winnerScore":117,"loserScore":107} */
答案 1 :(得分:0)
不幸的是,不,javascript确实没有任何东西允许一次性设置多个嵌套级别的字典。
答案 2 :(得分:0)
可悲的是,JavaScript无法做到这一点。但是,您可以使用一些依赖项来实现此目的,例如lodash
:
const _ = require('lodash');
const result: IResult = {};
_.set(result, ['2020-09-30', '2020093012344321'], {} /* replace {} with your value */);