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