Skip to content

Commit

Permalink
SimplifyDeep: Support array (#888)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emiyaaaaa authored Jun 7, 2024
1 parent 587380c commit a6ab051
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 17 deletions.
13 changes: 8 additions & 5 deletions source/merge-deep.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import type {
import type {UnknownRecord} from './unknown-record';
import type {EnforceOptional} from './enforce-optional';
import type {SimplifyDeep} from './simplify-deep';
import type {UnknownArray} from './unknown-array';

type SimplifyDeepExcludeArray<T> = SimplifyDeep<T, UnknownArray>;

/**
Try to merge two record properties or return the source property value, preserving `undefined` properties values in both cases.
Expand Down Expand Up @@ -247,7 +250,7 @@ type MergeDeepArrayRecursive<
: DoMergeArrayOrTuple<Destination, Source, Options>
: Destination[number] extends UnknownRecord
? Source[number] extends UnknownRecord
? Array<SimplifyDeep<MergeDeepRecord<Destination[number], Source[number], Options>>>
? Array<SimplifyDeepExcludeArray<MergeDeepRecord<Destination[number], Source[number], Options>>>
: DoMergeArrayOrTuple<Destination, Source, Options>
: DoMergeArrayOrTuple<Destination, Source, Options>;

Expand Down Expand Up @@ -290,7 +293,7 @@ type MergeDeepOrReturn<
Destination,
Source,
Options extends MergeDeepInternalOptions,
> = SimplifyDeep<[undefined] extends [Destination | Source]
> = SimplifyDeepExcludeArray<[undefined] extends [Destination | Source]
? DefaultType
: Destination extends UnknownRecord
? Source extends UnknownRecord
Expand Down Expand Up @@ -353,7 +356,7 @@ type DefaultMergeDeepOptions<Options extends MergeDeepOptions> = Merge<{
/**
This utility selects the correct entry point with the corresponding default options. This avoids re-merging the options at each iteration.
*/
type MergeDeepWithDefaultOptions<Destination, Source, Options extends MergeDeepOptions> = SimplifyDeep<
type MergeDeepWithDefaultOptions<Destination, Source, Options extends MergeDeepOptions> = SimplifyDeepExcludeArray<
[undefined] extends [Destination | Source]
? never
: Destination extends UnknownRecord
Expand Down Expand Up @@ -477,7 +480,7 @@ function mergeDeep<Destination, Source, Options extends MergeDeepOptions = {}>(
@category Utilities
*/
export type MergeDeep<Destination, Source, Options extends MergeDeepOptions = {}> = MergeDeepWithDefaultOptions<
SimplifyDeep<Destination>,
SimplifyDeep<Source>,
SimplifyDeepExcludeArray<Destination>,
SimplifyDeepExcludeArray<Source>,
Options
>;
4 changes: 2 additions & 2 deletions source/omit-deep.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ export type OmitDeep<T, PathUnion extends LiteralUnion<Paths<T>, string>> =
SimplifyDeep<
SharedUnionFieldsDeep<
{[P in PathUnion]: OmitDeepWithOnePath<T, P>}[PathUnion]
>
>;
>,
UnknownArray>;

/**
Omit one path from the given object/array.
Expand Down
84 changes: 74 additions & 10 deletions source/simplify-deep.d.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import type {ConditionalSimplifyDeep} from './conditional-simplify';
import type {NonRecursiveType} from './internal';

/**
Deeply simplifies an object type.
You can exclude certain types from being simplified by providing them in the second generic `ExcludeType`.
Useful to flatten the type output to improve type hints shown in editors.
@example
```
import type {SimplifyDeep} from 'type-fest';
type PositionX = {
left: number;
right: number;
};
type PositionY = {
top: number;
bottom: number;
};
type Properties1 = {
height: number;
position: {
top: number;
bottom: number;
};
position: PositionY;
};
type Properties2 = {
width: number;
position: {
left: number;
right: number;
};
position: PositionX;
};
type Properties = Properties1 & Properties2;
Expand All @@ -31,7 +38,58 @@ type Properties = Properties1 & Properties2;
// type Properties = Properties1 & Properties2;
type SimplifyDeepProperties = SimplifyDeep<Properties1 & Properties2>;
// But if wrapped in SimplifyDeep, hovering over `Props` will show a flattened object with all the properties:
// But if wrapped in SimplifyDeep, hovering over `SimplifyDeepProperties` will show a flattened object with all the properties:
//
// SimplifyDeepProperties = {
// height: number;
// width: number;
// position: {
// top: number;
// bottom: number;
// left: number;
// right: number;
// };
// };
```
@example
```
import type {SimplifyDeep} from 'type-fest';
// A complex type that you don't want or need to simplify
type ComplexType = {
a: string;
b: 'b';
c: number;
...
};
type PositionX = {
left: number;
right: number;
};
type PositionY = {
top: number;
bottom: number;
};
// You want to simplify all other types
type Properties1 = {
height: number;
position: PositionY;
foo: ComplexType;
};
type Properties2 = {
width: number;
position: PositionX;
foo: ComplexType;
};
type SimplifyDeepProperties = SimplifyDeep<Properties1 & Properties2, ComplexType>;
// If wrapped in `SimplifyDeep` and set `ComplexType` to exclude, hovering over `SimplifyDeepProperties` will
// show a flattened object with all the properties except `ComplexType`:
//
// SimplifyDeepProperties = {
// height: number;
Expand All @@ -42,10 +100,16 @@ type SimplifyDeepProperties = SimplifyDeep<Properties1 & Properties2>;
// left: number;
// right: number;
// };
// foo: ComplexType;
// };
```
@see Simplify
@category Object
*/
export type SimplifyDeep<Type> = ConditionalSimplifyDeep<Type, Function | Iterable<unknown>, object>;
export type SimplifyDeep<Type, ExcludeType = never> =
ConditionalSimplifyDeep<
Type,
ExcludeType | NonRecursiveType | Set<unknown> | Map<unknown, unknown>,
object
>;
1 change: 1 addition & 0 deletions test-d/merge-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ expectType<never>(mergeDeep(null, {}));
expectType<never>(mergeDeep([], 'life'));
expectType<never>(mergeDeep([], new Set()));
expectType<never>(mergeDeep(new Set(), new Set()));
expectType<never>(mergeDeep(new Map(), new Map()));
expectType<never>(mergeDeep(undefined, undefined));
expectType<never>(mergeDeep({}, undefined));
expectType<never>(mergeDeep(undefined, {}));
Expand Down
13 changes: 13 additions & 0 deletions test-d/simplify-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,17 @@ declare const flattenProperties: {
right: number;
};
};

expectType<SimplifyDeep<Properties1 & Properties2>>(flattenProperties);

// Array
type ArrayType = Array<{
a: string;
}>;

declare const flattenProperties2: {
arrayType: Array<{
a: string;
}>;
};
expectType<SimplifyDeep<{arrayType: ArrayType}>>(flattenProperties2);

0 comments on commit a6ab051

Please sign in to comment.