UNPKG

1.78 kBTypeScriptView Raw
1import type {RequiredKeysOf} from './required-keys-of';
2import type {Simplify} from './simplify';
3
4type SpreadObject<FirstType extends object, SecondType extends object> = {
5 [Key in keyof FirstType]: Key extends keyof SecondType
6 ? FirstType[Key] | Required<SecondType>[Key]
7 : FirstType[Key];
8} & Pick<
9SecondType,
10RequiredKeysOf<SecondType> | Exclude<keyof SecondType, keyof FirstType>
11>;
12
13type TupleOrArray = readonly [...unknown[]];
14
15type SpreadTupleOrArray<
16 FirstType extends TupleOrArray,
17 SecondType extends TupleOrArray,
18> = Array<FirstType[number] | SecondType[number]>;
19
20type Spreadable = object | TupleOrArray;
21
22/**
23Mimic the type inferred by TypeScript when merging two objects or two arrays/tuples using the spread syntax.
24
25@example
26```
27import type {Spread} from 'type-fest';
28
29type Foo = {
30 a: number;
31 b?: string;
32};
33
34type Bar = {
35 b?: number;
36 c: boolean;
37};
38
39const foo = {a: 1, b: '2'};
40const bar = {c: false};
41const fooBar = {...foo, ...bar};
42
43type FooBar = Spread<Foo, Bar>;
44// type FooBar = {
45// a: number;
46// b?: string | number | undefined;
47// c: boolean;
48// }
49
50const baz = (argument: FooBar) => {
51 // Do something
52}
53
54baz(fooBar);
55```
56
57@example
58```
59import type {Spread} from 'type-fest';
60
61const foo = [1, 2, 3];
62const bar = ['4', '5', '6'];
63
64const fooBar = [...foo, ...bar];
65type FooBar = Spread<typeof foo, typeof bar>;
66// FooBar = (string | number)[]
67
68const baz = (argument: FooBar) => {
69 // Do something
70};
71
72baz(fooBar);
73```
74
75@category Object
76*/
77export type Spread<
78 FirstType extends Spreadable,
79 SecondType extends Spreadable,
80> = FirstType extends TupleOrArray
81 ? SecondType extends TupleOrArray
82 ? SpreadTupleOrArray<FirstType, SecondType>
83 : Simplify<SpreadObject<FirstType, SecondType>>
84 : Simplify<SpreadObject<FirstType, SecondType>>;