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

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.