skip to Main Content

Perhaps what I’m asking to do is impossible, or I’m taking the wrong approach but is it possible to use a string to do a lookup on an imported namespace?

If I have a file: my_file.ts and its contents are many of these:

export const MyThing: CustomType = {
    propertyOne: "name",
    propertyTwo: 2
}
export const AnotherThing: CustomType = {
    propertyOne: "Another",
    propertyTwo: 3
}

Then I have a file that is going to import all these, but needs to find and use them dynamically based on a string:

import * as allthings from "dir/folder/my_file"


function doStuff() {
   let currentThing = allthings['MyThing']; // works
   let name = 'MyThing';
   let currentThing2 = allthings[name]; // doesnt work

}

The error I get here is:

Element implicitly has an ‘any’ type because expression of type
‘string’ can’t be used to index type ‘typeof
import("dir/folder/my_file")’. No index signature with a parameter of
type ‘string’ was found on type ‘typeof import("dir/folder/my_file")’.

Why does the literal string work but not a variable of type string?

2

Answers


  1. Chosen as BEST ANSWER

    I reread a similar question here: Element implicitly has an 'any' type because expression of type 'string' can't be used to index

    And was finally able to get it to work by doing this:

    import * as allthings from "dir/folder/my_file"
    
    
    function doStuff() {
       let currentThing = allthings['MyThing']; // works
       let name = 'MyThing';
       let currentThing2 = allthings[name as keyof typeof allthings]; // does work
    
    }
    

  2. The literal string doesn’t work because someone could reassign any string to your let name variable.

    It will work if your string is const. Casting it is possible:

    let name = 'MyThing' as const;
    

    But you should just define a const variable which has the same effect. There’s no reason to define a variable with let unless you intend to change it.

    const name = 'MyThing';
    

    See this TS playground example

    If you don’t know the key ahead of time, then if all the objects in my_file are of the same type (CustomType), then you can safely use keyof typeof allthings as the type

    export const allthings = {
      MyThing: {
        propertyOne: "name",
        propertyTwo: 2
      },
      AnotherThing: {
        propertyOne: "Another",
        propertyTwo: 3
      }
    };
    
    type CustomType = typeof allthings[keyof typeof allthings];
    
    
    function getValue(key: keyof typeof allthings): CustomType {
        return allthings[key]; 
    }
    

    See TS example

    For these enum like objects, you can use satisfies Record<string, MyType> to enforce they are all of the same type

    interface CustomType {
      propertyOne: string,
      propertyTwo: number
    }
    
    const allthings = {
      MyThing: {
        propertyOne: "name",
        propertyTwo: 2
      },
      AnotherThing: {
        propertyOne: "Another",
        propertyTwo: 3
      }
    } satisfies Record<string, CustomType>;
    
    
    function getValueFromAllThings(key: keyof typeof allthings): CustomType {
        return allthings[key]; 
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search