The problem
I have the following two types.
interface SchemaItem {
name: string,
value: string
}
type Result<T extends SchemaItem[]> = {
[K in T[number] as K['name']]: K['value']
}
And I have a function that is supposed to create a value of the Result type from the SchemaItem[] argument.
function createResult<T extends SchemaItem[]>(schemaItems: T): Result<T> {
// implementation doesn't matter for this question
return {} as Result<T>
}
The Result type works as expected when I test it like this.
// ResultType = { foo: "Foo", bar: "Bar" }
type ResultType = Result<[
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
]>
But when I test the function with the same data the returned value is not inferred properly.
// result is of type Result<{ name: string; value: string }[]>
const result = createResult([
{ name: 'foo', value: "Foo" },
{ name: 'bar', value: "Bar" },
])
Is it possible to make TypeScript infer the type of the result as { foo: "Foo", bar: "Bar" } or it's a design limitation?
What I have tried
I thought maybe the problem is that name property of SchemaItem is declared as string and here is what I come up with.
interface SchemaItem<T extends string = string> {
name: T,
value: string
}
type ArrayToUnion<T> = T extends Array<infer R> ? R : never
type Result<T extends SchemaItem[]> = ArrayToUnion<T> extends SchemaItem<infer R> ? { [key in R]: string } : never
But it didn't help and the result value was of type { [x: string]: string } which is no better.