Home > Software design >  TypeScript - Why I cannot push value to a string after I have defined the array type to number[] | s
TypeScript - Why I cannot push value to a string after I have defined the array type to number[] | s

Time:03-25

I get an error as below

Argument of type 'any' is not assignable to parameter of type 'never'.

And the error is at alarm[key]

Here is my code:

import { Injectable } from '@angular/core';
import alarmData from '../../mockData/alarmdData.json';

interface IAlarm {
  createdTime: string;
  station: string;
  deviceID: string;
  category: string;
  alarmValue: number;
  alarmType: string;
  status: string;
  startTime: string;
  endTime: string;
  handleState: string;
}

@Injectable({
  providedIn: 'root',
})
export class AlarmDataService {
  setColumnData(key: string, array: number[] | string[]): void {
    alarmData.forEach((alarm: IAlarm) => array.push(alarm[key]));
  }

  logData() {
    console.log(alarmData);
  }
}

My json file content is below:

[
  {
    "createdTime": "2022/03/24 18:00",
    "station": "testStation",
    "deviceID": "S1001",
    "category": "SO2",
    "alarmValue": 33,
    "alarmType": "SO2 limit",
    "status": "alarm",
    "startTime": "2022/03/24 18:00",
    "endTime": "2022/03/24 19:00",
    "handleState": "handled"
  },
  {
    "createdTime": "2022/03/24 19:00",
    "station": "test1Station",
    "deviceID": "S1002",
    "category": "NO",
    "alarmValue": 33,
    "alarmType": "NO limit",
    "status": "alarm",
    "startTime": "2022/03/24 20:00",
    "endTime": "2022/03/24 21:00",
    "handleState": "handled"
  }
]

Why I get this hint 'Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'IAlarm'. No index signature with a parameter of type 'string' was found on type 'IAlarm'.'.

What should I do to debug my code? Thank you for helping me in advance.

I have tried to change the array to 'any' but it still does not work.

CodePudding user response:

The way I read your code, it seems like the intent of the setColumnData function is as follows:

Given a property defined on the IAlarm interface and an array of IAlarm objects, extract the value of this property from each of those objects, and put all these values into a single array.

With that in mind, this should work:

setColumnData<Key extends keyof IAlarm>(key: Key, array: IAlarm[Key][]): void {
    alarmData.forEach((alarm) => array.push(alarm[key]));
}

Some notes:

  • By using Key extends keyof IAlarm, we ensure that the key parameter can only be one of the properties of IAlarm (e.g. station or category). Any other values will cause a type error.
  • Using IAlarm[Key][] as the type of the array parameter ensures that the type of the values in the array matches that of the property on IAlarm (number for alarmValue, string for anything else). This has the benefit of supporting additional types without requiring modifications to this method (for example, if you were to add a boolean property to IAlarm).

Here is a simplified version of this on the TS Playground.

  • Related