Skip to content

Instantly share code, notes, and snippets.

View ReVoid's full-sized avatar

Dmitrii Poroshin ReVoid

  • Kazakhstan, Astana
View GitHub Profile
@ReVoid
ReVoid / keysOf.ts
Created February 6, 2024 14:05
Strongly typed Object.keys()
type Key<T extends object> = keyof T;
type Keys<T extends object> = Array<Key<T>>;
function keysOf<T extends object>(value: T): Keys<T> {
const keys: string[] = Object.keys(value);
return keys as Keys<T>;
}
@ReVoid
ReVoid / Swap.ts
Last active February 15, 2024 07:25
Swap unions utility
type Swap<T, USubject, UTarget> = T extends USubject ? Exclude<T, USubject> | UTarget : T;
type Whatever = string | null;
// Swap null to undefined
type Swapped = Swap<Whatever, null, undefined>; // string | undefined
// TODO: Make a nested object implementation
@ReVoid
ReVoid / Extendable.ts
Last active October 16, 2023 12:43
How to make an object extendable with any keys
// Extendable regular object
type Extends<T extends object> = T & Record<string, unknown>;
// Extendable object with extendable nested objects
type Extendable<T> = Extends<{ [Key in keyof T]: T[Key] extends object ? Extends<T[Key]> : T[Key] }>;
type Employee = {
name: string,
age: number,
@ReVoid
ReVoid / safe-entity.ts
Last active October 12, 2023 14:20
How to get a totally not nullable object
// Unreliable object 😱
type UnsafePerson = {
name?: string | null,
age?: number | null,
}
// Nested unreliable object 😱😱😱
type UnsafeParent = UnsafePerson & { child: UnsafePerson };
@ReVoid
ReVoid / ui-size-tokens.ts
Created October 4, 2023 09:48
UI Element size tokens example
type SizeToken = 'XSmall' | 'Small' | 'Medium' | 'Large' | 'XLarge';
type ElementSizeVariant<T = string> = T extends SizeToken ? T | 'Medium' : { width: number, height: number };
type ButtonSize = ElementSizeVariant<'Small' | 'Large'>; // 'Small' | 'Large' | 'Medium';
type CardSize = ElementSizeVariant; // { width: number, height: number }
@ReVoid
ReVoid / extract-array-item.ts
Last active April 23, 2024 10:36
Extract array item with conditional types
// with infer keyword
type ArrayItemInfer<T> = T extends Array<infer I> ? I : never;
// or just with regular index type 🙃
type ArrayItemRegular<T extends Array<any>> = T[number];
type People = { firstName: string; lastName: string; }[];
type PersonInfer = ArrayItemInfer<People>; // { firstName: string; lastName: string; } ✅
type Validator<T> = (value: T) => boolean;
class FormInput<T> {
constructor(public value: T, public validators: Validator<T>[]){}
get isValid(): boolean {
return this.validators.every(v => v(this.value));
}
}
@ReVoid
ReVoid / strongly-typed-sort-order.ts
Last active November 27, 2023 11:40
Strongly typed sort order
// Example entity
export interface IPerson {
firstName: string,
lastName: string,
age: number,
}
type SortOrder = 'asc' | 'desc'; // ascending or descending
type OrderByKeys<T> = `${keyof T & string}:${SortOrder}`[]