Tips for creating cascading dynamic attributes within Typescript?

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;
    }
};

Answer №1

When your current configuration is in use, typescript reaches

licensesStats[license][titleUsedBy]
and encounters two possible values: either a number or an object (the LicenseStatsModule) which causes an error because a number cannot contain a property.

To satisfy typescript, you will need to implement some conditional checks, similar to the following:

const x = licensesStats[license][titleUsedBy];

if(typeof x !== "number"){
  const y = x[moduleNameAndVersion];

  // ... do something
  return;
}

// ... do something
return;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Library for Nodejs that specializes in generating and converting PDF/A files

Is there a library available that can convert/create a PDF/A file? I've been searching for solutions but the existing answers suggest using an external service or provide no response at all. I heard about libraries in other languages like ghostscriptP ...

Determine whether the radio button has been selected

Within my HTML code, there's a radio button enclosed in a form: <mat-radio-button [(ngModel)]="boxChecked" name="boxChecked" value="boxChecked">Check me</mat-radio-button> In the TypeScript section, I've declared my boolean variable ...

Using Webpack 4 and React Router, when trying to navigate to a sub path,

I'm currently working on setting up a router for my page, but I've encountered a problem. import * as React from 'react'; import {Route, Router, Switch, Redirect} from 'react-router-dom'; import { createBrowserHistory } from ...

The Angular 2 router is not compatible with using the same component but with different IDs

Currently utilizing the alpha8 router with 3 main routes: export const appRoutes: RouterConfig = [ { path: '', component: LandingComponent }, { path: 'blog', component: BlogComponent }, { path: 'posts/:id', compon ...

Challenges arise when attempting to share a theme across different repositories within a Storybook monorepo that utilizes

In my unique project setup, I have a singular repository containing atoms, molecules, and organisms along with storybooks to develop a custom components library. This library is based on MUI framework with a customized theme applied, all built with TypeScr ...

What is the best way to utilize v-model with an array of strings in a Vuex store when using v-for

Encountered an issue while trying to set a value in an Array within the Vuex Store: VueCompilerError: v-model cannot be used on v-for or v-slot scope variables because they are not writable. Seeking alternatives to achieve this without creating a local co ...

What specific characteristic of TypeScript's number data type or the Math.ceil() function is responsible for this calculation mistake?

Currently, I am working on a function in Typescript that is supposed to generate a unique number each time it runs. However, there seems to be a problem with the arithmetic as the results are not always correct. Upon further examination of the code below, ...

Having trouble with the Ng multiselect dropdown displaying empty options?

I'm currently facing a challenge in adding a multiselect dropdown feature to my project. Below is the code I have been working on: HTML <ng-multiselect-dropdown [settings]="searchSettings" [data]="dummyList" multiple> </n ...

Prevent coverage tracking for files or paths enclosed in square brackets in jest

I am trying to exclude a specific file from test coverage in Jest by modifying the collectCoverageFrom array. The file name contains square brackets, and I have added an entry with a negation for this file. collectCoverageFrom: [ './src/**/*.{js ...

Type ' ' cannot be assigned to type ''..ts(2322) ANOTHA ONE

Being a beginner in TypeScript and currently learning about enums, I encountered an error with the following example code that I cannot seem to understand. Here's the code snippet: enum Status { SUCCESS = 'success', FAILED = 'fa ...

ridiculing callback within parameter

I have a model setup in the following way: export class MyClass { grpcClient: MyGRPCClient; constructor(config: MyGRPCClientConfig) { this.grpcClient = new MyGRPCClient( config.serverUrl, grpc.credentials.createInsecure(), ); ...

Using TypeScript to pass a callback function to labelFormatter in the legend of a Highcharts chart

I am currently experimenting with integrating HighCharts into an Angular2 project using TypeScript. My goal is to customize the appearance of the legend text, adding an image next to it. I've found that HighCharts provides a labelFormatter property w ...

There is a delay in updating ng-if/ng-hide in real time on the HTML page

Assistance needed for implementing a slight adjustment in AngularJS with TypeScript. The requirement is to change the text of a button for 3 seconds upon clicking, then revert back to its original text. Two HTML elements are created for this purpose, each ...

The functionality of CDK Drag Drop is not accurately adjusting the placement of images

I have implemented an image gallery and am working on rearranging the position of the images using the Drag & Drop cdk library. However, I am facing an issue where the swapping of images does not always occur correctly; sometimes when attempting to exchan ...

Unlocking the Power of Passing Props to {children} in React Components

Looking to create a reusable input element in React. React version: "react": "17.0.2" Need to pass htmlFor in the label and use it in the children's id property. Attempting to pass props to {children} in react. Previously attempte ...

The type 'undefined' cannot be assigned to a different type within the map() function, resulting in a loss of type information

I am facing an issue in my redux toolkit where an action is trying to set some state. Below is the relevant code snippet: interfaces export interface ProposalTag { id: number; name: string; hex: string; color: string; } export interface ProposalS ...

Failure of React to connect event handlers

LATEST UPDATE: After removing the output entry from my webpack configuration, the React event listeners are now functioning correctly. Currently, I am diving into the world of hand-rolling webpack configurations for a React/TypeScript application for the ...

Struggling to bring in components in ReactJS

My journey with ReactJS has just begun, and I've encountered some issues with the code that I believe should work but doesn't. To start off, I set up a new ReactJS project using the npm command create-react-app. Following this, I installed Googl ...

Is it feasible to evaluate a Typescript method parameter decorator at request time in a nodejs+nestjs environment rather than just at build time?

Looking to simplify my handling of mongodb calls with and without transactions in a single service method by writing a decorator. This would help eliminate the repetition of code and make things more efficient. Key points for usage: • Service class has ...

The method this.$el.querySelector does not exist

The data retrieved from the database is inserted into the input fields and submitted as a form. This data is an object that passes the value to the database. However, when I trigger this form, an error occurs. See example of the error <input id=" ...