From 551ae4c87c13f2188b97930eaffd72e5575e9048 Mon Sep 17 00:00:00 2001 From: Daniel Roe Date: Tue, 16 Aug 2022 15:57:19 +0100 Subject: [PATCH] feat: export `Defu` type helper (#45) --- README.md | 11 +++++++++++ src/defu.ts | 6 ++++-- src/types.ts | 22 +++++++++++----------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index f6c2b2f..5010e8a 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,17 @@ console.log(defu({ array: ['b', 'c'] }, { array: ['a'] })) // => { array: ['a', 'b', 'c']} ``` +## Type + +We expose `Defu` as a type utility to return a merged type that follows the rules that defu follows. + +```js +import type { Defu } from 'defu' + +type Options = Defu<{ foo: 'bar' }, [{}, { bar: 'baz' }, { something: 42 }]> +// returns { foo: 'bar', bar: 'baz', 'something': 42 } +``` + ## License MIT. Made with 💖 diff --git a/src/defu.ts b/src/defu.ts index 004e2f7..73d3d9e 100644 --- a/src/defu.ts +++ b/src/defu.ts @@ -1,4 +1,4 @@ -import type { Merger, DefuFn, Defu } from './types' +import type { Merger, DefuFn, DefuInstance } from './types' function isObject (val: any) { return val !== null && typeof val === 'object' @@ -45,7 +45,7 @@ export function createDefu (merger?: Merger): DefuFn { } // Standard version -export const defu = createDefu() as Defu +export const defu = createDefu() as DefuInstance export default defu // Custom version with function merge support @@ -63,3 +63,5 @@ export const defuArrayFn = createDefu((obj, key, currentValue, _namespace) => { return true } }) + +export type { Defu } from './types' diff --git a/src/types.ts b/src/types.ts index 8666bb9..d370a82 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,5 @@ -type Input = Record -type IgnoredInput = boolean | number | null | any[] | Record | undefined +export type Input = Record +export type IgnoredInput = boolean | number | null | any[] | Record | undefined export type Merger = ( obj: T, @@ -10,7 +10,7 @@ export type Merger = ( type nullish = null | undefined | void -type MergeObjects< +export type MergeObjects< Destination extends Input, Defaults extends Input > = Destination extends Defaults ? Destination : Omit & Omit & @@ -25,28 +25,28 @@ type MergeObjects< : Merge // eslint-disable-line no-use-before-define } -type Coalesce> = +export type Defu> = D extends [infer F, ...infer Rest] ? F extends Input - ? Coalesce, Rest> + ? Defu, Rest> : F extends IgnoredInput - ? Coalesce + ? Defu : S - : S + : S export type DefuFn = >( source: Source, ...defaults: Defaults -) => Coalesce +) => Defu -export interface Defu { - >(source: Source | IgnoredInput, ...defaults: Defaults): Coalesce +export interface DefuInstance { + >(source: Source | IgnoredInput, ...defaults: Defaults): Defu fn: DefuFn arrayFn: DefuFn extend(merger?: Merger): DefuFn } -type MergeArrays = Destination extends Array +export type MergeArrays = Destination extends Array ? Source extends Array ? Array : Source | Array