An educational pure functional programming library in TypeScript
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add prelude/brand module with Branded and Refined types

+46
+45
src/prelude/brand.ts
··· 1 + import type { Option } from "./option" 2 + import { some, none } from "./option" 3 + 4 + // Brand symbol for nominal typing 5 + declare const __brand: unique symbol 6 + type Brand<B> = { [__brand]: B } 7 + 8 + /** 9 + * Branded type - creates distinct types from primitives. 10 + * Example: type UserId = Branded<string, "UserId"> 11 + */ 12 + export type Branded<T, B> = T & Brand<B> 13 + 14 + /** 15 + * Create a branded value (unchecked). 16 + */ 17 + export const brand = <T, B>(value: T): Branded<T, B> => value as Branded<T, B> 18 + 19 + // Refinement symbol 20 + declare const __refinement: unique symbol 21 + type Refinement<R> = { [__refinement]: R } 22 + 23 + /** 24 + * Refined type - branded with validation guarantee. 25 + */ 26 + export type Refined<T, R> = T & Refinement<R> 27 + 28 + /** 29 + * Create a refinement validator. 30 + * Returns Option to avoid throwing on invalid input. 31 + */ 32 + export const refine = <T, R>(predicate: (value: T) => boolean) => 33 + (value: T): Option<Refined<T, R>> => 34 + predicate(value) ? some(value as Refined<T, R>) : none 35 + 36 + // Common numeric refinements 37 + export type Positive = "Positive" 38 + export type NonNegative = "NonNegative" 39 + export type Normalized = "Normalized" 40 + export type Integer = "Integer" 41 + 42 + export const positive = refine<number, Positive>(x => x > 0) 43 + export const nonNegative = refine<number, NonNegative>(x => x >= 0) 44 + export const normalized = refine<number, Normalized>(x => x >= 0 && x <= 1) 45 + export const integer = refine<number, Integer>(x => Number.isInteger(x))
+1
src/prelude/index.ts
··· 2 2 export * from "./result" 3 3 export * from "./option" 4 4 export * from "./match" 5 + export * from "./brand"