如何在Typescript中编写链式动态对象属性?



我正在切换一个JS项目到TS,我正在努力与我的代码的某一部分,TS抱怨,我不知道如何解决这个问题。

在TS中,我想在一个名为licensesStats的动态对象中收集数据,最终可能看起来像这样:

{
'DYNAMIC_NAME': {
'Usage count': 2,
'Used by': {
'SOME_DYNAMIC_NAME': null,
'SOME_OTHER_NAME': null,
[...]
}
},
[...]
}

对于我的licensesStats对象,我创建了以下interface:

interface LicenseStatsCounter {
[key: string]: number;
}
interface LicenseStatsModule {
[key: string]: null;
}
interface LicenseStatsModules {
[key: string]: LicenseStatsModule;
}
interface LicensesStats {
[key: string]:
| LicenseStatsCounter
| LicenseStatsModules;
}
licensesStats: LicensesStats = {}
...

键"使用量"one_answers"使用;都存储在变量中,因此在数据收集期间的代码中,有这样一个命令:

licensesStats[license][titleUsedBy][moduleNameAndVersion] = null;

但TS抱怨:

元素隐式地具有'any'类型,因为type的表达式'string'不能用于索引类型'number | LicenseStatsModule'。
在类型上没有找到带有'string'类型参数的索引签名'number | LicenseStatsModule'.

我该怎么做才能满足TypeScript的需求?

注:以下是我的问题的示例TS文件:

const titleUsageCount = 'Usage count';
const titleUsedBy = 'Used by';
interface LicenseStatsCounter {
[key: string]: number;
}
interface LicenseStatsModule {
[key: string]: null;
}
interface LicenseStatsModules {
[key: string]: LicenseStatsModule;
}
interface LicensesStats {
[key: string]: LicenseStatsCounter | LicenseStatsModules;
}
// Exported functions:
export const readLicenses = (argv: Argv) => {
const licensesStats: LicensesStats = {};
const license = 'MIT';
const moduleNameAndVersion = 'chalk@1.0.0';
licensesStats[license] = licensesStats[license] || {
[titleUsageCount]: 0,
...((argv.summaryPlus as boolean) && { [titleUsedBy]: {} }),
};
(licensesStats[license][titleUsageCount] as number)++;
// This is the problematic line, where TS says:
// Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'number | LicenseStatsModule'.
// No index signature with a parameter of type 'string' was found on type 'number | LicenseStatsModule'.
licensesStats[license][titleUsedBy][moduleNameAndVersion] = null;
}
};

在当前的设置下,typescript到达licensesStats[license][titleUsedBy]并看到两个可能的值:numberobject(LicenseStatsModule)并抛出错误,因为数字不能包含属性。

你将需要一些条件检查来使typescript满意,比如:

const x = licensesStats[license][titleUsedBy];
if(typeof x !== "number"){
const y = x[moduleNameAndVersion];
// ... do something
return;
}
// ... do something
return;

最新更新