1

I have the following typescript code:

const a = [{ foo: 1 }, { bar: '2' }]

I wish to use a to create an object of the form:

const b = {
  foo: 1,
  bar: '2'
}

and the typing of b should be equivalent to the type:

type EquivalentType = {
  foo: number
  bar: string
}

Is this possible without casting? How can this be done?

2 Answers 2

2

Sure there is. This solution does not need as const like @Vija02's (although it is perfectly fine if it does).

Map over all possible keys in the array, then get only the type of that key using Extract:

type CreateFrom<T extends ReadonlyArray<unknown>> = { [K in keyof T[number]]-?: Extract<T[number], { [_ in K]: any }>[K] };

Then you'd just use this type in a supposed function:

function createFrom<T extends ReadonlyArray<unknown>>(list: T): CreateFrom<T> {
    // ... for you to implement!
}

Note that you might need to cast the return type. I don't think TypeScript will be too happy with this one.

And to finish it off, this is a playground demonstrating the solution.

Sign up to request clarification or add additional context in comments.

Comments

0
// You might be able to simplify this
type TypeFromLiteral<T> = T extends string ? string : T extends number ? number : T extends boolean ? boolean : never;

// The "as const" part is important so that we can process the types
const a = [{ foo: 1 }, { bar: '2' }] as const;

// Get the final type
type ObjectUnion = typeof a[number];
type NewType = { [T in ObjectUnion as keyof T]: TypeFromLiteral<T[keyof T]> };

// By itself, this will get the correct value. However, we need to process the type separately and cast it to get what you want.
const b = Object.assign({}, ...a) as NewType;

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.