Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into clone-proto-objec…
Browse files Browse the repository at this point in the history
…t-merge-object-fix
  • Loading branch information
segevfiner committed Dec 9, 2024
2 parents 8687915 + 4af2e21 commit 6d8383a
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 41 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# @fastify/deepmerge

![CI](https://github.com/fastify/deepmerge/workflows/CI/badge.svg)
[![CI](https://github.com/fastify/deepmerge/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/fastify/deepmerge/actions/workflows/ci.yml)
[![NPM version](https://img.shields.io/npm/v/@fastify/deepmerge.svg?style=flat)](https://www.npmjs.com/package/@fastify/deepmerge)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg?style=flat)](https://standardjs.com/)
[![neostandard javascript style](https://img.shields.io/badge/code_style-neostandard-brightgreen?style=flat)](https://github.com/neostandard/neostandard)

Merges the enumerable properties of two or more objects deeply. Fastest implementation of deepmerge, see section 'Benchmarks'.

Expand Down
6 changes: 6 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use strict'

module.exports = require('neostandard')({
ignores: require('neostandard').resolveIgnoresFromGitignore(),
ts: true
})
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
"type": "commonjs",
"types": "types/index.d.ts",
"scripts": {
"lint": "standard",
"lint:fix": "standard --fix",
"lint": "eslint",
"lint:fix": "eslint --fix",
"test": "npm run test:unit && npm run test:typescript",
"test:unit": "tap",
"test:typescript": "tsd"
Expand All @@ -23,7 +23,7 @@
},
"homepage": "https://github.com/fastify/deepmerge#readme",
"devDependencies": {
"standard": "^17.1.0",
"neostandard": "^0.11.9",
"tap": "^21.0.0",
"tape": "^5.7.5",
"tsd": "^0.31.1"
Expand Down
37 changes: 20 additions & 17 deletions types/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
type DeepMergeFn = <T1, T2>(target: T1, source: T2) => DeepMerge<T1, T2>;
type DeepMergeAllFn = <T extends Array<any>>(...targets: T) => DeepMergeAll<{}, T>;
type DeepMergeFn = <T1, T2>(target: T1, source: T2) => DeepMerge<T1, T2>
type DeepMergeAllFn = <T extends Array<any>>(...targets: T) => DeepMergeAll<{}, T>

type Primitive =
| null
Expand All @@ -8,14 +8,14 @@ type Primitive =
| number
| boolean
| symbol
| bigint;
| bigint

type BuiltIns = Primitive | Date | RegExp;
type BuiltIns = Primitive | Date | RegExp

type MergeArrays<T, U> = T extends readonly any[]
? U extends readonly any[]
? [...T, ...U]
: never
? [...T, ...U]
: never
: never

type DifferenceKeys<
Expand All @@ -37,19 +37,22 @@ type DeepMergeHelper<

type DeepMerge<T, U> =
U extends BuiltIns
? U
: [T, U] extends [readonly any[], readonly any[]]
? MergeArrays<T, U>
: [T, U] extends [{ [key: string]: unknown }, { [key: string]: unknown }]
? DeepMergeHelper<T, U>
: U

type First<T> = T extends [infer _I, ...infer _Rest] ? _I : never;
? U
: [T, U] extends [readonly any[], readonly any[]]
? MergeArrays<T, U>
: [T, U] extends [{ [key: string]: unknown }, { [key: string]: unknown }]
? DeepMergeHelper<T, U>
: U

// eslint-disable-next-line @typescript-eslint/no-unused-vars
type First<T> = T extends [infer _I, ...infer _Rest] ? _I : never

// eslint-disable-next-line @typescript-eslint/no-unused-vars
type Rest<T> = T extends [infer _I, ...infer _Rest] ? _Rest : never

type DeepMergeAll<R, T> = First<T> extends never
? R
: DeepMergeAll<DeepMerge<R, First<T>>, Rest<T>>;
: DeepMergeAll<DeepMerge<R, First<T>>, Rest<T>>

type MergeArrayFnOptions = {
clone: (value: any) => any;
Expand All @@ -74,7 +77,7 @@ declare namespace deepmerge {
export { deepmerge as default }
}

declare function deepmerge(options: Options & { all: true }): DeepMergeAllFn;
declare function deepmerge(options?: Options): DeepMergeFn;
declare function deepmerge (options: Options & { all: true }): DeepMergeAllFn
declare function deepmerge (options?: Options): DeepMergeFn

export = deepmerge
38 changes: 19 additions & 19 deletions types/index.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expectAssignable, expectError, expectType } from "tsd";
import { deepmerge } from ".";
import { expectAssignable, expectError, expectType } from 'tsd'
import { deepmerge } from '.'

expectType<string>(deepmerge()({ a: 'a' }, { b: 'b' }).a)
expectType<string>(deepmerge()({ a: 'a' }, { b: 'b' }).b)
Expand Down Expand Up @@ -31,26 +31,26 @@ expectType<{ a: number }>(deepmerge()({ a: { a: 'string' } }, { a: { a: 1 } }).a
expectType<{ a: number, b: string }>(deepmerge()({ a: { a: 'string' } }, { a: { a: 1, b: 'string' } }).a)
expectType<{ a: number, b: string }>(deepmerge()({ a: { a: { a: 'string' } } }, { a: { a: 1, b: 'string' } }).a)
expectType<{ a: { a: string, b: string } }>(deepmerge()({ a: { a: { a: 'string' } } }, { a: { a: { b: 'string' } } }).a)
expectType<string>(deepmerge()({ a: [1,2,3,4] }, { a: 'string' }).a)
expectType<number[]>(deepmerge()({ a: [1,2,3,4] }, { a: [1,2,3,4] }).a)
expectType<(number|string)[]>(deepmerge()({ a: [1,2,3,4] }, { a: ['a'] }).a)
expectType<(number|string)[]>(deepmerge()({ a: [1,2,3,4] as readonly number[] }, { a: ['a'] }).a)
expectType<[1,2,3,4,'a']>(deepmerge()({ a: [1,2,3,4] as const }, { a: ['a'] as const }).a)
expectType<string>(deepmerge()({ a: [1, 2, 3, 4] }, { a: 'string' }).a)
expectType<number[]>(deepmerge()({ a: [1, 2, 3, 4] }, { a: [1, 2, 3, 4] }).a)
expectType<(number | string)[]>(deepmerge()({ a: [1, 2, 3, 4] }, { a: ['a'] }).a)
expectType<(number | string)[]>(deepmerge()({ a: [1, 2, 3, 4] as readonly number[] }, { a: ['a'] }).a)
expectType<[1, 2, 3, 4, 'a']>(deepmerge()({ a: [1, 2, 3, 4] as const }, { a: ['a'] as const }).a)
expectType<Array<number>>(deepmerge()({ a: [1] }, { a: [2] }).a)
expectType<{b: number[]}>(deepmerge()({ a: {b: {}} }, { a: {b: [2]} }).a)
expectType<{b: Date}>(deepmerge()({ a: {b: {}} }, { a: {b: new Date()} }).a)
expectType<{b: RegExp}>(deepmerge()({ a: {b: {}} }, { a: {b: /abc/g } }).a)
expectType<Date>(deepmerge()({ a: {b: {}} }, new Date()))
expectType<Map<any, any>>(deepmerge()({ a: {b: {}} }, new Map()))
expectType<{ b: number[] }>(deepmerge()({ a: { b: {} } }, { a: { b: [2] } }).a)
expectType<{ b: Date }>(deepmerge()({ a: { b: {} } }, { a: { b: new Date() } }).a)
expectType<{ b: RegExp }>(deepmerge()({ a: { b: {} } }, { a: { b: /abc/g } }).a)
expectType<Date>(deepmerge()({ a: { b: {} } }, new Date()))
expectType<Map<any, any>>(deepmerge()({ a: { b: {} } }, new Map()))

expectAssignable<Function>(deepmerge({ all: true }))
expectAssignable<Function>(deepmerge({ all: true, symbols: true }))
expectType<string>(deepmerge({all: true, symbols: true})({a: 'a'}).a)
expectType<string>(deepmerge({all: true, symbols: true})({a: 'a'}, {b: 'a'}).a)
expectType<string>(deepmerge({all: true, symbols: true})({a: 'a'}, {b: 'a'}).b)
expectType<number>(deepmerge({all: true, symbols: true})({a: 'a'}, {a: 2}).a)
expectType<number>(deepmerge({all: true, symbols: true})({a: 'a'}, 2))
expectType<string>(deepmerge({all: true, symbols: true})({a: 'a'}, 'string'))
expectType<string>(deepmerge({ all: true, symbols: true })({ a: 'a' }).a)
expectType<string>(deepmerge({ all: true, symbols: true })({ a: 'a' }, { b: 'a' }).a)
expectType<string>(deepmerge({ all: true, symbols: true })({ a: 'a' }, { b: 'a' }).b)
expectType<number>(deepmerge({ all: true, symbols: true })({ a: 'a' }, { a: 2 }).a)
expectType<number>(deepmerge({ all: true, symbols: true })({ a: 'a' }, 2))
expectType<string>(deepmerge({ all: true, symbols: true })({ a: 'a' }, 'string'))

expectError(deepmerge({ mergeArray: function () { } }))
expectError(deepmerge({ mergeArray: function () { return () => 'test' } }))
Expand All @@ -69,4 +69,4 @@ deepmerge({
return source
}
}
})
})

0 comments on commit 6d8383a

Please sign in to comment.