Search code examples
javascripttypescriptobject

Make an object key from passed literal argument in TypeScript


I would like to know whether the below is possible. Based on the argument passed, recoginize the object key and access with that key.

Any solutions?

async function func(arg:'key1'|'key2'){
  // fetchResult returns an object which includes {key1:'result1'} or {key2:'result2'}
  const obj:{[arg]:string} = await fetchResult('url')
  console.log(obj[arg])
}

await func(key1) //Expect console.log('result1')

await func(key2) //Expect console.log('result2')

Solution

  • All you are asking is how to create an interface dynamically from a string union type. If the result of fetch function contains both key types you could just iterate over the type of the argument instead of assigning a specific value

    const obj:{[key in typeof arg]: string} = await fetchResult('url')
    

    I doubt you need to further narrow it down, since regardless of the value of the key the type of statement obj[arg] will still be a string.

    If you do need to narrow the type down to specific result, what is stopping you from typing them directly? You know what the return value of fetch is, so why not add it exactly?

    async function func<T extends 'key1' | 'key2'>(arg: T){
      // fetchResult returns an object which includes {key1:'result1'} or {key2:'result2'}
      const obj: {key1: "result1", key2: "result2"} = await fetchResult('url')
      return obj[arg];
    }
    
    (async () => {
      const a = await func("key1"); // a is of type "result1"
      const b = await func("key2"); // b is of type "result2"
    })()