1

I have a function that takes an array of strings and returns an object that uses strings from that array as keys, like that:

const ob = arrayToObject(['a', 'b', 'c']); // {a: any, b: any, c: any)

now i want typescript to dynamically set type of the returned object to be based on the array in the function arguments. I know I can get a union type of array values by passing it as tuple, but don't know how to get from there. Is what i want even possible to do?

3
  • I'm not sure it's possible to generically do this. Not unless you have information about the content of the array at compile time, e.g., arr = ["a", "b", "c"] as const. However, if you don't have the contents at compile time (e.g., ["a", "b", prompt("enter a letter")]) then I don't think TS has any way of expressing an object which has keys based on the contents of the array. Commented Nov 12, 2020 at 11:43
  • I do know the content at the time of compile, of course I don't expect Typescript to predict future. Commented Nov 12, 2020 at 11:44
  • Then you can do it with an as const assertion. I'll write up an answer for this. Commented Nov 12, 2020 at 11:47

1 Answer 1

3

does this meet your expectations:

const ob = arrayToObject(['a', 'b', 'c']);


type Convert<T extends ReadonlyArray<string>> = {
    [P in T[number]]: string

}
type Result = Convert<['foo', 'bar']> // {foo: string, bar: string)

function arrayToObject<T extends ReadonlyArray<string>>(args: readonly string[]): Convert<T> {
    return args.reduce((acc, elem) => ({...acc, [elem]: 'hello' }), {} as Convert<T>)
}

UPDATE

// Please keep in mind, array is index based data structure. Index has `number` type

type Arr = readonly [1,2,3,4,5]

// So, You can try to get value by index
type Value1 = Arr[0] // 1
type Value2 = Arr[1] // 2 ... etc

type Value3 = Arr[0|1] // 1|2

// This is how distributive types work
type Value4 = Arr[number] // 5|1|2|3|4

// TS know that array has numbers as indexes, so he replace `number` with allowed // indexes. I'd willing to bet that TS compiler works much more complicated, but // this is how I understand it
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, it works. Do you know where can I read more about this thing you used: 'T[number]' I'd like to know more about how it works, can't find anything in the handbook
Sure, I have updated the answer. Also You can check handbook: typescriptlang.org/docs/handbook/… and handbook version 2 beta: typescriptlang.org/docs/handbook/2/basic-types.html

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.