In TypeScript, the native type system does not directly support representing non-negative integers separately from other numeric types because TypeScript's base type is only number, which encompasses integers, floating-point numbers, positive numbers, and negative numbers. However, we can use certain techniques to ensure that variables remain non-negative integers at runtime.
Method 1: Type Alias and Runtime Checks
Although TypeScript cannot enforce non-negative integers at compile time, we can define a type alias to semantically represent this intent and enforce checks at runtime using functions.
typescripttype NonNegativeInteger = number; function asNonNegativeInteger(x: any): NonNegativeInteger { if (typeof x !== 'number' || !Number.isInteger(x) || x < 0) { throw new Error("Value must be a non-negative integer"); } return x; } // Wrap with function to ensure type safety let age: NonNegativeInteger = asNonNegativeInteger(25); let invalidAge = asNonNegativeInteger(-5); // This will throw an error
Method 2: Using Type Guards
We can define a type guard to help TypeScript understand whether a variable is a non-negative integer.
typescriptfunction isNonNegativeInteger(x: number): x is NonNegativeInteger { return Number.isInteger(x) && x >= 0; } function processAge(age: number) { if (isNonNegativeInteger(age)) { console.log(`Valid age: ${age}`); } else { console.log("Invalid age. Age must be a non-negative integer."); } } processAge(30); // Output: Valid age: 30 processAge(-1); // Output: Invalid age. Age must be a non-negative integer.
Method 3: Using Additional Libraries
There are some TypeScript extension libraries, such as io-ts and runtypes, that can perform runtime type checks while integrating with the type system.
typescriptimport * as t from 'io-ts'; const NonNegativeInteger = t.brand( t.number, (n): n is t.Branded<number, { readonly NonNegativeInteger: unique symbol }> => Number.isInteger(n) && n >= 0, 'NonNegativeInteger' ); const decodeAge = NonNegativeInteger.decode(30); if (decodeAge._tag === 'Right') { console.log(`Valid age: ${decodeAge.right}`); } else { console.log("Invalid age."); }
Summary
Although TypeScript cannot directly enforce non-negative integers at compile time, we can use runtime checks, type guards, and third-party libraries to ensure this. These methods help enhance safety and robustness in development.