Skip to content

Commit

Permalink
feat: export Defu type helper (#45)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe committed Aug 16, 2022
1 parent e349486 commit 551ae4c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 13 deletions.
11 changes: 11 additions & 0 deletions README.md
Expand Up @@ -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 💖
Expand Down
6 changes: 4 additions & 2 deletions 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'
Expand Down Expand Up @@ -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
Expand All @@ -63,3 +63,5 @@ export const defuArrayFn = createDefu((obj, key, currentValue, _namespace) => {
return true
}
})

export type { Defu } from './types'
22 changes: 11 additions & 11 deletions src/types.ts
@@ -1,5 +1,5 @@
type Input = Record<string | number | symbol, any>
type IgnoredInput = boolean | number | null | any[] | Record<never, any> | undefined
export type Input = Record<string | number | symbol, any>
export type IgnoredInput = boolean | number | null | any[] | Record<never, any> | undefined

export type Merger = <T extends Input, K extends keyof T>(
obj: T,
Expand All @@ -10,7 +10,7 @@ export type Merger = <T extends Input, K extends keyof T>(

type nullish = null | undefined | void

type MergeObjects<
export type MergeObjects<
Destination extends Input,
Defaults extends Input
> = Destination extends Defaults ? Destination : Omit<Destination, keyof Destination & keyof Defaults> & Omit<Defaults, keyof Destination & keyof Defaults> &
Expand All @@ -25,28 +25,28 @@ type MergeObjects<
: Merge<Destination[Key], Defaults[Key]> // eslint-disable-line no-use-before-define
}

type Coalesce<S extends Input, D extends Array<Input | IgnoredInput>> =
export type Defu<S extends Input, D extends Array<Input | IgnoredInput>> =
D extends [infer F, ...infer Rest]
? F extends Input
? Coalesce<MergeObjects<S, F>, Rest>
? Defu<MergeObjects<S, F>, Rest>
: F extends IgnoredInput
? Coalesce<S, Rest>
? Defu<S, Rest>
: S
: S
: S

export type DefuFn = <Source extends Input, Defaults extends Array<Input | IgnoredInput>>(
source: Source,
...defaults: Defaults
) => Coalesce<Source, Defaults>
) => Defu<Source, Defaults>

export interface Defu {
<Source extends Input, Defaults extends Array<Input | IgnoredInput>>(source: Source | IgnoredInput, ...defaults: Defaults): Coalesce<Source, Defaults>
export interface DefuInstance {
<Source extends Input, Defaults extends Array<Input | IgnoredInput>>(source: Source | IgnoredInput, ...defaults: Defaults): Defu<Source, Defaults>
fn: DefuFn
arrayFn: DefuFn
extend(merger?: Merger): DefuFn
}

type MergeArrays<Destination, Source> = Destination extends Array<infer DestinationType>
export type MergeArrays<Destination, Source> = Destination extends Array<infer DestinationType>
? Source extends Array<infer SourceType>
? Array<DestinationType | SourceType>
: Source | Array<DestinationType>
Expand Down

0 comments on commit 551ae4c

Please sign in to comment.