Files
music-repo/packages/common/src/Brand.ts
2024-12-25 17:26:20 +01:00

36 lines
1.0 KiB
TypeScript

import * as Function from "./Function";
import * as Types from "./Types";
declare const BrandTypeId: unique symbol;
export type BrandTypeId = typeof BrandTypeId;
declare const ConstructorTypeId: unique symbol;
export type ConstructorTypeId = typeof ConstructorTypeId;
export interface Brand<in out K extends string | symbol> {
readonly [BrandTypeId]: {
readonly [k in K]: K;
};
}
export declare namespace Brand {
export interface Constructor<in out A extends Brand<any>> {
readonly [ConstructorTypeId]: ConstructorTypeId;
(args: Brand.Unbranded<A>): A;
}
export type Unbranded<P> = P extends infer Q & Brands<P> ? Q : P;
export type Brands<P> = P extends Brand<any>
? Types.UnionToIntersection<{
[k in keyof P[BrandTypeId]]: k extends string | symbol ? Brand<k> : never
}[keyof P[BrandTypeId]]>
: never;
}
export type Branded<A, K extends string | symbol> = A & Brand<K>;
export const nominal = <A extends Brand<any>>(): Brand.Constructor<A> => {
return Function.identity as Brand.Constructor<A>;
};