1

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.

1
  • There are at least two problems here. The first one is trying to get a property with an arbitrary string. TS does not know which property (if any) you'd get and thus cannot guarantee type safety. Second the array being declared as only either numbers or strings, means that you can only add one or the other. There is no guarantee whether you got an array of numbers and you're trying to push a string into it or vice versa. Commented Mar 24, 2022 at 14:06

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.