diff --git a/src/custom-types.ts b/src/custom-types.ts index e0e35a0..979f817 100644 --- a/src/custom-types.ts +++ b/src/custom-types.ts @@ -140,3 +140,12 @@ export interface CoordsValues { startSubjPixels?: number; endSubjPixels?: number; } + +export type posnumber = number & { readonly _positive: unique symbol }; + +export function toPositiveNumber(value: number): posnumber { + if (value < 0) { + throw new Error(`${value} is not a positive number`); + } + return value as posnumber; +} diff --git a/tests/custom-types.test.ts b/tests/custom-types.test.ts index 10496b7..1cdd697 100644 --- a/tests/custom-types.test.ts +++ b/tests/custom-types.test.ts @@ -12,6 +12,8 @@ import { textDefaults, rectDefaults, lineDefaults, + toPositiveNumber, + posnumber, } from '../src/custom-types'; // Test suite for ColorSchemeEnum @@ -112,3 +114,24 @@ describe('CoordsValues Interface', () => { expect(coords.end).toBe(90); }); }); + +describe('toPositiveNumber', () => { + it('should return a posnumber for a positive input', () => { + const value = 5; + const result: posnumber = toPositiveNumber(value); + expect(result).toBe(value); // Check if the returned value is the input itself + expect(typeof result).toBe('number'); // Ensure the type is still a number + }); + + it('should return a posnumber for zero', () => { + const value = 0; + const result: posnumber = toPositiveNumber(value); + expect(result).toBe(value); // Check if the returned value is zero + expect(typeof result).toBe('number'); // Ensure the type is still a number + }); + + it('should throw an error for a negative input', () => { + const value = -3; + expect(() => toPositiveNumber(value)).toThrow(`${value} is not a positive number`); + }); +});