@apexo/type
v0.0.3
Published
@apexo/type is a small, zero-dependency library that gives you easy and reliable type checks in JavaScript and TypeScript.
Maintainers
Readme
@apexo/type
Ever spent hours writing validation code, only to realize you're doing the same thing in every function? Or maybe you've let AI generate it for you, and now your bundle is bloated with duplicate boilerplate?
@apexo/type is a small library that does all your type checking for you. Why do you need it? Because JavaScript's type checking is weird:
typeof nullsays it's an"object"(but it's not!)typeof []says it's an"object"(arrays need different checks)typeof NaNsays it's a"number"(even though NaN means "Not a Number")- No easy way to check for empty values or loops in objects
You could write all the checks yourself:
function processUser(data) {
if (data === null || data === undefined) {
throw new Error('Data is required');
}
if (typeof data !== 'object' || Array.isArray(data)) {
throw new Error('Data must be an object');
}
if (typeof data.name !== 'string' || data.name.trim() === '') {
throw new Error('Name must be a non-empty string');
}
if (typeof data.age !== 'number' || isNaN(data.age) || data.age < 0) {
throw new Error('Age must be a positive number');
}
// Finally, your actual logic...
}Or you could use @apexo/type and get it done in 3 lines:
import { isObject, isNotEmpty, isPositive } from '@apexo/type';
function processUser(data) {
if (!isObject(data)) throw new Error('Data must be an object');
if (!isNotEmpty(data.name)) throw new Error('Name is required');
if (!isPositive(data.age)) throw new Error('Age must be positive');
// Your actual logic, front and center
}Why would I want that?
JavaScript's typeof operator falls short in many real-world scenarios:
typeof null === 'object'(it's not!)typeof [] === 'object'(arrays need special handling)- No way to check for
NaN, empty values, or validate complex structures
@apexo/type solves these problems by providing:
- Runtime Safety: Validate data from APIs, user input, or any untrusted source before processing
- TypeScript Integration: Type guards automatically narrow types in your code, giving you full IntelliSense support
- Readable Code: Replace verbose checks like
if (value !== null && value !== undefined && typeof value === 'string' && value.trim() !== '')withif (isNotEmpty(value)) - Edge Case Handling: Correctly handles tricky JavaScript edge cases (
null,undefined,NaN,Symbol,BigInt, circular references)
How little is it?
- ~12KB minified (entire library)
- Tree-shakeable: Only bundle what you use. Import just
isString? Your bundle won't include date validators or circular reference detection - Zero dependencies: No bloat from external packages
- Side-effect free: Marked as
"sideEffects": falsefor optimal tree-shaking
How do I install it?
npm install @apexo/typeOr with your preferred package manager:
pnpm add @apexo/type
yarn add @apexo/typeHow do I use it?
Basic Type Guards
Type guards return a boolean and automatically narrow TypeScript types:
import { isString, isNumber, isArray } from '@apexo/type';
function process(input: unknown) {
if (isString(input)) {
// TypeScript knows input is string here
console.log(input.toUpperCase());
}
if (isArray(input)) {
// TypeScript knows input is any[] here
console.log(input.length);
}
}Validating Values
Beyond type checking, validate specific properties:
import { isPositive, isEven, isFutureDate, isEmpty } from '@apexo/type';
isPositive(10); // true
isEven(7); // false
isEmpty(' '); // true
isFutureDate(new Date('2050-01-01')); // trueAdvanced Utilities
import { whatTypeOf, hasCircularReference } from '@apexo/type';
whatTypeOf(null); // "null" (not "object"!)
whatTypeOf([]); // "array"
whatTypeOf(new Date()); // "date"
const obj: any = {};
obj.self = obj;
hasCircularReference(obj); // { hasCircular: true, path: "root.self -> root" }Loading the library
ES Modules (Recommended)
import { isString, isObject } from '@apexo/type';CommonJS
const { isString, isObject } = require('@apexo/type');TypeScript
The library is written in TypeScript and includes full type definitions out of the box.
Are there TypeScript definitions?
Yes! The library is TypeScript-first and includes complete type definitions. All type guards use TypeScript's type predicate syntax (value is Type), providing automatic type narrowing:
function example(input: unknown) {
if (isString(input)) {
// input is automatically typed as 'string'
input.toLowerCase(); // ✅ TypeScript knows this is safe
}
}Where can I use it?
Everywhere JavaScript runs:
- ✅ Node.js (v14+)
- ✅ Browsers (Modern browsers, IE11+ with polyfills)
- ✅ Deno
- ✅ Bun
- ✅ Edge Functions (Vercel, Cloudflare Workers, etc.)
- ✅ React Native
The library has zero dependencies and uses only standard JavaScript features, making it universally compatible.
API Reference
Primitives
isString(value)- Checks if value is a stringisNumber(value)- Checks if value is a number (and not NaN)isNumberStr(value)- Checks if value is a number or numeric stringisBoolean(value)- Checks if value is a booleanisNil(value)- Checks if value isnullorundefinedisNull(value)- Checks if value isnullisUndefined(value)- Checks if value isundefinedisBigInt(value)- Checks if value is a BigIntisSymbol(value)- Checks if value is a SymbolisPrimitive(value)- Checks if value is a primitive type
Objects & Structures
isObject(value)- Checks if value is a non-null object (excluding arrays)isPlainObject(value)- Checks if value is a plain object ({}ornew Object())isArray(value)- Checks if value is an arrayisArrayLike(value)- Checks if value is array-like (has length property)isFunction(value)- Checks if value is a functionisClass(value)- Checks if value is a class constructorisIterable(value)- Checks if value is iterableisAsyncIterable(value)- Checks if value is async iterableisGeneratorFunction(value)- Checks if value is a generator functionisWindow(value)- Checks if value is a Window object
Advanced Types
isPromise(value)- Checks if value is a PromiseisMap(value)- Checks if value is a MapisSet(value)- Checks if value is a SetisWeakMap(value)- Checks if value is a WeakMapisWeakSet(value)- Checks if value is a WeakSetisRegExp(value)- Checks if value is a RegExpisDate(value)- Checks if value is a Date objectisError(value)- Checks if value is an ErrorisTypeError(value)- Checks if value is a TypeErrorisReferenceError(value)- Checks if value is a ReferenceErrorisSyntaxError(value)- Checks if value is a SyntaxErrorisRangeError(value)- Checks if value is a RangeErrorisURIError(value)- Checks if value is a URIErrorisEvalError(value)- Checks if value is an EvalErrorisAggregateError(value)- Checks if value is an AggregateErrorisBuffer(value)- Checks if value is a Buffer (Node.js) or ArrayBuffer/ViewisJson(value)- Checks if value is a valid JSON string
Empty Checks
isEmpty(value)- Checks if value is empty (null, undefined, empty string/array/object)isNotEmpty(value)- Inverse ofisEmptyisEmptyStr(value)- Checks if value is an empty string (or whitespace only)isEmptyArr(value)- Checks if value is an empty arrayisEmptyObj(value)- Checks if value is an empty object
Number Validators
isFiniteNumber(value)- Checks if value is a finite numberisInteger(value)- Checks if value is an integerisFloat(value)- Checks if value is a floatisSafeInteger(value)- Checks if value is a safe integerisPositive(value)- Checks if value is > 0isNegative(value)- Checks if value is < 0isZero(value)- Checks if value is 0isEven(value)- Checks if value is evenisOdd(value)- Checks if value is oddisPrime(value)- Checks if value is a prime numberisInRange(value, min, max)- Checks if value is within [min, max]isBetween(value, min, max)- Checks if value is strictly between (min, max)
Date Validators
isValidDate(value)- Checks if value is a valid Date (not Invalid Date)isStrictDate(value)- Alias forisValidDateisFutureDate(date)- Checks if date is in the futureisPastDate(date)- Checks if date is in the pastisToday(date)- Checks if date is todayisSameDay(a, b)- Checks if two dates are on the same dayisLeapYear(year)- Checks if year is a leap yearisISODateString(value)- Checks if value is an ISO 8601 date stringisValidISODateOnly(value)- Checks if value is a valid YYYY-MM-DD stringisValidTimeString(value)- Checks if value is a valid time string (HH:mm)isDateTimeString(value)- Checks if value is a valid datetime stringisTimestamp(value)- Checks if value is a valid timestampisDateLike(value)- Checks if value can be converted to a valid DateisForwardTime(date, offset?)- Checks if date is after now + offsetisBackwardTime(date, offset?)- Checks if date is before now - offset
Utilities
whatTypeOf(value)- Returns a specific type string (e.g., "array", "date", "null")hasCircularReference(obj)- Detects circular references in objects/arrays
Architecture
The library is organized for maximum tree-shaking efficiency:
src/
├── guards/ # Type guards (value is Type)
│ ├── primitives.ts # Basic types
│ ├── objects.ts # Object structures
│ ├── advanced.ts # Promises, Maps, Sets
│ ├── errors.ts # Error types
│ └── empty.ts # Empty checks
├── validators/ # Value validators (boolean)
│ ├── number.ts # Numeric validations
│ └── date.ts # Date validations
└── utils/ # Helper utilities
├── type-of.ts # Enhanced typeof
└── circular-ref.ts # Circular reference detectionThis structure allows bundlers to eliminate entire categories of checks if you don't use them.
License
Repository
https://github.com/bytetologic/apexo.js/tree/main/packages/type
