Comparing version 1.0.10 to 1.0.11
@@ -36,5 +36,5 @@ import { Fn, PartialApply, unset, _ } from "../core/Core"; | ||
export type Parameter<N extends number | _ | unset = unset, fn extends ((...args: any[]) => any) | _ | unset = unset> = PartialApply<ParameterFn, [fn, N]>; | ||
type ReturnImpl<fn> = fn extends (...args: any[]) => infer ret ? ret : never; | ||
type ReturnTypeImpl<fn> = fn extends (...args: any[]) => infer ret ? ret : never; | ||
/** | ||
* Returns the return type of a function. | ||
* ReturnTypes the return type of a function. | ||
* | ||
@@ -46,10 +46,11 @@ * @param fn - The function to extract the return type from. | ||
* ```ts | ||
* type T0 = Call<Return, (a: number, b: string) => number>; // number | ||
* type T1 = Eval<Return<(a: number, b: string) => number>>; // number | ||
* type T0 = Call<ReturnType, (a: number, b: string) => number>; // number | ||
* type T1 = Eval<ReturnType<(a: number, b: string) => number>>; // number | ||
* ``` | ||
*/ | ||
export interface Return extends Fn { | ||
return: ReturnImpl<this["arg0"]>; | ||
export type ReturnType<fn extends ((...args: any[]) => any) | _ | unset = unset> = PartialApply<ReturnTypeFn, [fn]>; | ||
export interface ReturnTypeFn extends Fn { | ||
return: ReturnTypeImpl<this["arg0"]>; | ||
} | ||
export {}; | ||
} |
import { Apply, Call, Fn } from "../../core/Core"; | ||
import { Strings } from "../../strings/Strings"; | ||
import { Equal, Prettify, Primitive, UnionToIntersection } from "../../helpers"; | ||
import { Std } from "../../std/Std"; | ||
export type Keys<src> = src extends unknown[] ? { | ||
import { Equal, IsTuple, Prettify, Primitive, UnionToIntersection } from "../../helpers"; | ||
export type Keys<src> = src extends readonly unknown[] ? { | ||
[key in keyof src]: key; | ||
@@ -15,12 +14,2 @@ }[number] extends infer res ? res extends string ? Call<Strings.ToNumber, res> & keyof src : res & keyof src : never : keyof src; | ||
}[keys] : never; | ||
type GroupByImplRec<xs, fn extends Fn, acc = {}> = xs extends [ | ||
infer first, | ||
...infer rest | ||
] ? Call<fn, first> extends infer key extends PropertyKey ? GroupByImplRec<rest, fn, Std._Omit<acc, key> & { | ||
[K in key]: [ | ||
...(key extends keyof acc ? Extract<acc[key], readonly any[]> : []), | ||
first | ||
]; | ||
}> : never : acc; | ||
export type GroupBy<xs, fn extends Fn> = Prettify<GroupByImplRec<xs, fn>>; | ||
export type Assign<xs extends readonly any[]> = Prettify<UnionToIntersection<xs[number]>>; | ||
@@ -32,13 +21,20 @@ export type GetFromPath<Obj, path> = RecursiveGet<Obj, ParsePath<path>>; | ||
], ""> : ParsePath<rest, output, `${currentChunk}${first}`> : [...output, ...(currentChunk extends "" ? [] : [currentChunk])]; | ||
type RecursiveGet<Obj, pathList> = Obj extends any ? pathList extends [infer first, ...infer rest] ? first extends keyof Obj ? RecursiveGet<Obj[first], rest> : [first, Obj] extends [`${number}` | "number", any[]] ? RecursiveGet<Extract<Obj, any[]>[number], rest> : undefined : Obj : never; | ||
export type PartialDeep<T> = T extends object ? { | ||
[P in keyof T]?: PartialDeep<T[P]>; | ||
} : T; | ||
type RecursiveGet<Obj, pathList> = Obj extends any ? pathList extends [infer first, ...infer rest] ? first extends keyof Obj ? RecursiveGet<Obj[first], rest> : [first, Obj] extends [`${number}` | "number", readonly any[]] ? RecursiveGet<Extract<Obj, any[]>[number], rest> : undefined : Obj : never; | ||
export type TransformObjectDeep<fn extends Fn, type> = type extends Function | Date ? type : type extends Map<infer keys, infer values> ? Map<TransformObjectDeep<fn, keys>, TransformObjectDeep<fn, values>> : type extends ReadonlyMap<infer keys, infer values> ? ReadonlyMap<TransformObjectDeep<fn, keys>, TransformObjectDeep<fn, values>> : type extends WeakMap<infer keys, infer values> ? WeakMap<Extract<TransformObjectDeep<fn, keys>, object>, TransformObjectDeep<fn, values>> : type extends Set<infer values> ? Set<TransformObjectDeep<fn, values>> : type extends ReadonlySet<infer values> ? ReadonlySet<TransformObjectDeep<fn, values>> : type extends WeakSet<infer values> ? WeakSet<Extract<TransformObjectDeep<fn, values>, object>> : type extends Array<infer values> ? IsTuple<type> extends true ? Call<fn, { | ||
[Key in keyof type]: TransformObjectDeep<fn, type[Key]>; | ||
}> : Array<TransformObjectDeep<fn, values> | undefined> : type extends Promise<infer value> ? Promise<TransformObjectDeep<fn, value>> : type extends object ? Call<fn, { | ||
[Key in keyof type]: TransformObjectDeep<fn, type[Key]>; | ||
}> : Equal<type, unknown> extends true ? unknown : Partial<type>; | ||
export type Update<obj, path, fnOrValue> = RecursiveUpdate<obj, ParsePath<path>, fnOrValue>; | ||
type RecursiveUpdate<obj, pathList, fnOrValue> = obj extends any ? pathList extends [infer first, ...infer rest] ? first extends keyof obj ? { | ||
[K in keyof obj]: Equal<first, K> extends true ? RecursiveUpdate<obj[K], rest, fnOrValue> : obj[K]; | ||
} : [first, obj] extends ["number", any[]] ? RecursiveUpdate<Extract<obj, any[]>[number], rest, fnOrValue>[] : undefined : fnOrValue extends Fn ? Call<Extract<fnOrValue, Fn>, obj> : fnOrValue : never; | ||
export type Create<pattern, args extends unknown[]> = pattern extends infer p extends Fn ? Apply<p, args> : pattern extends Primitive ? pattern : pattern extends [any, ...any] ? { | ||
} : [first, obj] extends ["number", readonly any[]] ? RecursiveUpdate<Extract<obj, any[]>[number], rest, fnOrValue>[] : Assign<[ | ||
obj, | ||
{ | ||
[K in Extract<first, PropertyKey>]: RecursiveUpdate<{}, rest, fnOrValue>; | ||
} | ||
]> : fnOrValue extends Fn ? Call<Extract<fnOrValue, Fn>, obj> : fnOrValue : never; | ||
export type Create<pattern, args extends unknown[]> = pattern extends infer p extends Fn ? Apply<p, args> : pattern extends Primitive ? pattern : pattern extends readonly [any, ...any] ? { | ||
[key in keyof pattern]: Create<pattern[key], args>; | ||
} : pattern extends (infer V)[] ? Create<V, args>[] : pattern extends object ? { | ||
} : pattern extends readonly (infer V)[] ? Create<V, args>[] : pattern extends object ? { | ||
[key in keyof pattern]: Create<pattern[key], args>; | ||
@@ -49,3 +45,3 @@ } : pattern; | ||
] extends [never] ? B : [B] extends [never] ? A : `${A}${Sep}${B}`; | ||
export type AllPaths<T, ParentPath extends string = never> = T extends Primitive ? ParentPath : unknown extends T ? JoinPath<ParentPath, string, "."> : T extends any[] ? Keys<T> extends infer key extends string | number ? JoinPath<ParentPath, `[${key}]`> | AllPaths<T[number], JoinPath<ParentPath, `[${key}]`>> : never : keyof T extends infer key extends keyof T & string ? key extends any ? JoinPath<ParentPath, key, "."> | AllPaths<T[key], JoinPath<ParentPath, key, ".">> : never : ParentPath; | ||
export type AllPaths<T, ParentPath extends string = never> = T extends Primitive ? ParentPath : unknown extends T ? JoinPath<ParentPath, string, "."> : T extends readonly any[] ? Keys<T> extends infer key extends string | number ? JoinPath<ParentPath, `[${key}]`> | AllPaths<T[number], JoinPath<ParentPath, `[${key}]`>> : never : keyof T extends infer key extends keyof T & string ? key extends any ? JoinPath<ParentPath, key, "."> | AllPaths<T[key], JoinPath<ParentPath, key, ".">> : never : ParentPath; | ||
export {}; |
@@ -7,5 +7,23 @@ import { IsArrayStrict, Prettify } from "../helpers"; | ||
export declare namespace Objects { | ||
/** | ||
* Create an object from a union of `[key, value]` entries. | ||
* @param entries - union of entries to convert to an object | ||
* @returns an object | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.FromEntries, ["a", 1] | ["b", true]>; // { a: 1; b: true } | ||
* ``` | ||
*/ | ||
export interface FromEntries extends Fn { | ||
return: Impl.FromEntries<Extract<this["arg0"], [PropertyKey, any]>>; | ||
} | ||
/** | ||
* Turn an object into a union of entries | ||
* @param obj - The object to transform to entries | ||
* @returns a union of `[key, value]` entry tuples. | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.Entries, { a: 1; b: true }>; // ["a", 1] | ["b", true] | ||
* ``` | ||
*/ | ||
export interface Entries extends Fn { | ||
@@ -17,2 +35,15 @@ return: Impl.Entries<this["arg0"]>; | ||
}; | ||
/** | ||
* Map over values in an object type. | ||
* @param fn - The function to run on every object value | ||
* @param obj - The object to transform | ||
* @returns a new object with updated values | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.MapValues<Strings.ToNumber>, | ||
* { a: "1"; b: "2" } | ||
* >; // { a: 1, b: 2 } | ||
* ``` | ||
*/ | ||
export interface MapValues<fn extends Fn> extends Fn { | ||
@@ -24,11 +55,60 @@ return: MapValuesImpl<this["arg0"], fn>; | ||
}; | ||
/** | ||
* Map over keys in an object type. | ||
* @param fn - The function to run on every object key | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.MapKeys<Strings.Uppercase>, | ||
* { a: 1; b: 2 } | ||
* >; // { A: 1, B: 2 } | ||
* ``` | ||
*/ | ||
export interface MapKeys<fn extends Fn> extends Fn { | ||
return: MapKeysImpl<this["arg0"], fn>; | ||
} | ||
/** | ||
* Turn object keys into kebab-case | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.KebabCase, | ||
* { userName: "Bob" } | ||
* >; // { "user-name": "Bob" } | ||
* ``` | ||
*/ | ||
export interface KebabCase extends Fn { | ||
return: Call<MapKeys<Strings.KebabCase>, this["arg0"]>; | ||
} | ||
/** | ||
* Turn object keys into snake_case | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.SnakeCase, | ||
* { userName: "Bob" } | ||
* >; // { user_name: "Bob" } | ||
* ``` | ||
*/ | ||
export interface SnakeCase extends Fn { | ||
return: Call<MapKeys<Strings.SnakeCase>, this["arg0"]>; | ||
} | ||
/** | ||
* Turn object keys into camelCase | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.CamelCase, | ||
* { user_name: "Bob" } | ||
* >; // { userName: "Bob" } | ||
* ``` | ||
*/ | ||
export interface CamelCase extends Fn { | ||
@@ -40,17 +120,80 @@ return: Call<MapKeys<Strings.CamelCase>, this["arg0"]>; | ||
} : T; | ||
/** | ||
* Recursively transform all keys in a structure of object types | ||
* @param fn - The function to apply to every key | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.MapKeysDeep<Strings.Prepend<'_'>>, | ||
* { a: { b: { c: string } } } | ||
* >; // { _a: { _b: { _c: string } } } | ||
* ``` | ||
*/ | ||
export interface MapKeysDeep<fn extends Fn> extends Fn { | ||
return: MapKeysDeepImpl<this["arg0"], fn>; | ||
} | ||
/** | ||
* Recursively transform all keys of a deeply nested object | ||
* to kebab-case. | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.KebabCaseDeep, | ||
* { currentUser: { firstName: string } } | ||
* >; // { "current-user": { "first-name": string } } | ||
* ``` | ||
*/ | ||
export interface KebabCaseDeep extends Fn { | ||
return: Call<MapKeysDeep<Strings.KebabCase>, this["arg0"]>; | ||
} | ||
/** | ||
* Recursively transform all keys of a deeply nested object | ||
* to snake_case. | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.SnakeCaseDeep, | ||
* { currentUser: { firstName: string } } | ||
* >; // { current_user: { first_name: string } } | ||
* ``` | ||
*/ | ||
export interface SnakeCaseDeep extends Fn { | ||
return: Call<MapKeysDeep<Strings.SnakeCase>, this["arg0"]>; | ||
} | ||
/** | ||
* Recursively transform all keys of a deeply nested object | ||
* to camelCase. | ||
* @param obj - The object to transform | ||
* @returns a new object with updated keys | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.CamelCaseDeep, | ||
* { current_user: { first_name: string } } | ||
* >; // { currentUser: { firstName: string } } | ||
* ``` | ||
*/ | ||
export interface CamelCaseDeep extends Fn { | ||
return: Call<MapKeysDeep<Strings.CamelCase>, this["arg0"]>; | ||
} | ||
type PickImpl<obj, keys> = { | ||
[key in Extract<keyof obj, keys>]: obj[key]; | ||
}; | ||
/** | ||
* Only keep keys of an object if they are | ||
* assignable to some type. | ||
* @param key - The type remaining keys should be assignable to | ||
* @param obj - The object to filter | ||
* @returns a filtered object | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.Pick<"a" | "b">, | ||
* { a: 1, b: 1, c: 1 } | ||
* >; // { a: 1, b: 1 } | ||
* ``` | ||
*/ | ||
export type Pick<key = unset, obj = unset> = PartialApply<PickFn, [key, obj]>; | ||
@@ -60,6 +203,80 @@ interface PickFn extends Fn { | ||
} | ||
interface ReadonlyFn extends Fn { | ||
return: this["args"] extends [infer value] ? Std._Readonly<value> : never; | ||
type PickImpl<obj, keys> = { | ||
[key in Extract<keyof obj, keys>]: obj[key]; | ||
}; | ||
/** | ||
* Only keep keys of an object if they aren't | ||
* assignable to some type. | ||
* @param key - The type remaining keys should _not_ be assignable to | ||
* @param obj - The object to filter | ||
* @returns a filtered object | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.Pick<"a" | "b">, | ||
* { a: 1, b: 1, c: 1 } | ||
* >; // { c: 1 } | ||
* ``` | ||
*/ | ||
export type Omit<key = unset, obj = unset> = PartialApply<OmitFn, [key, obj]>; | ||
interface OmitFn extends Fn { | ||
return: OmitImpl<this["arg1"], this["arg0"]>; | ||
} | ||
type OmitImpl<obj, keys> = { | ||
[key in Exclude<keyof obj, keys>]: obj[key]; | ||
}; | ||
/** | ||
* Only keep keys of an object if the predicate function | ||
* returns true | ||
* @param fn - The predicate function, taking (value, key) as arguments | ||
* @param obj - The object to filter | ||
* @returns a filtered object | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.PickBy<Strings.StartsWith<"a">>, | ||
* { a: "ab", b: "ac", c: "bc" } | ||
* >; // { a: "ab", b: "ac" } | ||
* ``` | ||
*/ | ||
export interface PickBy<fn extends Fn> extends Fn { | ||
return: PickByImpl<this["arg0"], fn>; | ||
} | ||
type PickByImpl<T, fn extends Fn> = Impl.FromEntries<PickEntriesImpl<Impl.Entries<T>, fn>>; | ||
type PickEntriesImpl<entries extends [PropertyKey, any], fn extends Fn> = entries extends any ? Call2<fn, entries[1], entries[0]> extends true ? entries : never : never; | ||
/** | ||
* Only keep keys of an object if the predicate function | ||
* returns false | ||
* @param fn - The predicate function, taking (value, key) as arguments | ||
* @param obj - The object to filter | ||
* @returns a filtered object | ||
* @example | ||
* ```ts | ||
* type T0 = Call< | ||
* Objects.PickBy<Strings.StartsWith<"a">>, | ||
* { a: "ab", b: "ac", c: "bc" } | ||
* >; // { c: "bc" } | ||
* ``` | ||
*/ | ||
export interface OmitBy<fn extends Fn> extends Fn { | ||
return: OmitByImpl<this["arg0"], fn>; | ||
} | ||
type OmitByImpl<T, fn extends Fn> = Impl.FromEntries<OmitEntriesImpl<Impl.Entries<T>, fn>>; | ||
type OmitEntriesImpl<entries extends [PropertyKey, any], fn extends Fn> = entries extends any ? Call2<fn, entries[1], entries[0]> extends true ? never : entries : never; | ||
/** | ||
* Merge several objects together | ||
* @param {...objects} - Objects to merge | ||
* @returns a merged object | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.Assign<{ a: string }>, { b: number }>; // { a: string, b: number } | ||
* type T1 = Eval<Objects.Assign<{ a: string }, { b: number }>>; // { a: string, b: number } | ||
* type T2 = Eval<Objects.Assign<{ a: 1 }, { b: 1 }, { c: 1 }>>; // { a: 1, b: 1, c: 1 } | ||
* ``` | ||
*/ | ||
export type Assign<arg1 = unset, arg2 = unset, arg3 = unset, arg4 = unset, arg5 = unset> = PartialApply<AssignFn, [arg1, arg2, arg3, arg4, arg5]>; | ||
interface AssignFn extends Fn { | ||
return: Impl.Assign<this["args"]>; | ||
} | ||
/** | ||
* Make all properties of an object readonly | ||
@@ -71,3 +288,3 @@ * @description This function is used to make properties of an object readonly | ||
* ```ts | ||
* type T0 = Call<Objects.Readonly, {a: 1; b: true }>; // { readonly a:1; readonly b: true} | ||
* type T0 = Call<Objects.Readonly, { a: 1; b: true }>; // { readonly a:1; readonly b: true} | ||
* type T1 = Eval<Objects.Readonly<{ a: 1; b: true }>>; // { readonly a:1; readonly b: true} | ||
@@ -77,4 +294,4 @@ * ``` | ||
export type Readonly<value = unset> = PartialApply<ReadonlyFn, [value]>; | ||
interface RequiredFn extends Fn { | ||
return: this["args"] extends [infer value] ? Std._Required<value> : never; | ||
interface ReadonlyFn extends Fn { | ||
return: this["args"] extends [infer value] ? Std._Readonly<value> : never; | ||
} | ||
@@ -88,3 +305,3 @@ /** | ||
* ```ts | ||
* type T0 = Call<Objects.Required, {a?: 1; b?: true }>; // { a:1; b: true} | ||
* type T0 = Call<Objects.Required, { a?: 1; b?: true }>; // { a:1; b: true} | ||
* type T1 = Eval<Objects.Required<{ a?: 1; b?: true }>>; // { a:1; b: true} | ||
@@ -94,4 +311,4 @@ * ``` | ||
export type Required<value = unset> = PartialApply<RequiredFn, [value]>; | ||
interface PartialFn extends Fn { | ||
return: this["args"] extends [infer value] ? Std._Partial<value> : never; | ||
interface RequiredFn extends Fn { | ||
return: this["args"] extends [infer value] ? Std._Required<value> : never; | ||
} | ||
@@ -105,3 +322,3 @@ /** | ||
* ```ts | ||
* type T0 = Call<Objects.Partial, {a: 1; b: true }>; // { a?:1; b?: true} | ||
* type T0 = Call<Objects.Partial, { a: 1; b: true }>; // { a?:1; b?: true} | ||
* type T1 = Eval<Objects.Partial<{ a: 1; b: true }>>; // { a?:1; b?: true} | ||
@@ -111,34 +328,20 @@ * ``` | ||
export type Partial<value = unset> = PartialApply<PartialFn, [value]>; | ||
type OmitImpl<obj, keys> = { | ||
[key in Exclude<keyof obj, keys>]: obj[key]; | ||
}; | ||
export type Omit<key = unset, obj = unset> = PartialApply<OmitFn, [key, obj]>; | ||
interface OmitFn extends Fn { | ||
return: OmitImpl<this["arg1"], this["arg0"]>; | ||
interface PartialFn extends Fn { | ||
return: this["args"] extends [infer value] ? Std._Partial<value> : never; | ||
} | ||
type PickEntriesImpl<entries extends [PropertyKey, any], fn extends Fn> = entries extends any ? Call2<fn, entries[1], entries[0]> extends true ? entries : never : never; | ||
type PickByImpl<T, fn extends Fn> = Impl.FromEntries<PickEntriesImpl<Impl.Entries<T>, fn>>; | ||
export interface PickBy<fn extends Fn> extends Fn { | ||
return: PickByImpl<this["arg0"], fn>; | ||
/** | ||
* Make all properties of an object mutable | ||
* @param value - The object to make properties mutable | ||
* @returns The object with its properties made mutable | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.Mutable, { readonly a: 1; readonly b: true }>; // { a:1; b: true } | ||
* ``` | ||
*/ | ||
export type Mutable<obj = unset> = PartialApply<MutableFn, [obj]>; | ||
interface MutableFn extends Fn { | ||
return: this["args"] extends [infer obj, ...any] ? { | ||
-readonly [key in keyof obj]: obj[key]; | ||
} : never; | ||
} | ||
type OmitEntriesImpl<entries extends [PropertyKey, any], fn extends Fn> = entries extends any ? Call2<fn, entries[1], entries[0]> extends true ? never : entries : never; | ||
type OmitByImpl<T, fn extends Fn> = Impl.FromEntries<OmitEntriesImpl<Impl.Entries<T>, fn>>; | ||
export interface OmitBy<fn extends Fn> extends Fn { | ||
return: OmitByImpl<this["arg0"], fn>; | ||
} | ||
export type Assign<arg1 = unset, arg2 = unset, arg3 = unset, arg4 = unset, arg5 = unset> = PartialApply<AssignFn, [arg1, arg2, arg3, arg4, arg5]>; | ||
interface AssignFn extends Fn { | ||
return: Impl.Assign<this["args"]>; | ||
} | ||
export interface GroupBy<fn extends Fn> extends Fn { | ||
return: Impl.GroupBy<this["arg0"], fn>; | ||
} | ||
export type Get<path extends string | number | _ | unset = unset, obj = unset> = PartialApply<GetFn, [path, obj]>; | ||
export interface GetFn extends Fn { | ||
return: this["args"] extends [ | ||
infer path extends string | number, | ||
infer obj, | ||
...any | ||
] ? Impl.GetFromPath<obj, path> : never; | ||
} | ||
/** | ||
@@ -152,11 +355,94 @@ * Makes all levels of an object optional | ||
* ```ts | ||
* type T0 = Call<Objects.PartialDeep, {a: 1; b: true }>; // { a?:1; b?: true} | ||
* type T1 = Call<Objects.PartialDeep, {a: 1; b: { c: true } }>; // { a?:1; b?: { c?: true } } | ||
* type T2 = Call<Objects.PartialDeep, {a: 1; b: { c: true, d: { e: false } } }>; // { a?:1; b?: { c?: true, d?: { e?: false } } } | ||
* type T0 = Call<Objects.PartialDeep, { a: 1; b: true }>; | ||
* // ^? { a?:1; b?: true} | ||
* type T1 = Call<Objects.PartialDeep, { a: 1; b: { c: true } }>; | ||
* // ^? { a?:1; b?: { c?: true } } | ||
* type T2 = Call<Objects.PartialDeep, { a: 1; b: { c: true, d: { e: false } } }>; | ||
* // ^? { a?:1; b?: { c?: true, d?: { e?: false } } } | ||
*/ | ||
export type PartialDeep<obj = unset> = PartialApply<PartialDeepFn, [obj]>; | ||
interface PartialDeepFn extends Fn { | ||
return: this["args"] extends [infer obj] ? Impl.PartialDeep<obj> : never; | ||
return: this["args"] extends [infer obj] ? Impl.TransformObjectDeep<PartialFn, obj> : never; | ||
} | ||
/** | ||
* Makes all levels of an object required | ||
* @description This function is used to make all levels of an object required | ||
* @param obj - The object to make levels required | ||
* @returns The object with its levels made required | ||
* | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.RequiredDeep, { a?:1; b?: true }>; | ||
* // ^? { a: 1; b: true } | ||
* type T1 = Call<Objects.RequiredDeep, { a?:1; b?: { c?: true } }>; | ||
* // ^? { a: 1; b: { c: true } } | ||
* type T2 = Call<Objects.RequiredDeep, { a?:1; b?: { c?: true, d?: { e?: false } } }>; | ||
* // ^? { a: 1; b: { c: true, d: { e: false } } } | ||
*/ | ||
export type RequiredDeep<obj = unset> = PartialApply<RequiredDeepFn, [obj]>; | ||
interface RequiredDeepFn extends Fn { | ||
return: this["args"] extends [infer obj] ? Impl.TransformObjectDeep<RequiredFn, obj> : never; | ||
} | ||
/** | ||
* Makes all levels of an object readonly | ||
* @description This function is used to make all levels of an object readonly | ||
* @param obj - The object to make levels readonly | ||
* @returns The object with its levels made readonly | ||
* | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.ReadonlyDeep, { a:1; b: true }>; | ||
* // ^? { readonly a: 1; readonly b: true } | ||
* type T1 = Call<Objects.ReadonlyDeep, { a:1; b: { c: true } }>; | ||
* // ^? { readonly a: 1; readonly b: { readonly c: true } } | ||
* type T2 = Call<Objects.ReadonlyDeep, { a:1; b: { c: true, d: { e: false } } }>; | ||
* // ^? { readonly a: 1; readonly b: { readonly c: true, d: { readonly e: false } } } | ||
*/ | ||
export type ReadonlyDeep<obj = unset> = PartialApply<ReadonlyDeepFn, [obj]>; | ||
interface ReadonlyDeepFn extends Fn { | ||
return: this["args"] extends [infer obj] ? Impl.TransformObjectDeep<ReadonlyFn, obj> : never; | ||
} | ||
/** | ||
* Makes all levels of an object mutable | ||
* @description This function is used to make all levels of an object mutable | ||
* @param obj - The object to make levels mutable | ||
* @returns The object with its levels made mutable | ||
* | ||
* @example | ||
* ```ts | ||
* type T0 = Call<Objects.MutableDeep, { readonly a: 1; readonly b: true }>; | ||
* // ^? { a:1; b: true } | ||
* type T1 = Call<Objects.MutableDeep, { readonly a: 1; readonly b: { readonly c: true } }>; | ||
* // ^? { a:1; b: { c: true } } | ||
* type T2 = Call<Objects.MutableDeep, { readonly a: 1; readonly b: { readonly c: true, d: { readonly e: false } } }>; | ||
* // ^? { a:1; b: { c: true, d: { e: false } } } | ||
*/ | ||
export type MutableDeep<obj = unset> = PartialApply<MutableDeepFn, [obj]>; | ||
interface MutableDeepFn extends Fn { | ||
return: this["args"] extends [infer obj] ? Impl.TransformObjectDeep<MutableFn, obj> : never; | ||
} | ||
/** | ||
* Get a value within an object or a tuple type. | ||
* @description This function takes an object, a path to one of its properties, | ||
* and returns the property under that path. | ||
* @param path - the path to the property to get. | ||
* @param obj - the object to read from. | ||
* @returns The value under that path | ||
* | ||
* @example | ||
* ```ts | ||
* type T0 = Call<O.Get<'a'>, { a: 1, b: 1 }>; // 1 | ||
* type T1 = Call<O.Get<'a[0]'>, { a: [1, 2, 3] }>; // 1 | ||
* type T2 = Call<O.Get<'a.b'>, { a: { b: 1 }, c: '' }>; // 1 | ||
* ``` | ||
*/ | ||
export type Get<path extends string | number | _ | unset = unset, obj = unset> = PartialApply<GetFn, [path, obj]>; | ||
export interface GetFn extends Fn { | ||
return: this["args"] extends [ | ||
infer path extends string | number, | ||
infer obj, | ||
...any | ||
] ? Impl.GetFromPath<obj, path> : never; | ||
} | ||
/** | ||
* Updates an object or a tuple type. | ||
@@ -163,0 +449,0 @@ * @description This function takes an object, a path to one of its properties, |
import { Numbers as N, Numbers } from "../numbers/Numbers"; | ||
import { Apply, args, Call, Call2, Eval, Fn, PartialApply, Pipe, unset, _ } from "../core/Core"; | ||
import { Iterator, Stringifiable } from "../helpers"; | ||
import { Iterator, Prettify, Stringifiable } from "../helpers"; | ||
import { Objects } from "../objects/Objects"; | ||
import * as NumberImpls from "../numbers/impl/numbers"; | ||
import { Std } from "../std/Std"; | ||
export declare namespace Tuples { | ||
@@ -542,2 +543,33 @@ type HeadImpl<xs> = xs extends readonly [infer head, ...any] ? head : never; | ||
/** | ||
* Group values in a tuple into an object, using a predicate | ||
* to compute the key of each group. | ||
* @param fn - function applied to all values in the tuple to get a key. | ||
* @param tuple - A list of element | ||
* @returns an object containing a list of element for each key. | ||
* @example | ||
* ```ts | ||
* interface IsNumber extends Fn { | ||
* return: this["arg0"] extends number ? true : false; | ||
* } | ||
* | ||
* type T0 = Call<Tuples.GroupBy<IsNumber>, [1, "str", 2]>; | ||
* // ^? { true: [1, 2], false: ["str"] } | ||
* type T2 = Call<Tuples.GroupBy<Strings.StartsWith<"a">>, ["alice", "bob", "carl"]>; | ||
* // ^? { true: ["alice"], false: ["bob", "carl"] } | ||
* ``` | ||
*/ | ||
export interface GroupBy<fn extends Fn> extends Fn { | ||
return: GroupByImpl<this["arg0"], fn>; | ||
} | ||
type GroupByImplRec<xs, fn extends Fn, acc = {}> = xs extends [ | ||
infer first, | ||
...infer rest | ||
] ? Call<fn, first> extends infer key extends PropertyKey ? GroupByImplRec<rest, fn, Std._Omit<acc, key> & { | ||
[K in key]: [ | ||
...(key extends keyof acc ? Extract<acc[key], readonly any[]> : []), | ||
first | ||
]; | ||
}> : never : acc; | ||
export type GroupByImpl<xs, fn extends Fn> = Prettify<GroupByImplRec<xs, fn>>; | ||
/** | ||
* Range takes a `start` and an `end` integer and produces | ||
@@ -544,0 +576,0 @@ * a tuple containing integer ranging from `start` to `end` |
{ | ||
"name": "hotscript", | ||
"version": "1.0.10", | ||
"version": "1.0.11", | ||
"description": "Type-level madness", | ||
@@ -5,0 +5,0 @@ "type": "module", |
# Higher-Order TypeScript (HOTScript) | ||
A lodash-like library for types, with support for type-level lambda functions. | ||
A library of composable functions for the type-level! Transform your TypeScript types in any way you want using functions you already know. | ||
 | ||
## Features | ||
- Type-level higher-order functions (`Tuples.Map`, `Tuples.Filter`, `Objects.MapValues`, etc). | ||
- Type-level pattern matching with `Match`. | ||
- Performant math operations (`Numbers.Add`, `Numbers.Sub`, `Numbers.Mul`, `Numbers.Div`, etc). | ||
- Custom "lambda" functions. | ||
🚧 work in progress 🚧 | ||
@@ -143,6 +152,6 @@ | ||
- [x] Find | ||
- [x] Sum | ||
- [x] Drop n | ||
- [x] Take n | ||
- [x] TakeWhile | ||
- [x] GroupBy | ||
- [x] Join separator | ||
@@ -160,10 +169,13 @@ - [x] Map | ||
- [x] Concat | ||
- [x] Min | ||
- [x] Max | ||
- [x] Sum | ||
- [ ] Object | ||
- [x] Readonly | ||
- [ ] Mutable | ||
- [x] Mutable | ||
- [x] Required | ||
- [x] Partial | ||
- [ ] ReadonlyDeep | ||
- [ ] MutableDeep | ||
- [ ] RequiredDeep | ||
- [x] ReadonlyDeep | ||
- [x] MutableDeep | ||
- [x] RequiredDeep | ||
- [x] PartialDeep | ||
@@ -181,3 +193,2 @@ - [x] Update | ||
- [x] MapKeys | ||
- [x] GroupBy | ||
- [x] Assign | ||
@@ -194,4 +205,2 @@ - [x] Pick | ||
- [x] KebabCaseDeep | ||
- [x] Min | ||
- [x] Max | ||
- [ ] Union | ||
@@ -198,0 +207,0 @@ - [x] Map |
185174
4812
264