As in the title.
"Resolving" as in converting { a: string } & { b: string }
to { a: string, b: string }
.
This is @jcalz's one, from his answer to "How can I see the full expanded contract of a Typescript type?":
type Expand<T> = T extends infer O ? { [K in keyof O]: O[K] } : never;
And this is his summary:
Those use conditional type inference to "copy" a type T into a new type variable O and then an identity-like mapped type which iterates through the copied type's properties.
The conditional type inference is conceptually a no-op, but it's used to distribute union types and to force the compiler to evaluate the "true" branch of the conditional (if you redefine
Expand<T>
without it, sometimes the compiler will just output the mapped type{[K in keyof RelevantType]: RelevantType[K]}
, which is not what you want to see).
And this is the one Gabriel Vergnaud uses in his Type-Level Typescript workshop:
/**
* Compute is a helper converting intersections of objects into
* flat, plain object types.
*/
type Compute<T> = { [K in keyof T]: T[K] } & unknown
As to the methods of the types, @jcalz's one uses the conditional type inference to force the evaluation of the type, while Gabriel's one uses an intersection with unknown
.
EDIT
To clarify:
What are the technical differences in the output of these two methods?
And are there any cases where their output will differ?
Bonus points for info on things like performance.