UNPKG

runtime-branding

Version:
90 lines (89 loc) 4.42 kB
declare const brand: unique symbol; declare const targetType: unique symbol; export interface Brand<T, B> { [targetType]?: T; [brand]: B; } /** * Branded object type */ export declare type Branded<T, B> = [T & Brand<T, B>][0]; declare type BrandedObject<B extends object, X extends object> = (object extends X ? [Brand<X, B>][0] : [X & Branded<X, B>][0]); /** * Branding function definition */ export interface Branding<B extends object, X extends object = object> extends Brand<X, B> { /** * Brands an object * @param obj the object to brand * @throws Error if the object is already branded */ <T extends X>(obj: T): Branded<T, B>; /** * Asserts this brand for the given object. * @param obj the object to assert brand on * @throws Error when object is not branded. */ assert(obj: object): asserts obj is BrandedObject<B, X>; /** * Checks if the given object has this brand. * @param obj the object to check */ has(obj: object): obj is BrandedObject<B, X>; /** * Refines this branding with a new outer brand. The resulting branding will * be a composition (merge) between the inner and outer brand. * This method is actually a shortcut for createBranding and subsequent merge. * * @param newBrand the new brand that refines the current one * @param callback a callback invoked when object are branded with the refined branding */ refine<N extends object, Y extends X = X>(newBrand: N, callback?: BrandingCallback<N, Y>): Branding<N & B, Y>; /** * Merges the given branding with the current one. * * @param branding the other brand to merge with */ merge<C extends object, Y extends X = X>(branding: Branding<C, Y>): Branding<B & C, Y>; } /** * A branding callback invoked during object branding */ export declare type BrandingCallback<B extends object, T extends object = object> = (obj: T, brand: B) => void; /** * Creates a new brand, identified by the provided branding object. * * @param brandObject An object that represents the brand. The shape of this object should be unique, and symbols may be used as unique keys. * @param callback An optional callback with variable arguments which is invoked during object branding */ export declare function createBranding<B extends object, X extends object = object>(brandObject: B, callback?: BrandingCallback<B, X>): Branding<B, X>; /***********************************************/ export declare type Constructor<T, A extends any[]> = new (...args: A) => T; export declare type TypeId<T> = string | Constructor<T, any[]>; declare const typeSym: unique symbol; export interface TypeBrand<T extends object> { readonly [typeSym]: null; readonly typeId: TypeId<T>; readonly base: Set<TypeBranding<object>>; readonly ancestors: Set<TypeBranding<object>>; } export declare type Typed<T extends object> = Branded<T, TypeBrand<T>>; export interface TypeBranding<T extends object> extends Branding<TypeBrand<T>, T>, TypeBrand<T> { (obj: T): Typed<T>; } export interface BaseTypeBranding<T extends object> { <S extends object>(obj: T extends infer S ? S : never): Branded<any, TypeBrand<S>>; assert: Function; has: Function; refine: Function; merge: Function; } export declare function type<T = void>(typeId: string, ...base: T extends object ? BaseTypeBranding<T>[] : never): T extends object ? TypeBranding<T> : never; export declare function type<T extends object>(typeId: Constructor<T, any[]>, ...base: BaseTypeBranding<T>[]): TypeBranding<T>; export declare function typeOf<T extends Constructor<any, any>>(obj: T): typeof obj extends Constructor<infer X, any[]> ? X extends object ? TypeBranding<X> : never : never; export declare function typeOf<T>(obj: T): typeof obj extends InstanceType<Constructor<infer X, any>> ? X extends object ? TypeBranding<X> : never : TypeBranding<object>; export declare function typeOf<T extends object>(obj: T): T extends Typed<infer X> ? TypeBranding<X> : TypeBranding<object>; export declare function isTyped(obj: object): boolean; export declare function assertType<X, T extends Object>(type: TypeBranding<T>, obj: X): asserts obj is Typed<T & X>; export declare function isTypeBranding(fn: any): fn is TypeBranding<object>; export {};