UNPKG

type-fest

Version:

A collection of essential TypeScript types

89 lines (75 loc) 2.3 kB
import type {NonRecursiveType, ReadonlyKeysOfUnion, ValueOfUnion} from './internal'; import type {KeysOfUnion} from './keys-of-union'; import type {SharedUnionFields} from './shared-union-fields'; import type {Simplify} from './simplify'; import type {UnknownArray} from './unknown-array'; /** Create a type with all fields from a union of object types. Use-cases: - You want a safe object type where each key exists in the union object. @example ``` import type {AllUnionFields} from 'type-fest'; type Cat = { name: string; type: 'cat'; catType: string; }; type Dog = { name: string; type: 'dog'; dogType: string; }; function displayPetInfo(petInfo: Cat | Dog) { // typeof petInfo => // { // name: string; // type: 'cat'; // catType: string; // } | { // name: string; // type: 'dog'; // dogType: string; // } console.log('name: ', petInfo.name); console.log('type: ', petInfo.type); // TypeScript complains about `catType` and `dogType` not existing on type `Cat | Dog`. console.log('animal type: ', petInfo.catType ?? petInfo.dogType); } function displayPetInfo(petInfo: AllUnionFields<Cat | Dog>) { // typeof petInfo => // { // name: string; // type: 'cat' | 'dog'; // catType?: string; // dogType?: string; // } console.log('name: ', petInfo.name); console.log('type: ', petInfo.type); // No TypeScript error. console.log('animal type: ', petInfo.catType ?? petInfo.dogType); } ``` @see SharedUnionFields @category Object @category Union */ export type AllUnionFields<Union> = Extract<Union, NonRecursiveType | ReadonlyMap<unknown, unknown> | ReadonlySet<unknown> | UnknownArray> extends infer SkippedMembers ? Exclude<Union, SkippedMembers> extends infer RelevantMembers ? | SkippedMembers | Simplify< // Include fields that are common in all union members SharedUnionFields<RelevantMembers> & // Include readonly fields present in any union member { readonly [P in ReadonlyKeysOfUnion<RelevantMembers>]?: ValueOfUnion<RelevantMembers, P & KeysOfUnion<RelevantMembers>> } & // Include remaining fields that are neither common nor readonly { [P in Exclude<KeysOfUnion<RelevantMembers>, ReadonlyKeysOfUnion<RelevantMembers> | keyof RelevantMembers>]?: ValueOfUnion<RelevantMembers, P> } > : never : never;