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 data/guards module with type guards and combinators

+77
+70
src/data/guards.ts
··· 1 + /** 2 + * Type guards and combinators for runtime type checking. 3 + * 4 + * @module data/guards 5 + */ 6 + 7 + // ============================================================================= 8 + // Primitive Type Guards 9 + // ============================================================================= 10 + 11 + /** Type guard for string values */ 12 + export const isString = (x: unknown): x is string => typeof x === "string" 13 + 14 + /** Type guard for number values */ 15 + export const isNumber = (x: unknown): x is number => typeof x === "number" 16 + 17 + /** Type guard for boolean values */ 18 + export const isBoolean = (x: unknown): x is boolean => typeof x === "boolean" 19 + 20 + /** Type guard for non-null object values */ 21 + export const isObject = (x: unknown): x is object => typeof x === "object" && x !== null 22 + 23 + /** Type guard for array values */ 24 + export const isArray = (x: unknown): x is unknown[] => Array.isArray(x) 25 + 26 + // ============================================================================= 27 + // Number Property Guards 28 + // ============================================================================= 29 + 30 + /** Type guard for positive numbers (x > 0) */ 31 + export const isPositive = (x: unknown): x is number => isNumber(x) && x > 0 32 + 33 + /** Type guard for negative numbers (x < 0) */ 34 + export const isNegative = (x: unknown): x is number => isNumber(x) && x < 0 35 + 36 + /** Type guard for integer numbers */ 37 + export const isInteger = (x: unknown): x is number => isNumber(x) && Number.isInteger(x) 38 + 39 + /** Type guard for finite numbers (excludes Infinity and NaN) */ 40 + export const isFiniteNumber = (x: unknown): x is number => isNumber(x) && Number.isFinite(x) 41 + 42 + // ============================================================================= 43 + // Guard Combinators 44 + // ============================================================================= 45 + 46 + /** Combines two guards with logical AND - both must pass */ 47 + export const and = <A, B extends A, C extends B>( 48 + g1: (x: A) => x is B, 49 + g2: (x: B) => x is C 50 + ) => (x: A): x is C => g1(x) && g2(x) 51 + 52 + /** Combines two guards with logical OR - either must pass */ 53 + export const or = <A, B extends A, C extends A>( 54 + g1: (x: A) => x is B, 55 + g2: (x: A) => x is C 56 + ) => (x: A): x is B | C => g1(x) || g2(x) 57 + 58 + /** Negates a guard */ 59 + export const not = <A, B extends A>( 60 + guard: (x: A) => x is B 61 + ) => (x: A): x is Exclude<A, B> => !guard(x) 62 + 63 + // ============================================================================= 64 + // Property Guards 65 + // ============================================================================= 66 + 67 + /** Creates a guard that checks if an object has a specific property */ 68 + export const hasProperty = <K extends string>(key: K) => 69 + <T>(x: T): x is T & Record<K, unknown> => 70 + isObject(x) && key in x
+7
src/data/index.ts
··· 1 + /** 2 + * Data module - Type guards and combinators. 3 + * 4 + * @module data 5 + */ 6 + 7 + export * from "./guards"