Skip to main content
Module

x/evt/tools/typeSafety/id.ts

💧EventEmitter's typesafe replacement
Go to Latest
File

/** * The identity function. * * Help to build an object of type T. * Better than using 'as T' as there is no type safety loss. * * - Used as continence for enabling type inference. * Example: * * type Circle = { * type: "CIRCLE"; * radius: number; * }; * * type Square = { * type: "SQUARE"; * side: number; * }; * type Shape= Circle | Square; * * declare function f(shape: Shape): void; * * f(id<Circle>({ "type": "CIRCLE", "radius": 33 }); <== We have auto completion to instantiate circle. * * - Used to loosen the type restriction without saying "trust me" to the compiler. * declare const x: Set<readonly ["FOO"]>; * declare function f(s: Set<string[]>): void; * f(id<Set<any>>(x)); * * Example: * declare const x: Set<readonly [ "FOO" ]>; * declare f(x: Set<string[]>): void; * id(x as Set<["FOO"]>); <== trust me it's readonly! * f(id<Set<any>>(x)); <== we acknowledge that we are out of the safe zone. */export const id = <T>(x: T) => x;
/** * Ensure that a that a specific type that we are declaring extends a more generic type * * Use case example 1: * * type MyObject = { * p1: string; * p2: string; * a: string; * b: string; * }; * * We want to define a type that consist in an union of * all the property name that are letters: * * type AlphabeticalKeys = Id<keyof MyObject, "a" | "b">; * * Here AlphabeticalKeys is "a" | "b" but it's better than * simply writing it explicitly as we get autocompletion * and we can't include a property name that does not exist on MyObject. * * Use case example 2: * * We want to declare object type that only take string or number * as key value: * * export type MyObject = Id<Record<string, string | number>, { * p1: string; * p2: number; * }>; * * If later on someone adds "p3": string[] he will get a type error. * */export type Id<Generic, Specific extends Generic> = Specific;