0

I have a custom interface that I've written, and a variable that is typed using that interface.

I want to be able to index my object using a key string to return a specific value. And to do that I'm doing var[key], but I'm getting a typescript error.

Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'BasicMonitorSpec'.   No index signature with a parameter of type 'string' was found on type 'BasicMonitorSpec'.

I've definitely done this before, so I'm not sure what I'm doing wrong.

export interface BasicMonitorSpec{
    width: string,
    eyeTech: boolean,
    panelType: string,
    refreshRate: string,
}

calculateWeight(inputSpec: BasicMonitorSpec, testSpec: BasicMonitorSpec){
        let keys = Object.keys(testSpec);

        keys.forEach(key => {
            let inputValue: any;
            inputValue = inputSpec[key]; //<-- Error is on this line
            console.log("INPUTVALUE: ", inputValue);
        });
    }

My own working example

let results: PropResults = this.propResultService.propResults;
    let summaryData: SummaryDataRow[] = [];
    Object.keys(results).forEach(key => {
      let mapping: PropMapping;

      if(results[key] === '') return; //This works 
}

Updated link

jm123456
  • 509
  • 1
  • 8
  • 20
  • Does this answer your question? [TypeScript: Object.keys return string\[\]](https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string) – Jared Smith Dec 16 '20 at 21:18
  • @JaredSmith No it doesn't. I've added my own code which works to the post, please tell me how that code works and yet the code I've written above doesn't. `PropResults` is just an interface – jm123456 Dec 16 '20 at 21:33
  • 1
    @jm123456 it would be helpful if your second example came with all required type declarations. – zerkms Dec 16 '20 at 21:34
  • @zerkms It's simply an interface with a number of string declarations, that's it – jm123456 Dec 16 '20 at 21:35
  • I feel like I'm going crazy because this code is semantically the exact same. An object with a type interface is indexed using a string, how does one work and one doesn't? – jm123456 Dec 16 '20 at 21:36
  • @jm123456 it does not work either for me: https://www.typescriptlang.org/play?#code/JYOwLgpgTgZghgYwgAgApQPYAcBKEDOArgDZj7IDeAUMrcjBhgFzL5hSgDmA3DXQEZwoLEIQC2-aLwC+VKsQhhkUAiTIt02PEVLkAvJQbNkAcjj8EJgDTJBw5ABYATNN5UA8vwBWEBGAB0ANYQAJ74ABQqOmQAlP4MUACiiAAW4cEhyHoAfJR8tMAwkaq6ANoZALpZegYmJjHKioRQINzIAPTtACopwOQA7hhQgeRU0jFAA – zerkms Dec 16 '20 at 21:40
  • @zerkms I've just copied and pasted the following code from one project to another. `let x = {'prop':'stirng' }; let y = x["key"]` it works in one but not in the other. I'm writing it in a class method in both projects, why does one work but not the other???? – jm123456 Dec 16 '20 at 21:41
  • That's why I suggested to provide a _working_ example that demonstrates the problem: in the playground link I provided - that code does not work either (as expected). – zerkms Dec 16 '20 at 21:42
  • 1
    @jm123456 that's just stack overflow's phrasing not mine. That *does* answer your question, and that comment was automatically added because I voted to close yours as a duplicate of that one. Your problem is that when the compiler sees Object.keys it does not and cannot assume that the set of keys of the given object *known at compile-time* corresponds perfectly to the set of keys enumerated at runtime, so if you as the programmer know better you need to assert that to the compiler...and deal with the consequences if you turn out to be wrong, it can't guarantee that you'll get a known key. – Jared Smith Dec 16 '20 at 21:44
  • @zerkms I've edited your link with some code of my own that does work, please have a look. I can't tell what the difference is between the two examples, they look identical to me. – jm123456 Dec 16 '20 at 21:47
  • 2
    @jm123456 you need to share the new link, it's only visible to you otherwise :-) – zerkms Dec 16 '20 at 21:48
  • @JaredSmith I understand that, but I'm just very confused as to why I'm suddenly getting compile errors now for doing this in my code when I've done this before and never had any issue. If you take a look at the link posted by zerkms I've added some code that is semantically the same but doesn't throw compile errors. – jm123456 Dec 16 '20 at 21:49
  • 1
    @jm123456 the urls are immutable, you need to share a link with the edited code or we can't see your edits. As to why you would "suddenly" get that error if you changed the noImpicitAny setting in your tsconfig... it would cause that to suddenly be a problem. – Jared Smith Dec 16 '20 at 21:50
  • @zerkms Apologies, it's in the OP. It was too long for the comments apparently – jm123456 Dec 16 '20 at 21:51
  • @JaredSmith That was the problem, it was set in the tsconfig. I had no idea that was a setting. Thank you. – jm123456 Dec 16 '20 at 21:52
  • 1
    @jm123456 mouse over `results` and see it's of `any` type. Type checker does not verify expressions against it. – zerkms Dec 16 '20 at 21:52
  • 1
    To further what @zerkms is saying, your assertion doesn't take because the playground doesn't have access to the missing imported type. So the two aren't really the same, you have an untyped Object.keys iteration and a typed one and the typed one fails for the reasons cited. – Jared Smith Dec 16 '20 at 21:53

2 Answers2

0

I made a quick search and saw this discussion:

Get keys of a Typescript interface as array of strings

It is probably because you are trying to get the keys of an interface rather than an object. Your only choice seems like creating a class that implements that interface and create an object with the type of that class, then start reading the keys from it.

Hope this helps you to solve the issue.

-1

You should use inputSpec as Object to use Object type of indexing:

inputValue = Object(inputSpec)[key];

Other way is to put index in interface declaration:

export interface BasicMonitorSpec {
    [index: string]: any,
    width: string,
    eyeTech: boolean,
    panelType: string,
    refreshRate: string,
}
Leszek Mazur
  • 2,443
  • 1
  • 14
  • 28
  • 2
    It loses all type safety TS provides. It's just barely better than typing `inputSpec` as `any`. – zerkms Dec 16 '20 at 21:32
  • Yes, but this whole example is prepared in type breaking way. We can use object that implements interface and have another fields as `testSpec` – Leszek Mazur Dec 16 '20 at 21:46