style(skills): standardize utility-types.ts formatting
This commit is contained in:
@@ -16,14 +16,14 @@
|
|||||||
* type UserId = Brand<string, 'UserId'>
|
* type UserId = Brand<string, 'UserId'>
|
||||||
* type OrderId = Brand<string, 'OrderId'>
|
* type OrderId = Brand<string, 'OrderId'>
|
||||||
*/
|
*/
|
||||||
export type Brand<K, T> = K & { readonly __brand: T }
|
export type Brand<K, T> = K & { readonly __brand: T };
|
||||||
|
|
||||||
// Branded type constructors
|
// Branded type constructors
|
||||||
export type UserId = Brand<string, 'UserId'>
|
export type UserId = Brand<string, "UserId">;
|
||||||
export type Email = Brand<string, 'Email'>
|
export type Email = Brand<string, "Email">;
|
||||||
export type UUID = Brand<string, 'UUID'>
|
export type UUID = Brand<string, "UUID">;
|
||||||
export type Timestamp = Brand<number, 'Timestamp'>
|
export type Timestamp = Brand<number, "Timestamp">;
|
||||||
export type PositiveNumber = Brand<number, 'PositiveNumber'>
|
export type PositiveNumber = Brand<number, "PositiveNumber">;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// RESULT TYPE (Error Handling)
|
// RESULT TYPE (Error Handling)
|
||||||
@@ -34,17 +34,17 @@ export type PositiveNumber = Brand<number, 'PositiveNumber'>
|
|||||||
*/
|
*/
|
||||||
export type Result<T, E = Error> =
|
export type Result<T, E = Error> =
|
||||||
| { success: true; data: T }
|
| { success: true; data: T }
|
||||||
| { success: false; error: E }
|
| { success: false; error: E };
|
||||||
|
|
||||||
export const ok = <T>(data: T): Result<T, never> => ({
|
export const ok = <T>(data: T): Result<T, never> => ({
|
||||||
success: true,
|
success: true,
|
||||||
data
|
data,
|
||||||
})
|
});
|
||||||
|
|
||||||
export const err = <E>(error: E): Result<never, E> => ({
|
export const err = <E>(error: E): Result<never, E> => ({
|
||||||
success: false,
|
success: false,
|
||||||
error
|
error,
|
||||||
})
|
});
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// OPTION TYPE (Nullable Handling)
|
// OPTION TYPE (Nullable Handling)
|
||||||
@@ -53,13 +53,13 @@ export const err = <E>(error: E): Result<never, E> => ({
|
|||||||
/**
|
/**
|
||||||
* Explicit optional value handling.
|
* Explicit optional value handling.
|
||||||
*/
|
*/
|
||||||
export type Option<T> = Some<T> | None
|
export type Option<T> = Some<T> | None;
|
||||||
|
|
||||||
export type Some<T> = { type: 'some'; value: T }
|
export type Some<T> = { type: "some"; value: T };
|
||||||
export type None = { type: 'none' }
|
export type None = { type: "none" };
|
||||||
|
|
||||||
export const some = <T>(value: T): Some<T> => ({ type: 'some', value })
|
export const some = <T>(value: T): Some<T> => ({ type: "some", value });
|
||||||
export const none: None = { type: 'none' }
|
export const none: None = { type: "none" };
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// DEEP UTILITIES
|
// DEEP UTILITIES
|
||||||
@@ -72,28 +72,28 @@ export type DeepReadonly<T> = T extends (...args: any[]) => any
|
|||||||
? T
|
? T
|
||||||
: T extends object
|
: T extends object
|
||||||
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
|
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
|
||||||
: T
|
: T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make all properties deeply optional.
|
* Make all properties deeply optional.
|
||||||
*/
|
*/
|
||||||
export type DeepPartial<T> = T extends object
|
export type DeepPartial<T> = T extends object
|
||||||
? { [K in keyof T]?: DeepPartial<T[K]> }
|
? { [K in keyof T]?: DeepPartial<T[K]> }
|
||||||
: T
|
: T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make all properties deeply required.
|
* Make all properties deeply required.
|
||||||
*/
|
*/
|
||||||
export type DeepRequired<T> = T extends object
|
export type DeepRequired<T> = T extends object
|
||||||
? { [K in keyof T]-?: DeepRequired<T[K]> }
|
? { [K in keyof T]-?: DeepRequired<T[K]> }
|
||||||
: T
|
: T;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make all properties deeply mutable (remove readonly).
|
* Make all properties deeply mutable (remove readonly).
|
||||||
*/
|
*/
|
||||||
export type DeepMutable<T> = T extends object
|
export type DeepMutable<T> = T extends object
|
||||||
? { -readonly [K in keyof T]: DeepMutable<T[K]> }
|
? { -readonly [K in keyof T]: DeepMutable<T[K]> }
|
||||||
: T
|
: T;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// OBJECT UTILITIES
|
// OBJECT UTILITIES
|
||||||
@@ -103,38 +103,40 @@ export type DeepMutable<T> = T extends object
|
|||||||
* Get keys of object where value matches type.
|
* Get keys of object where value matches type.
|
||||||
*/
|
*/
|
||||||
export type KeysOfType<T, V> = {
|
export type KeysOfType<T, V> = {
|
||||||
[K in keyof T]: T[K] extends V ? K : never
|
[K in keyof T]: T[K] extends V ? K : never;
|
||||||
}[keyof T]
|
}[keyof T];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pick properties by value type.
|
* Pick properties by value type.
|
||||||
*/
|
*/
|
||||||
export type PickByType<T, V> = Pick<T, KeysOfType<T, V>>
|
export type PickByType<T, V> = Pick<T, KeysOfType<T, V>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Omit properties by value type.
|
* Omit properties by value type.
|
||||||
*/
|
*/
|
||||||
export type OmitByType<T, V> = Omit<T, KeysOfType<T, V>>
|
export type OmitByType<T, V> = Omit<T, KeysOfType<T, V>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make specific keys optional.
|
* Make specific keys optional.
|
||||||
*/
|
*/
|
||||||
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>
|
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make specific keys required.
|
* Make specific keys required.
|
||||||
*/
|
*/
|
||||||
export type RequiredBy<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>
|
export type RequiredBy<T, K extends keyof T> = Omit<T, K> &
|
||||||
|
Required<Pick<T, K>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make specific keys readonly.
|
* Make specific keys readonly.
|
||||||
*/
|
*/
|
||||||
export type ReadonlyBy<T, K extends keyof T> = Omit<T, K> & Readonly<Pick<T, K>>
|
export type ReadonlyBy<T, K extends keyof T> = Omit<T, K> &
|
||||||
|
Readonly<Pick<T, K>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merge two types (second overrides first).
|
* Merge two types (second overrides first).
|
||||||
*/
|
*/
|
||||||
export type Merge<T, U> = Omit<T, keyof U> & U
|
export type Merge<T, U> = Omit<T, keyof U> & U;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// ARRAY UTILITIES
|
// ARRAY UTILITIES
|
||||||
@@ -143,7 +145,7 @@ export type Merge<T, U> = Omit<T, keyof U> & U
|
|||||||
/**
|
/**
|
||||||
* Get element type from array.
|
* Get element type from array.
|
||||||
*/
|
*/
|
||||||
export type ElementOf<T> = T extends (infer E)[] ? E : never
|
export type ElementOf<T> = T extends (infer E)[] ? E : never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tuple of specific length.
|
* Tuple of specific length.
|
||||||
@@ -152,21 +154,21 @@ export type Tuple<T, N extends number> = N extends N
|
|||||||
? number extends N
|
? number extends N
|
||||||
? T[]
|
? T[]
|
||||||
: _TupleOf<T, N, []>
|
: _TupleOf<T, N, []>
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N
|
type _TupleOf<T, N extends number, R extends unknown[]> = R["length"] extends N
|
||||||
? R
|
? R
|
||||||
: _TupleOf<T, N, [T, ...R]>
|
: _TupleOf<T, N, [T, ...R]>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Non-empty array.
|
* Non-empty array.
|
||||||
*/
|
*/
|
||||||
export type NonEmptyArray<T> = [T, ...T[]]
|
export type NonEmptyArray<T> = [T, ...T[]];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* At least N elements.
|
* At least N elements.
|
||||||
*/
|
*/
|
||||||
export type AtLeast<T, N extends number> = [...Tuple<T, N>, ...T[]]
|
export type AtLeast<T, N extends number> = [...Tuple<T, N>, ...T[]];
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// FUNCTION UTILITIES
|
// FUNCTION UTILITIES
|
||||||
@@ -175,28 +177,28 @@ export type AtLeast<T, N extends number> = [...Tuple<T, N>, ...T[]]
|
|||||||
/**
|
/**
|
||||||
* Get function arguments as tuple.
|
* Get function arguments as tuple.
|
||||||
*/
|
*/
|
||||||
export type Arguments<T> = T extends (...args: infer A) => any ? A : never
|
export type Arguments<T> = T extends (...args: infer A) => any ? A : never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get first argument of function.
|
* Get first argument of function.
|
||||||
*/
|
*/
|
||||||
export type FirstArgument<T> = T extends (first: infer F, ...args: any[]) => any
|
export type FirstArgument<T> = T extends (first: infer F, ...args: any[]) => any
|
||||||
? F
|
? F
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async version of function.
|
* Async version of function.
|
||||||
*/
|
*/
|
||||||
export type AsyncFunction<T extends (...args: any[]) => any> = (
|
export type AsyncFunction<T extends (...args: any[]) => any> = (
|
||||||
...args: Parameters<T>
|
...args: Parameters<T>
|
||||||
) => Promise<Awaited<ReturnType<T>>>
|
) => Promise<Awaited<ReturnType<T>>>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Promisify return type.
|
* Promisify return type.
|
||||||
*/
|
*/
|
||||||
export type Promisify<T> = T extends (...args: infer A) => infer R
|
export type Promisify<T> = T extends (...args: infer A) => infer R
|
||||||
? (...args: A) => Promise<Awaited<R>>
|
? (...args: A) => Promise<Awaited<R>>
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// STRING UTILITIES
|
// STRING UTILITIES
|
||||||
@@ -205,22 +207,21 @@ export type Promisify<T> = T extends (...args: infer A) => infer R
|
|||||||
/**
|
/**
|
||||||
* Split string by delimiter.
|
* Split string by delimiter.
|
||||||
*/
|
*/
|
||||||
export type Split<S extends string, D extends string> =
|
export type Split<
|
||||||
S extends `${infer T}${D}${infer U}`
|
S extends string,
|
||||||
? [T, ...Split<U, D>]
|
D extends string,
|
||||||
: [S]
|
> = S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>] : [S];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Join tuple to string.
|
* Join tuple to string.
|
||||||
*/
|
*/
|
||||||
export type Join<T extends string[], D extends string> =
|
export type Join<T extends string[], D extends string> = T extends []
|
||||||
T extends []
|
? ""
|
||||||
? ''
|
|
||||||
: T extends [infer F extends string]
|
: T extends [infer F extends string]
|
||||||
? F
|
? F
|
||||||
: T extends [infer F extends string, ...infer R extends string[]]
|
: T extends [infer F extends string, ...infer R extends string[]]
|
||||||
? `${F}${D}${Join<R, D>}`
|
? `${F}${D}${Join<R, D>}`
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path to nested object.
|
* Path to nested object.
|
||||||
@@ -229,7 +230,7 @@ export type PathOf<T, K extends keyof T = keyof T> = K extends string
|
|||||||
? T[K] extends object
|
? T[K] extends object
|
||||||
? K | `${K}.${PathOf<T[K]>}`
|
? K | `${K}.${PathOf<T[K]>}`
|
||||||
: K
|
: K
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// UNION UTILITIES
|
// UNION UTILITIES
|
||||||
@@ -238,27 +239,28 @@ export type PathOf<T, K extends keyof T = keyof T> = K extends string
|
|||||||
/**
|
/**
|
||||||
* Last element of union.
|
* Last element of union.
|
||||||
*/
|
*/
|
||||||
export type UnionLast<T> = UnionToIntersection<
|
export type UnionLast<T> =
|
||||||
T extends any ? () => T : never
|
UnionToIntersection<T extends any ? () => T : never> extends () => infer R
|
||||||
> extends () => infer R
|
|
||||||
? R
|
? R
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Union to intersection.
|
* Union to intersection.
|
||||||
*/
|
*/
|
||||||
export type UnionToIntersection<U> = (
|
export type UnionToIntersection<U> = (
|
||||||
U extends any ? (k: U) => void : never
|
U extends any
|
||||||
|
? (k: U) => void
|
||||||
|
: never
|
||||||
) extends (k: infer I) => void
|
) extends (k: infer I) => void
|
||||||
? I
|
? I
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Union to tuple.
|
* Union to tuple.
|
||||||
*/
|
*/
|
||||||
export type UnionToTuple<T, L = UnionLast<T>> = [T] extends [never]
|
export type UnionToTuple<T, L = UnionLast<T>> = [T] extends [never]
|
||||||
? []
|
? []
|
||||||
: [...UnionToTuple<Exclude<T, L>>, L]
|
: [...UnionToTuple<Exclude<T, L>>, L];
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// VALIDATION UTILITIES
|
// VALIDATION UTILITIES
|
||||||
@@ -268,28 +270,25 @@ export type UnionToTuple<T, L = UnionLast<T>> = [T] extends [never]
|
|||||||
* Assert type at compile time.
|
* Assert type at compile time.
|
||||||
*/
|
*/
|
||||||
export type AssertEqual<T, U> =
|
export type AssertEqual<T, U> =
|
||||||
(<V>() => V extends T ? 1 : 2) extends (<V>() => V extends U ? 1 : 2)
|
(<V>() => V extends T ? 1 : 2) extends <V>() => V extends U ? 1 : 2
|
||||||
? true
|
? true
|
||||||
: false
|
: false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure type is not never.
|
* Ensure type is not never.
|
||||||
*/
|
*/
|
||||||
export type IsNever<T> = [T] extends [never] ? true : false
|
export type IsNever<T> = [T] extends [never] ? true : false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure type is any.
|
* Ensure type is any.
|
||||||
*/
|
*/
|
||||||
export type IsAny<T> = 0 extends 1 & T ? true : false
|
export type IsAny<T> = 0 extends 1 & T ? true : false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ensure type is unknown.
|
* Ensure type is unknown.
|
||||||
*/
|
*/
|
||||||
export type IsUnknown<T> = IsAny<T> extends true
|
export type IsUnknown<T> =
|
||||||
? false
|
IsAny<T> extends true ? false : unknown extends T ? true : false;
|
||||||
: unknown extends T
|
|
||||||
? true
|
|
||||||
: false
|
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// JSON UTILITIES
|
// JSON UTILITIES
|
||||||
@@ -298,10 +297,10 @@ export type IsUnknown<T> = IsAny<T> extends true
|
|||||||
/**
|
/**
|
||||||
* JSON-safe types.
|
* JSON-safe types.
|
||||||
*/
|
*/
|
||||||
export type JsonPrimitive = string | number | boolean | null
|
export type JsonPrimitive = string | number | boolean | null;
|
||||||
export type JsonArray = JsonValue[]
|
export type JsonArray = JsonValue[];
|
||||||
export type JsonObject = { [key: string]: JsonValue }
|
export type JsonObject = { [key: string]: JsonValue };
|
||||||
export type JsonValue = JsonPrimitive | JsonArray | JsonObject
|
export type JsonValue = JsonPrimitive | JsonArray | JsonObject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make type JSON-serializable.
|
* Make type JSON-serializable.
|
||||||
@@ -314,7 +313,7 @@ export type Jsonify<T> = T extends JsonPrimitive
|
|||||||
? R
|
? R
|
||||||
: T extends object
|
: T extends object
|
||||||
? { [K in keyof T]: Jsonify<T[K]> }
|
? { [K in keyof T]: Jsonify<T[K]> }
|
||||||
: never
|
: never;
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// EXHAUSTIVE CHECK
|
// EXHAUSTIVE CHECK
|
||||||
@@ -324,7 +323,7 @@ export type Jsonify<T> = T extends JsonPrimitive
|
|||||||
* Ensure all cases are handled in switch/if.
|
* Ensure all cases are handled in switch/if.
|
||||||
*/
|
*/
|
||||||
export function assertNever(value: never, message?: string): never {
|
export function assertNever(value: never, message?: string): never {
|
||||||
throw new Error(message ?? `Unexpected value: ${value}`)
|
throw new Error(message ?? `Unexpected value: ${value}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user