Issue
Given the function
function invert(arr: string[]) {
let result = {};
arr.forEach((x, i) => {
result[x] = i;
})
return result; // insert type cast here
}
What I'm basically looking for, is a way for intellisense in VSCode to tell me exactly what props are available in the resulting object, so given const example = invert(['foo', 'bar', 'baz'])
The auto-completion should show me this:
My current approach involves casting the result as {[K in T[number]]: K}
where T
is an alias for typeof arr
, but this approach doesn't give me any auto-completion.
What do I write to get TypeScript to do show me this stuff?
The interface {[name]: number}
is merely a simplified example (for NDA reasons), the main question of how to map an array to property names is still the core of it all.
Solution
As the comments already noted, one way to do this is to make invert
generic. Currently arr
is only a string[]
. That's why your mapped type does not work.
function invert<T extends string>(arr: T[]): Record<T, number> {
let result = {} as Record<T, number>;
arr.forEach((x, i) => {
result[x] = i;
})
return result
}
This simply generic implementation produces a Record<T, number>
where T
consists of the keys inside the array.
const example = invert(['foo', 'bar', 'baz'])
// const example: Record<"foo" | "bar" | "baz", number>
This works but we could still improve this a bit. As currently, the keys are only typed as number
even though we know exactly which number they have.
function invert<T extends string[]>(arr: [...T]): {
[K in keyof T & `${bigint}` as T[K] & string]: K extends `${infer N extends number}` ? N : never
} {
let result = {} as any;
arr.forEach((x, i) => {
result[x] = i;
})
return result
}
In this implementation, we map over the elements of T
directly and filter out the number keys. Then we convert the index K
to a number.
This results in the following return type:
const example = invert(['foo', 'bar', 'baz'])
// const example: {
// foo: 0;
// bar: 1;
// baz: 2;
// }
Answered By - Tobias S.
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.