Skip to content

Commit

Permalink
docs: document each type alias
Browse files Browse the repository at this point in the history
  • Loading branch information
Rebecca Stevens committed Nov 10, 2020
1 parent 24b9aa9 commit ac37a6b
Showing 1 changed file with 101 additions and 7 deletions.
108 changes: 101 additions & 7 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Minimum TypeScript Version: 4.2
// TODO: Can be reduce to version 4.1 upon it's release.

/**
* Deep merge 1 or more types given in an array.
*/
type DeepMergeAll<
Ts extends readonly [any, ...any[]],
Options extends deepmerge.Options
Expand All @@ -12,6 +15,9 @@ type DeepMergeAll<
: T1
: never;

/**
* Deep merge 2 types.
*/
type DeepMerge<T1, T2, Options extends deepmerge.Options> = IsSame<
T1,
T2
Expand All @@ -23,6 +29,9 @@ type DeepMerge<T1, T2, Options extends deepmerge.Options> = IsSame<
: MergeLeafs<T1, T2>
: MergeLeafs<T1, T2>;

/**
* Deep merge 2 objects (they may be arrays).
*/
type DeepMergeNonPrimitive<
T1,
T2,
Expand All @@ -31,6 +40,9 @@ type DeepMergeNonPrimitive<
? DeepMergeArrays<T1, T2, Options>
: DeepMergeObjects<T1, T2, Options>;

/**
* Deep merge 2 non-array types.
*/
type DeepMergeObjects<
T1,
T2,
Expand All @@ -39,12 +51,15 @@ type DeepMergeObjects<
? DeepMergeObjectProps<T1, T2, Options>
: MergeLeafs<T1, T2>;

// @see https://github.com/microsoft/TypeScript/issues/41448
/**
* Deep merge 2 non-array objects.
*/
type DeepMergeObjectProps<
T1,
T2,
Options extends deepmerge.Options
> = FlatternAlias<
// @see https://github.com/microsoft/TypeScript/issues/41448
{
-readonly [K in keyof T1]: DeepMergeProps<
ValueOfKey<T1, K>,
Expand All @@ -61,6 +76,10 @@ type DeepMergeObjectProps<
}
>;

/**
* Deep merge 2 types that are known to be properties of an object being deeply
* merged.
*/
type DeepMergeProps<T1, T2, Options extends deepmerge.Options> = GetOption<
Options,
"isMergeableObject"
Expand All @@ -70,6 +89,10 @@ type DeepMergeProps<T1, T2, Options extends deepmerge.Options> = GetOption<
: DeepMergePropsCustom<T1, T2, Options>
: MergeMaybeLeafs<T1, T2, Options>;

/**
* Deep merge 2 types that are known to be properties of an object being deeply
* merged and where a "customMerge" function has been provided.
*/
type DeepMergePropsCustom<
T1,
T2,
Expand All @@ -94,6 +117,9 @@ type DeepMergePropsCustom<
NonNullable<ReturnType<NonNullable<GetOption<Options, "customMerge">>>>
>;

/**
* Deep merge 2 arrays.
*/
type DeepMergeArrays<
T1,
T2,
Expand All @@ -106,6 +132,9 @@ type DeepMergeArrays<
: never
: never;

/**
* Get the leaf type of 2 types that can't be merged.
*/
type MergeLeafs<T1, T2> = Is<T2, never> extends true
? T1
: Is<T1, never> extends true
Expand All @@ -114,6 +143,9 @@ type MergeLeafs<T1, T2> = Is<T2, never> extends true
? T1
: T2;

/**
* Get the leaf type of 2 types that might not be able to be merged.
*/
type MergeMaybeLeafs<T1, T2, Options extends deepmerge.Options> = Is<
T2,
never
Expand All @@ -131,52 +163,98 @@ type MergeMaybeLeafs<T1, T2, Options extends deepmerge.Options> = Is<
? DeepMerge<T1, T2, Options>
: unknown;

/**
* Flatten a complex type such as a union or intersection of objects into a
* single object.
*/
type FlatternAlias<T> = {} & { [P in keyof T]: T[P] };

/**
* Get the value of the given key in the given object.
*/
type ValueOfKey<T, K> = K extends keyof T ? T[K] : never;

/**
* Safely test whether or not the first given types extends the second.
*
* Needed in particular for testing if a type is "never".
*/
type Is<T1, T2> = [T1] extends [T2] ? true : false;

/**
* Returns whether or not the give two types are the same.
*/
type IsSame<T1, T2> = Is<T1, T2> extends true ? Is<T2, T1> : false;

/**
* Returns whether or not the given type an object (arrays are objects).
*/
type IsObjectOrArray<T> = Is<T, never> extends true ? false : Is<T, object>;

type IsObject<T> = Is<T, ReadonlyArray<any>> extends true
/**
* Returns whether or not the given type a non-array object.
*/
type IsObject<T> = IsArray<T> extends true
? false
: IsObjectOrArray<T>;

/**
* Returns whether or not the given type an array.
*/
type IsArray<T> = Is<T, ReadonlyArray<any>>;

/**
* Returns whether or not 2 types are both non-array objects that can be merged.
*/
type ShouldMergeObjects<T1, T2> = IsObject<T1> extends true
? IsObject<T2>
: false;

type ShouldMergeArrays<T1, T2> = Is<T1, ReadonlyArray<any>> extends true
? Is<T2, ReadonlyArray<any>>
/**
* Returns whether or not 2 types are both arrays that can be merged.
*/
type ShouldMergeArrays<T1, T2> = IsArray<T1> extends true
? IsArray<T2>
: false;

/**
* A function that merges any 2 arrays.
*/
type ArrayMerge = (
target: Array<any>,
source: Array<any>,
options: Required<deepmerge.Options>
) => any;

/**
* A function that merges any 2 non-arrays objects.
*/
type ObjectMerge = (
key: string,
options: Required<deepmerge.Options>
) =>
| ((target: any, source: any, options?: deepmerge.Options) => any)
| undefined;

/**
* A function that determins if any non-array object is mergable.
*/
type IsMergeable = (value: any) => boolean;

/**
* The default config options.
*/
type DefaultOptions = {
arrayMerge: undefined;
clone: true;
customMerge: undefined;
isMergeableObject: undefined;
};

/**
* Get the type of a given config option, defaulting to the default type if it
* wasn't given.
*/
type GetOption<
O extends deepmerge.Options,
K extends keyof deepmerge.Options
Expand All @@ -185,9 +263,9 @@ type GetOption<
/**
* Deeply merge two objects.
*
* @param target the first obj
* @param source the second obj
* @param options deepmerge option
* @param target The first object.
* @param source The second object.
* @param options Deep merge options.
*/
declare function deepmerge<
T1 extends object,
Expand All @@ -196,17 +274,33 @@ declare function deepmerge<
>(target: T1, source: T2, options?: Options): DeepMerge<T1, T2, Options>;

declare namespace deepmerge {
/**
* Deep merge config options.
*/
export type Options = {
arrayMerge?: ArrayMerge;
clone?: boolean;
customMerge?: ObjectMerge;
isMergeableObject?: IsMergeable;
};

/**
* Deeply merge two or more objects.
*
* @param objects An tuple of the objects to merge.
* @param options Deep merge options.
*/
export function all<
Ts extends readonly [object, ...object[]],
O extends Options = DefaultOptions
>(objects: [...Ts], options?: O): DeepMergeAll<Ts, O>;

/**
* Deeply merge two or more objects.
*
* @param objects An array of the objects to merge.
* @param options Deep merge options.
*/
export function all(
objects: ReadonlyArray<object>,
options?: Options
Expand Down

0 comments on commit ac37a6b

Please sign in to comment.