type-plus
Version:
Provides additional types for TypeScript.
204 lines (201 loc) • 4.63 kB
text/typescript
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import type { AnyRecord } from './AnyRecord.js'
import type { Omit } from './omit.js'
import { reduceByKey } from './reduceKey.js'
import type { Partial } from './Partial.js'
import type { NonUndefined } from '../utils/NonUndefined.js'
type Splitter<T extends AnyRecord> = Partial<{ [k in keyof T]: T[k] | undefined }>
export type Split<T extends AnyRecord, S extends AnyRecord> = {
[k in keyof S]-?: S[k] extends undefined ? T[k] : NonNullable<T[k]> | NonUndefined<S[k]>
}
/**
* Split an object into multiple objects.
* @returns [...entries, remaining]
*/
export function split<T extends AnyRecord, S1 extends Splitter<T>>(
target: T,
split1: S1
): [Split<T, S1>, Omit<T, keyof S1>]
export function split<T extends AnyRecord, S1 extends Splitter<T>, S2 extends Splitter<T>>(
target: T,
split1: S1,
split2: S2
): [Split<T, S1>, Split<T, S2>, Omit<T, keyof S1 | keyof S2>]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3
): [Split<T, S1>, Split<T, S2>, Split<T, S3>, Omit<T, keyof S1 | keyof S2 | keyof S3>]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>,
S4 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3,
splitter4: S4
): [
Split<T, S1>,
Split<T, S2>,
Split<T, S3>,
Split<T, S4>,
Omit<T, keyof S1 | keyof S2 | keyof S3 | keyof S4>
]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>,
S4 extends Splitter<T>,
S5 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3,
splitter4: S4,
splitter5: S5
): [
Split<T, S1>,
Split<T, S2>,
Split<T, S3>,
Split<T, S4>,
Split<T, S5>,
Omit<T, keyof S1 | keyof S2 | keyof S3 | keyof S4 | keyof S5>
]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>,
S4 extends Splitter<T>,
S5 extends Splitter<T>,
S6 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3,
splitter4: S4,
splitter5: S5,
splitter6: S6
): [
Split<T, S1>,
Split<T, S2>,
Split<T, S3>,
Split<T, S4>,
Split<T, S5>,
Split<T, S6>,
Omit<T, keyof S1 | keyof S2 | keyof S3 | keyof S4 | keyof S5 | keyof S6>
]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>,
S4 extends Splitter<T>,
S5 extends Splitter<T>,
S6 extends Splitter<T>,
S7 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3,
splitter4: S4,
splitter5: S5,
splitter6: S6,
splitter7: S7
): [
Split<T, S1>,
Split<T, S2>,
Split<T, S3>,
Split<T, S4>,
Split<T, S5>,
Split<T, S6>,
Split<T, S7>,
Omit<T, keyof S1 | keyof S2 | keyof S3 | keyof S4 | keyof S5 | keyof S6 | keyof S7>
]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>,
S4 extends Splitter<T>,
S5 extends Splitter<T>,
S6 extends Splitter<T>,
S7 extends Splitter<T>,
S8 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3,
splitter4: S4,
splitter5: S5,
splitter6: S6,
splitter7: S7,
splitter8: S8
): [
Split<T, S1>,
Split<T, S2>,
Split<T, S3>,
Split<T, S4>,
Split<T, S5>,
Split<T, S6>,
Split<T, S7>,
Split<T, S8>,
Omit<T, keyof S1 | keyof S2 | keyof S3 | keyof S4 | keyof S5 | keyof S6 | keyof S7 | keyof S8>
]
export function split<
T extends AnyRecord,
S1 extends Splitter<T>,
S2 extends Splitter<T>,
S3 extends Splitter<T>,
S4 extends Splitter<T>,
S5 extends Splitter<T>,
S6 extends Splitter<T>,
S7 extends Splitter<T>,
S8 extends Splitter<T>,
S9 extends Splitter<T>
>(
target: T,
splitter1: S1,
splitter2: S2,
splitter3: S3,
splitter4: S4,
splitter5: S5,
splitter6: S6,
splitter7: S7,
splitter8: S8,
splitter9: S9
): [
Split<T, S1>,
Split<T, S2>,
Split<T, S3>,
Split<T, S4>,
Split<T, S5>,
Split<T, S6>,
Split<T, S7>,
Split<T, S8>,
Split<T, S9>,
Omit<T, keyof S1 | keyof S2 | keyof S3 | keyof S4 | keyof S5 | keyof S6 | keyof S7 | keyof S8 | keyof S9>
]
export function split(target: AnyRecord, ...splitters: AnyRecord[]): AnyRecord[] {
const keyMap: AnyRecord = {}
const s = splitters.map(s =>
reduceByKey(s, (p, k) => ((keyMap[k] = true), (p[k] = target[k] ?? s[k]), p), {} as AnyRecord)
)
const r = reduceByKey(target, (p, k) => (keyMap[k] ? p : ((p[k] = target[k]), p)), {} as AnyRecord)
return [...s, r]
}