Skip to content

Commit 8a02ac9

Browse files
committed
Merge pull request #7016 from pimterry/lodash-merge
Use intersection types to correctly infer the result of _.merge in lodash
2 parents 010d44d + 4e4ffc7 commit 8a02ac9

File tree

2 files changed

+98
-50
lines changed

2 files changed

+98
-50
lines changed

lodash/lodash-tests.ts

Lines changed: 80 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8349,48 +8349,96 @@ module TestMapKeys {
83498349

83508350
// _.merge
83518351
module TestMerge {
8352-
let customizer: (value: any, srcValue: any, key?: string, object?: {}, source?: {}) => any;
8353-
let result: TResult;
8352+
type InitialValue = { a : number };
8353+
type MergingValue = { b : string };
8354+
8355+
var initialValue = { a : 1 };
8356+
var mergingValue = { b : "hi" };
8357+
8358+
type ExpectedResult = { a: number, b: string };
8359+
let result: ExpectedResult;
8360+
8361+
let customizer: (value: any, srcValue: any, key?: string, object?: InitialValue, source?: MergingValue) => any;
8362+
8363+
// Test for basic merging
8364+
8365+
result = _.merge(initialValue, mergingValue);
8366+
result = _.merge(initialValue, mergingValue, customizer);
8367+
result = _.merge(initialValue, mergingValue, customizer, any);
8368+
8369+
result = _.merge(initialValue, {}, mergingValue);
8370+
result = _.merge(initialValue, {}, mergingValue, customizer);
8371+
result = _.merge(initialValue, {}, mergingValue, customizer, any);
8372+
8373+
result = _.merge(initialValue, {}, {}, mergingValue);
8374+
result = _.merge(initialValue, {}, {}, mergingValue, customizer);
8375+
result = _.merge(initialValue, {}, {}, mergingValue, customizer, any);
8376+
8377+
result = _.merge(initialValue, {}, {}, {}, mergingValue);
8378+
result = _.merge(initialValue, {}, {}, {}, mergingValue, customizer);
8379+
result = _.merge(initialValue, {}, {}, {}, mergingValue, customizer, any);
8380+
8381+
// Once we get to the varargs version, you have to specify the result explicitly
8382+
result = _.merge<ExpectedResult>(initialValue, {}, {}, {}, {}, mergingValue);
8383+
result = _.merge<ExpectedResult>(initialValue, {}, {}, {}, {}, mergingValue, customizer);
8384+
result = _.merge<ExpectedResult>(initialValue, {}, {}, {}, {}, mergingValue, customizer, any);
8385+
8386+
// Test for multiple combinations of many types
8387+
8388+
type ComplicatedExpectedType = { a: number, b: string, c: {}, d: number[], e: boolean };
8389+
8390+
var complicatedResult: ComplicatedExpectedType = _.merge({ a: 1 },
8391+
{ b: "string" },
8392+
{ c: {} },
8393+
{ d: [1] },
8394+
{ e: true });
8395+
// Test for type overriding
8396+
8397+
type ExpectedTypeAfterOverriding = { a: boolean };
8398+
8399+
var overriddenResult: ExpectedTypeAfterOverriding = _.merge({ a: 1 },
8400+
{ a: "string" },
8401+
{ a: {} },
8402+
{ a: [1] },
8403+
{ a: true });
8404+
8405+
// Tests for basic chaining with merge
83548406

8355-
result = _.merge<{}, {}, TResult>({}, {});
8356-
result = _.merge<{}, {}, TResult>({}, {}, customizer);
8357-
result = _.merge<{}, {}, TResult>({}, {}, customizer, any);
8407+
result = _(initialValue).merge(mergingValue).value();
8408+
result = _(initialValue).merge(mergingValue, customizer).value();
8409+
result = _(initialValue).merge(mergingValue, customizer, any).value();
83588410

8359-
result = _.merge<{}, {}, {}, TResult>({}, {}, {});
8360-
result = _.merge<{}, {}, {}, TResult>({}, {}, {}, customizer);
8361-
result = _.merge<{}, {}, {}, TResult>({}, {}, {}, customizer, any);
8411+
result = _(initialValue).merge({}, mergingValue).value();
8412+
result = _(initialValue).merge({}, mergingValue, customizer).value();
8413+
result = _(initialValue).merge({}, mergingValue, customizer, any).value();
83628414

8363-
result = _.merge<{}, {}, {}, {}, TResult>({}, {}, {}, {});
8364-
result = _.merge<{}, {}, {}, {}, TResult>({}, {}, {}, {}, customizer);
8365-
result = _.merge<{}, {}, {}, {}, TResult>({}, {}, {}, {}, customizer, any);
8415+
result = _(initialValue).merge({}, {}, mergingValue).value();
8416+
result = _(initialValue).merge({}, {}, mergingValue, customizer).value();
8417+
result = _(initialValue).merge({}, {}, mergingValue, customizer, any).value();
83668418

8367-
result = _.merge<{}, {}, {}, {}, {}, TResult>({}, {}, {}, {}, {});
8368-
result = _.merge<{}, {}, {}, {}, {}, TResult>({}, {}, {}, {}, {}, customizer);
8369-
result = _.merge<{}, {}, {}, {}, {}, TResult>({}, {}, {}, {}, {}, customizer, any);
8419+
result = _(initialValue).merge({}, {}, {}, mergingValue).value();
8420+
result = _(initialValue).merge({}, {}, {}, mergingValue, customizer).value();
8421+
result = _(initialValue).merge({}, {}, {}, mergingValue, customizer, any).value();
83708422

8371-
result = _.merge<{}, TResult>({}, {}, {}, {}, {}, {});
8372-
result = _.merge<{}, TResult>({}, {}, {}, {}, {}, {}, customizer);
8373-
result = _.merge<{}, TResult>({}, {}, {}, {}, {}, {}, customizer, any);
8423+
// Once we get to the varargs version, you have to specify the result explicitly
8424+
result = _(initialValue).merge<ExpectedResult>({}, {}, {}, {}, mergingValue).value();
8425+
result = _(initialValue).merge<ExpectedResult>({}, {}, {}, {}, mergingValue, customizer).value();
8426+
result = _(initialValue).merge<ExpectedResult>({}, {}, {}, {}, mergingValue, customizer, any).value();
83748427

8375-
result = _({}).merge<{}, TResult>({}).value();
8376-
result = _({}).merge<{}, TResult>({}, customizer).value();
8377-
result = _({}).merge<{}, TResult>({}, customizer, any).value();
8428+
// Test complex multiple combinations with chaining
83788429

8379-
result = _({}).merge<{}, {}, TResult>({}, {}).value();
8380-
result = _({}).merge<{}, {}, TResult>({}, {}, customizer).value();
8381-
result = _({}).merge<{}, {}, TResult>({}, {}, customizer, any).value();
8430+
var complicatedResult: ComplicatedExpectedType = _({ a: 1 }).merge({ b: "string" },
8431+
{ c: {} },
8432+
{ d: [1] },
8433+
{ e: true }).value();
83828434

8383-
result = _({}).merge<{}, {}, {}, TResult>({}, {}, {}).value();
8384-
result = _({}).merge<{}, {}, {}, TResult>({}, {}, {}, customizer).value();
8385-
result = _({}).merge<{}, {}, {}, TResult>({}, {}, {}, customizer, any).value();
8435+
// Test for type overriding with chaining
83868436

8387-
result = _({}).merge<{}, {}, {}, {}, TResult>({}, {}, {}, {}).value();
8388-
result = _({}).merge<{}, {}, {}, {}, TResult>({}, {}, {}, {}, customizer).value();
8389-
result = _({}).merge<{}, {}, {}, {}, TResult>({}, {}, {}, {}, customizer, any).value();
8437+
var overriddenResult: ExpectedTypeAfterOverriding = _({ a: 1 }).merge({ a: "string" },
8438+
{ a: {} },
8439+
{ a: [1] },
8440+
{ a: true }).value();
83908441

8391-
result = _({}).merge<TResult>({}, {}, {}, {}, {}).value();
8392-
result = _({}).merge<TResult>({}, {}, {}, {}, {}, customizer).value();
8393-
result = _({}).merge<TResult>({}, {}, {}, {}, {}, customizer, any).value();
83948442
}
83958443

83968444
// _.methods

lodash/lodash.d.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12948,54 +12948,54 @@ declare module _ {
1294812948
* @param thisArg The this binding of customizer.
1294912949
* @return Returns object.
1295012950
*/
12951-
merge<TObject, TSource, TResult>(
12951+
merge<TObject, TSource>(
1295212952
object: TObject,
1295312953
source: TSource,
1295412954
customizer?: MergeCustomizer,
1295512955
thisArg?: any
12956-
): TResult;
12956+
): TObject & TSource;
1295712957

1295812958
/**
1295912959
* @see _.merge
1296012960
*/
12961-
merge<TObject, TSource1, TSource2, TResult>(
12961+
merge<TObject, TSource1, TSource2>(
1296212962
object: TObject,
1296312963
source1: TSource1,
1296412964
source2: TSource2,
1296512965
customizer?: MergeCustomizer,
1296612966
thisArg?: any
12967-
): TResult;
12967+
): TObject & TSource1 & TSource2;
1296812968

1296912969
/**
1297012970
* @see _.merge
1297112971
*/
12972-
merge<TObject, TSource1, TSource2, TSource3, TResult>(
12972+
merge<TObject, TSource1, TSource2, TSource3>(
1297312973
object: TObject,
1297412974
source1: TSource1,
1297512975
source2: TSource2,
1297612976
source3: TSource3,
1297712977
customizer?: MergeCustomizer,
1297812978
thisArg?: any
12979-
): TResult;
12979+
): TObject & TSource1 & TSource2 & TSource3;
1298012980

1298112981
/**
1298212982
* @see _.merge
1298312983
*/
12984-
merge<TObject, TSource1, TSource2, TSource3, TSource4, TResult>(
12984+
merge<TObject, TSource1, TSource2, TSource3, TSource4>(
1298512985
object: TObject,
1298612986
source1: TSource1,
1298712987
source2: TSource2,
1298812988
source3: TSource3,
1298912989
source4: TSource4,
1299012990
customizer?: MergeCustomizer,
1299112991
thisArg?: any
12992-
): TResult;
12992+
): TObject & TSource1 & TSource2 & TSource3 & TSource4;
1299312993

1299412994
/**
1299512995
* @see _.merge
1299612996
*/
12997-
merge<TObject, TResult>(
12998-
object: TObject,
12997+
merge<TResult>(
12998+
object: any,
1299912999
...otherArgs: any[]
1300013000
): TResult;
1300113001
}
@@ -13004,44 +13004,44 @@ declare module _ {
1300413004
/**
1300513005
* @see _.merge
1300613006
*/
13007-
merge<TSource, TResult>(
13007+
merge<TSource>(
1300813008
source: TSource,
1300913009
customizer?: MergeCustomizer,
1301013010
thisArg?: any
13011-
): LoDashImplicitObjectWrapper<TResult>;
13011+
): LoDashImplicitObjectWrapper<T & TSource>;
1301213012

1301313013
/**
1301413014
* @see _.merge
1301513015
*/
13016-
merge<TSource1, TSource2, TResult>(
13016+
merge<TSource1, TSource2>(
1301713017
source1: TSource1,
1301813018
source2: TSource2,
1301913019
customizer?: MergeCustomizer,
1302013020
thisArg?: any
13021-
): LoDashImplicitObjectWrapper<TResult>;
13021+
): LoDashImplicitObjectWrapper<T & TSource1 & TSource2>;
1302213022

1302313023
/**
1302413024
* @see _.merge
1302513025
*/
13026-
merge<TSource1, TSource2, TSource3, TResult>(
13026+
merge<TSource1, TSource2, TSource3>(
1302713027
source1: TSource1,
1302813028
source2: TSource2,
1302913029
source3: TSource3,
1303013030
customizer?: MergeCustomizer,
1303113031
thisArg?: any
13032-
): LoDashImplicitObjectWrapper<TResult>;
13032+
): LoDashImplicitObjectWrapper<T & TSource1 & TSource2 & TSource3>;
1303313033

1303413034
/**
1303513035
* @see _.merge
1303613036
*/
13037-
merge<TSource1, TSource2, TSource3, TSource4, TResult>(
13037+
merge<TSource1, TSource2, TSource3, TSource4>(
1303813038
source1: TSource1,
1303913039
source2: TSource2,
1304013040
source3: TSource3,
1304113041
source4: TSource4,
1304213042
customizer?: MergeCustomizer,
1304313043
thisArg?: any
13044-
): LoDashImplicitObjectWrapper<TResult>;
13044+
): LoDashImplicitObjectWrapper<T & TSource1 & TSource2 & TSource3 & TSource4>;
1304513045

1304613046
/**
1304713047
* @see _.merge

0 commit comments

Comments
 (0)