rambdax
Version:
Extended version of Rambda - a lightweight, faster alternative to Ramda
44 lines (40 loc) • 1.9 kB
text/typescript
import {_Omit} from '../Object/Omit'
import {_Pick} from '../Object/Pick'
import {At} from '../Object/At'
import {Exclude} from '../Union/Exclude'
import {Numbers} from '../Number/_Internal'
import {_ListOf} from '../Object/ListOf'
import {Has} from '../Union/Has'
/**
* @hidden
*/
type ArrayEntry = Numbers['string']['0' | '+'] // tuple entries become literal if mixed with objects
/**
* @hidden
*/
type ArrayProps = keyof any[] | ArrayEntry // so this matches any entry, whether is mixed or not
/**
* Sometimes, we can end up with mixed up `objects` that do not make sense
* visually (or that could at least be simplified for the end user). This will
* turn anything that is passed to it into a cleaned up [[Object]].
*
* @param O
* @returns [[Object]]
* @example
* ```ts
* ```
*/
export type Clean<A extends any> =
A extends object
? Has<keyof A, keyof any[]> extends 1 // if it is mixed with, or is an array
? [Exclude<keyof A, ArrayProps>] extends [never] // if it is an array, or a tuple
? number extends At<A, 'length'> // if it is an array
? At<A, number>[] // reform array
: A // it's a tuple
: number extends At<A, 'length'> // else, if it's mixed with
? _Omit<A, ArrayProps> & At<A, number>[] // untangle array
: At<A, 'length'> extends number // else, if it's a mixed tuple
? _Omit<A, ArrayProps> & _ListOf<_Pick<A, ArrayEntry>> // untangle tuple
: A // cannot clean it
: A // it has not been mixed
: A