36 lines
1.0 KiB
TypeScript
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>;
|
|
};
|