I'm in the process of converting a JavaScript project to TypeScript and encountering difficulties with a certain section of my code that TypeScript is flagging as an issue.
Within TypeScript, I aim to gather data in a dynamic object named licensesStats
, which may eventually take the form shown below:
{
'DYNAMIC_NAME': {
'Usage count': 2,
'Used by': {
'SOME_DYNAMIC_NAME': null,
'SOME_OTHER_NAME': null,
[...]
}
},
[...]
}
To define my licensesStats
object, I've defined the following set of interfaces:
interface LicenseStatsCounter {
[key: string]: number;
}
interface LicenseStatsModule {
[key: string]: null;
}
interface LicenseStatsModules {
[key: string]: LicenseStatsModule;
}
interface LicensesStats {
[key: string]:
| LicenseStatsCounter
| LicenseStatsModules;
}
licensesStats: LicensesStats = {}
...
The keys "Usage count" and "Used by" are stored as variables. In the code for collecting data, there's a line that reads:
licensesStats[license][titleUsedBy][moduleNameAndVersion] = null;
However, TypeScript raises a complaint:
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'.
What adjustments do I need to make to satisfy TypeScript's requirements?
P.S.: Below is a sample TypeScript file illustrating my issue:
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 = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="54373c35383f14657a64">[email protected]</a>';
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;
}
};