@knighttower/type-check
v5.17.0
Published
typeCheck JS
Maintainers
Readme
typeCheck JS
A simple type checker for JavaScript
typeCheck JS is a JavaScript library designed for fast and efficient type checking. Inspired by gkz/type-check, this library aims to overcome the limitations and complexities associated with TypeScript. It offers a lightweight, memory-efficient, and easy-to-use solution for both basic and complex type-checking requirements.
📚 Table of Contents
- Installation
- Quick Start
- Why typeCheck JS?
- What does it solve?
- API Reference
- Type Patterns
- Examples
- Performance
- Tests
🔧 Installation
Via npm
npm i @knighttower/type-check
# or
yarn add @knighttower/type-check
# or
# as part of a monorepo
npm i knighttower
# then import {typeCheck} from 'knighttower/type-check';In the Browser
<script src="https://cdn.jsdelivr.net/npm/@knighttower/type-check@latest/dist/browser/typeCheck.min.js"></script>
<!-- OR as ESM -->
<script type="module">
import { typeCheck } from 'https://esm.run/@knighttower/type-check@latest/index.js';
</script>Note: by default the library is ESM, but other builds are available in the dist folder (CJS, UMD, IIFE, etc.)
📦 Files
| File | Size | | ---------------- | ----- | | /typeCheck.js | 8 KiB | | /typeCheck.js.br | 3 KiB | | /typeCheck.js.gz | 3 KiB |
You can also import from the /src folder for ESM + JS next, or from /index.js and /index.cjs.js as needed.
💡 Why typeCheck JS?
- Lightweight: Adds minimal overhead to your project (~6k GZip).
- Fast Performance: Micro Optimized for runtime operations.
- Ease of Use: Simple API and pattern syntax.
- No Compile Step: Works directly in vanilla JS.
- Complementary: Works alongside TypeScript for runtime enforcement.
- Supports: callbacks, custom messages, logs, and error throwing.
- Flexible: Supports piped types, optional keys, wildcard matching.
- Extensible: You can register custom test types.
- Fully Tested: Using Vitest for all cases.
- Documented: Full JSDoc for all major methods and patterns.
❓ What does it solve?
- Enforces runtime type checking in production builds.
- Helps validate user inputs, API data, and 3rd-party sources.
- Avoids unnecessary adoption of TypeScript for small apps.
- Solves the issue of type loss in runtime JS after TS transpilation.
- Works directly in browsers or legacy JS environments.
- Helps library authors enforce expected types at runtime.
🚫 What it doesn't solve
- It doesn't stop bad programming decisions.
📋 API Reference
typeCheck()
Basic type validation with strict error throwing
typeCheck(valueToTest, typeExpression, options?)Parameters:
valueToTest(any) - The value to validatetypeExpression(string) - The type pattern to match againstoptions(object|string, optional) - Configuration options
Returns: true on success, throws error on failure
Examples:
import { typeCheck } from '@knighttower/type-check';
// Basic types
typeCheck(123, 'number'); // ✅ passes
typeCheck('hello', 'string'); // ✅ passes
typeCheck(true, 'boolean'); // ✅ passes
// Will throw errors
typeCheck('hello', 'number'); // ❌ throws TypeError
typeCheck(123, 'string'); // ❌ throws TypeError
// Optional types
typeCheck(null, 'string?'); // ✅ passes (null/undefined allowed)
typeCheck(undefined, 'number?'); // ✅ passes
typeCheck('hello', 'string?'); // ✅ passes
// Union types
typeCheck(123, 'string|number'); // ✅ passes (either type allowed)
typeCheck('hi', 'string|number'); // ✅ passes
// Arrays
typeCheck([1, 2, 3], '[number]'); // ✅ all elements are numbers
typeCheck([1, 'hi', 3], '[number, string, number]'); // ✅ exact positions match
// Objects
typeCheck({ name: 'John', age: 30 }, '{name: string, age: number}'); // ✅
typeCheck({ x: 1, y: 2 }, '{any: number}'); // ✅ all values are numbers
// Custom error message
typeCheck(123, 'string', { error: 'Value must be a string!' });
// With callback for additional validation
typeCheck({ id: 1 }, '{id: number}', (result) => {
console.log('Validation result:', result);
});_typeCheck()
Advanced type validation with chainable methods
_typeCheck(valueToTest, typeExpression, options?)Parameters:
- Same as
typeCheck()but returns a chainable object instead of throwing immediately
Chainable Methods:
.test()- Returns boolean result.bool- Direct boolean property access.log()- Logs validation details to console.fail()- Throws error if validation fails.return()- Returns the original value
Examples:
import { _typeCheck } from '@knighttower/type-check';
// Get boolean result without throwing
const isValid = _typeCheck(123, 'number').test(); // true
// Chain methods for debugging
_typeCheck({ name: 'John' }, '{name: string}')
.log() // logs validation details
.fail() // throws if invalid
.return(); // returns original value
// Conditional validation
if (_typeCheck(userInput, 'string').test()) {
// Safe to use userInput as string
console.log(userInput.toUpperCase());
}
// Direct boolean access
const isNumber = _typeCheck(value, 'number').bool;
// Custom options
_typeCheck(data, 'object', {
log: true, // auto-log results
fail: true, // auto-fail on error
callback: (result) => {
console.log('Custom validation logic', result);
}
});validType()
Simple boolean validation without throwing errors
validType(valueToTest, typeExpression)Parameters:
valueToTest(any) - The value to validatetypeExpression(string) - The type pattern to match against
Returns: boolean - true if valid, false if invalid
Examples:
import { validType } from '@knighttower/type-check';
// Safe validation for conditional logic
if (validType(userInput, 'string')) {
// userInput is definitely a string
processString(userInput);
} else {
console.log('Invalid input type');
}
// Form validation
function validateForm(data) {
const errors = [];
if (!validType(data.email, 'string')) {
errors.push('Email must be a string');
}
if (!validType(data.age, 'number')) {
errors.push('Age must be a number');
}
if (!validType(data.preferences, '{theme: string, notifications: boolean}')) {
errors.push('Invalid preferences object');
}
return errors;
}
// API response validation
function handleApiResponse(response) {
if (validType(response, '{data: array, status: number}')) {
return response.data;
}
throw new Error('Invalid API response format');
}_tc()
Function wrapper with input parameter validation
_tc(typeExpressions, functionToWrap, options?)Parameters:
typeExpressions(array) - Array of type patterns for each parameterfunctionToWrap(function) - The function to wrap with validationoptions(object, optional) - Configuration options
Returns: Wrapped function that validates inputs before execution
Examples:
import { _tc } from '@knighttower/type-check';
// Basic function wrapping
const greet = _tc(['string'], function(name) {
return `Hello, ${name}!`;
});
greet('Alice'); // ✅ returns "Hello, Alice!"
greet(123); // ❌ throws error
// Multiple parameters
const calculate = _tc(['number', 'number', 'string'], function(a, b, operation) {
switch(operation) {
case 'add': return a + b;
case 'multiply': return a * b;
default: return 0;
}
});
calculate(5, 3, 'add'); // ✅ returns 8
calculate('5', 3, 'add'); // ❌ throws error
// With options
const processUser = _tc(
['{name: string, age: number}'],
function(user) {
return `Processing user: ${user.name}, age: ${user.age}`;
},
{
log: false, // don't log by default
fail: true, // throw errors (default)
error: 'Invalid user object provided'
}
);
// Arrow functions
const multiply = _tc(['number', 'number'], (a, b) => a * b);
// Complex type validation
const createOrder = _tc(
['{items: [object], total: number, customer: {id: number, email: string}}'],
function(orderData) {
// Function implementation
return { orderId: Date.now(), ...orderData };
}
);_tcx()
Function wrapper with input AND output validation
_tcx(typeExpressions, functionToWrap, options?)Parameters:
typeExpressions(array) - Array of type patterns for each parameterfunctionToWrap(function) - The function to wrap with validationoptions(object, optional) - Configuration options includingvalidOutput
Chainable Methods:
.log()- Log validation details.fail()- Throw error if validation fails.return()- Get the return value.test()- Get boolean validation result
Examples:
import { _tcx } from '@knighttower/type-check';
// Function with return value validation
const getLength = _tcx(
['string'],
(str) => str.length,
{ validOutput: 'number' }
);
const length = getLength('hello').return(); // 5
getLength(123); // ❌ throws (invalid input)
// Complex example with chaining
const processData = _tcx(
['{data: array}'],
function(input) {
return {
processed: true,
count: input.data.length,
summary: 'Data processed successfully'
};
},
{
validOutput: '{processed: boolean, count: number, summary: string}',
log: false
}
);
const result = processData({ data: [1, 2, 3] })
.log() // logs validation details
.fail() // throws if validation fails
.return(); // returns the actual result
// Mathematical operations with validation
const divide = _tcx(
['number', 'number'],
(a, b) => {
if (b === 0) throw new Error('Division by zero');
return a / b;
},
{ validOutput: 'number' }
);
const result = divide(10, 2).return(); // 5
// API function wrapper
const fetchUser = _tcx(
['number'],
async function(userId) {
const response = await fetch(`/api/users/${userId}`);
return await response.json();
},
{
validOutput: '{id: number, name: string, email: string}',
error: 'Invalid user data received from API'
}
);
// Usage with async
const user = await fetchUser(123).fail().return();addTypeTest()
Register custom type validators
addTypeTest(name, validationFunction)Parameters:
name(string) - Name of the custom typevalidationFunction(function) - Function that returns boolean for validation
Returns: true if added successfully, error message if name already exists
Examples:
import { addTypeTest, typeCheck } from '@knighttower/type-check';
// Custom validator for even numbers
addTypeTest('even', (value) => {
return typeof value === 'number' && value % 2 === 0;
});
typeCheck(4, 'even'); // ✅ passes
typeCheck(3, 'even'); // ❌ throws
typeCheck([2, 4, 6], '[even]'); // ✅ all even numbers
// Email validation
addTypeTest('email', (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return typeof value === 'string' && emailRegex.test(value);
});
typeCheck('[email protected]', 'email'); // ✅
typeCheck('invalid-email', 'email'); // ❌
// Non-empty string
addTypeTest('nonEmptyString', (value) => {
return typeof value === 'string' && value.trim().length > 0;
});
// Positive number
addTypeTest('positive', (value) => {
return typeof value === 'number' && value > 0;
});
// Use in complex validations
typeCheck({
name: 'John Doe',
email: '[email protected]',
age: 25
}, '{name: nonEmptyString, email: email, age: positive}');
// URL validation
addTypeTest('url', (value) => {
try {
new URL(value);
return true;
} catch {
return false;
}
});
// Date string validation
addTypeTest('dateString', (value) => {
return typeof value === 'string' && !isNaN(Date.parse(value));
});
// Use custom types in arrays and objects
typeCheck(['2023-01-01', '2023-12-31'], '[dateString]');
typeCheck({
homepage: 'https://example.com',
created: '2023-01-01'
}, '{homepage: url, created: dateString}');🔤 Type Patterns
🚀 Usage
import { typeCheck } from '@knighttower/type-check';
typeCheck(123, 'number'); // ✅
typeCheck('hello', 'number'); // ❌ throws👉 IMPORTANT
The API for the direct typeCheck() function uses the familiar value, type order:
typeCheck(valueToTest, typeExpression);⚡ Quick Start
typeCheck('hello', 'string'); // ✅
typeCheck([1, 2], '[number]'); // ✅
typeCheck({ x: 1 }, '{x: number}'); // ✅🧪 Examples
// With optional arguments
typeCheck(null, 'string?'); // true
typeCheck(undefined, 'string?'); // true
typeCheck('str', 'string?'); // true
typeCheck(null, 'string?', options);
typeCheck(null, 'string?', 'error message'); // throws error with custom message
// Piped
typeCheck(1, 'string | number'); // true
typeCheck('str', 'string | int'); // true
// Array
typeCheck([1], '[number]'); // true
typeCheck([1, 2, 3], '[number]'); // true
typeCheck([1, 3, null], '[number, number, string]'); // Matches the index of the array
// Object
typeCheck({ x: 'string', y: 10 }, '{x: string, y: number}'); // true
typeCheck({ x: 'string', y: 'str' }, '{x: string, y: number}'); // false
typeCheck({ x: 'string', y: 10, z: 10 }, '{x: string, y: number}'); // false
typeCheck({ x: 2, y: 10 }, '{x: string|number, y: number}'); // true
// Object with optional keys
typeCheck({ x: 'string', y: 10 }, '{x: string, y: number, z?: number}'); // true
// Object with specific keys to test all other ignore
typeCheck({ x: 'string', y: 10, z: 20 }, '{x: string, y: number, ...}'); // true
// Object with specific keys to test all test a common test method
typeCheck({ x: 'string', y: 10, z: 20 }, '{x: string, y: number, any: number}'); // true
// Nested arrays or objects
typeCheck([1, { x: 'string', y: 10, z: 20 }, 3], '[number, {any: number, x: string}, number]'); // true
// With callback functions
_typeCheck({ x: 'string', y: 10 }, '{y: number, x: string}', ($this) => {
console.log('__testLogHere__', $this);
}).log();
//with log function to see the results in the console
_typeCheck({ x: 'string', y: 10 }, '{y: number, x: string}').log();
//with fail function to stop execution if the type is not correct
_typeCheck({ x: 'string', y: 10 }, '{y: number, x: string}').fail();
// Basic
_typeCheck(1, 'number').test(); // true and returns a boolean
_typeCheck('1', 'number').fail().test(); // false and throw exception
_typeCheck('str', 'string').log().test(); // true and logs the test results🧰 Advanced API
_typeCheck(valueToTest, testExpression, options?)
/**
* @param {any} valueToTest
* @param {string} testExpression (see below for patterns)
* @param {function} callback optional
* @return {object} typeCheck Object with chainable methods
* @see testUnit for more examples and test cases
*/
_typeCheck(valueToTest, testExpression, options);
// Methods:
_typeCheck(..).test(); // returns true or false, helpful for if statements or other logic
_typeCheck(..).bool; // same as 'test()', returns true or false, but more direct in the intent
_typeCheck(..).log(); // logs the results, helpful for debugging
_typeCheck(..).fail(); // throws exception if the test fails. Strict validation enforcement
_typeCheck(..).return(); // returns the valueToTest (non chainable with 'test' method)
//Chain methods
_typeCheck(..).log().test();
_typeCheck(..).fail().test();
_typeCheck(..).log().fail().return();
// Options
{
log: true,
fail: true,
callback: function,
error: string
}validType(valueToTest, testExpression, options);
Alias function for _typeCheck(valueToTest, testExpression, options); It does not do strict validation, but returns a boolean instead of throwing an exception.
function yourExistingFunction(valueToTest) {
validType(valueToTest, 'string');
// your code here
}_tc(testExpression, __function, options);
- Wrapper for "typeCheck" (_tc) to implement functions with type checking.
- Does not validate the "return value" of the function. (use "_tcx" instead).
- lightweight, fast and easy to implement.
- Does take options.
- Does return the 'return value' of the function for each instance.
- Note: all test expressions are passed as 'array' like because args are 1 or more.
const greet = _tc(['string'], function (name) {
return `Hello, ${name}`;
});
greet('Alice'); // ✅
greet(123); // ❌ throwsconst logData = _tc(['number', 'boolean'], (id, active) => {
return `${id}:${active}`;
});
logData(5, true); // ✅
logData('5', true); // ❌ throwsconst yourCoolFunction = _tc(['number', 'string'], function (myVar, theOtherVar) {
// .. your code here
});
yourCoolFunction(44.5, 'hello'); // validates that both are numbers
// Options
{
log: false, // default false. Same as method log()
fail: false, // default true. Same as method fail()
error: string, // custom error message
}_tcx(testExpression, __function, options);
- Wrapper for "typeCheck" with 'return X' (_tcx) to implement functions with type checking
- Validates the "return value" of the function.
- Offers more options.
- Has built in features for all its instances.
- Does take options.
- slighty slower than "_tc", but more robust for full type checking.
- Does not return the 'return value' as '_tc', instead it has to be explicitly called with '.return()'.
- Note: all test expressions are passed as 'array' like because args are 1 or more.
const yourCoolFunction = _tcx(['number', 'string'], function (myVar, theOtherVar) {
// .. your code here
return 'hello';
}, {validOutput: 'string'});
yourCoolFunction(44.5, 'hello'); // validates that arg1 is 'number' and arg2 is 'string' and that the return value is a string
// Options
{
validOutput: 'testExpression', // default null. Same as method log()
log: false, // default false. Same as method log()
fail: false, // default true. Same as method fail()
error: string, // custom error message
}
// Built in features
yourCoolFunction(...).log(); // logs the results, helpful for debugging individual functions
yourCoolFunction(...).fail(); // throws exception if the test fails. Strict validation enforcement
yourCoolFunction(...).return(); // returns the 'return value' (non chainable with 'test' method)
yourCoolFunction(...).test(); // returns true or false, helpful for if statements or other logic
yourCoolFunction(...).fail().return(); // if the test fails, it will throw exception and if passes returns the 'return value'const getLength = _tcx(['string'], (str) => str.length, {
validOutput: 'number',
});
getLength('hello').log().return(); // ✅ 5const sum = _tcx(['number', 'number'], (a, b) => a + b, {
validOutput: 'number',
});
sum(10, 5).log().fail().return(); // ✅ 15addTypeTest(name, fn)
Registers a custom type function globally.
addTypeTest('even', (x) => typeof x === 'number' && x % 2 === 0);
typeCheck(2, 'even'); // ✅
typeCheck(3, 'even'); // ❌ throws
typeCheck([2, 4, 6], '[even]'); // ✅
typeCheck({ count: 8 }, '{count: even}'); // ✅addTypeTest('nonEmptyString', (val) =>
typeof val === 'string' && val.trim().length > 0
);
typeCheck('hello', 'nonEmptyString'); // ✅
typeCheck('', 'nonEmptyString'); // ❌🔤 Possible Patterns
Possible type patterns:
// basic string
'type' // only one test
'type | type' // returns to test one or more types
'type?' // is type or null/undefined
'type | type?' // the second type would be type or null/undefined
// basic array
'[type]' // returns test to test all the keys
'[type | type]' // returns test to test all key with one or more
'[[type],[type]]'
// basic object
'{key1: type}'
'{key1: type | type}'
'{key1: type, key2: type}'
'{key1: type, key2?: type}' // if key2 is not present or null/undefined, it will not be tested
'{key1: type, key2: type?}' // if key2 is not set or null/undefined, it will not be tested
'{key1: type | type, key2: type | type}'
'{any: type}' // any key
'{any: type | type}' // any key
'{key1: type, any: type}' // specific key, and all other "any"
'{key1: type | type, ...}' // specific key, and all other no test
// ADVANCE
// array of objects
## 🔤 Type Patterns
TypeCheck JS supports a rich pattern syntax for expressing complex type requirements:
### Basic Types
```javascript
// Single type
'string' // must be string
'number' // must be number
'boolean' // must be boolean
'null' // must be null
'undefined' // must be undefined
'array' // must be array
'object' // must be object
'function' // must be function
// Optional types (allows null/undefined)
'string?' // string, null, or undefined
'number?' // number, null, or undefined
// Union types (multiple allowed types)
'string|number' // string OR number
'boolean|string|number' // any of the three types
'array|object' // array OR object
// Combined optional and union
'string|number?' // string, number, null, or undefinedArray Patterns
// Homogeneous arrays (all elements same type)
'[string]' // array of strings
'[number]' // array of numbers
'[boolean]' // array of booleans
// Heterogeneous arrays (specific positions)
'[string, number]' // first element string, second number
'[string, number, boolean]' // three elements with specific types
'[object, array, string]' // mixed types at specific positions
// Union types in arrays
'[string|number]' // array where all elements are string OR number
'[string, number|boolean]' // first string, second number OR boolean
// Nested arrays
'[[string]]' // array of string arrays
'[string, [number]]' // first string, second is number array
'[[string, number]]' // array containing [string, number] pairs
// Optional elements in arrays
'[string, number?]' // second element optionalObject Patterns
// Basic object structure
'{name: string}' // object with name property (string)
'{name: string, age: number}' // object with name and age properties
'{id: number, active: boolean}' // id (number) and active (boolean)
// Optional properties
'{name: string, age?: number}' // age property is optional
'{id: number, email?: string}' // email property is optional
// Union types in properties
'{status: string|number}' // status can be string OR number
'{data: string|array|object}' // data can be multiple types
// Any key validation (all properties same type)
'{any: string}' // all property values must be strings
'{any: number}' // all property values must be numbers
'{any: string|number}' // all values string OR number
// Mixed specific and any
'{id: number, any: string}' // id must be number, others string
'{name: string, age: number, any: boolean}' // specific props + others boolean
// Ignore extra properties
'{name: string, ...}' // name required, ignore other props
'{id: number, email: string, ...}' // specified props required, others ignored
// Nested objects
'{user: {name: string, age: number}}' // nested object structure
'{config: {theme: string, debug: boolean}}' // nested configuration object
// Complex nested structures
'{users: [{id: number, name: string}]}' // array of user objects
'{response: {data: [object], meta: {total: number}}}' // complex API responseAdvanced Patterns
// Enums (specific values only)
'enum=red/green/blue' // only these three values allowed
'enum=small/medium/large' // size enum
'enum=admin/user/guest' // role enum
// Enums with other types
'string|enum=active/inactive' // string OR specific enum values
'enum=1/2/3|string' // enum values OR any string
// Complex array patterns
'[{name: string, tags: [string]}]' // array of objects with string arrays
'[string, {count: number}, [boolean]]' // mixed: string, object, boolean array
// Real-world examples
'{id: number, user: {name: string, email: string}, items: [{id: number, quantity: number}]}'
// API response patterns
'{data: [object], pagination: {page: number, total: number}, meta: {timestamp: string}}'
// Form validation patterns
'{email: string, password: string, confirmPassword?: string, terms: boolean}'
// Configuration object patterns
'{api: {baseUrl: string, timeout: number?}, features: {darkMode: boolean, notifications: boolean}}'Pattern Examples with Use Cases
// User profile validation
const userPattern = `{
id: number,
email: string,
profile: {
firstName: string,
lastName: string,
avatar?: string
},
preferences: {
theme: enum=light/dark,
notifications: boolean
},
roles: [enum=admin/user/moderator]
}`;
// E-commerce order
const orderPattern = `{
orderId: string,
customer: {id: number, email: string},
items: [{
productId: number,
name: string,
price: number,
quantity: number
}],
shipping: {
address: string,
method: enum=standard/express/overnight
},
total: number
}`;
// API response with pagination
const apiResponsePattern = `{
data: [object],
pagination: {
page: number,
limit: number,
total: number,
hasNext: boolean
},
meta?: {
timestamp: string,
version: string
}
}`;📝 Comprehensive Examples
Form Validation
import { validType, typeCheck } from '@knighttower/type-check';
function validateRegistrationForm(formData) {
const errors = [];
// Basic field validation
if (!validType(formData.email, 'string')) {
errors.push('Email is required');
}
if (!validType(formData.password, 'string')) {
errors.push('Password is required');
}
// Complex object validation
if (!validType(formData, '{email: string, password: string, age?: number}')) {
errors.push('Invalid form structure');
}
// Custom validation with typeCheck for strict enforcement
try {
typeCheck(formData.preferences, '{newsletter: boolean, theme: enum=light/dark}');
} catch (error) {
errors.push('Invalid preferences');
}
return errors;
}
// Usage
const formData = {
email: '[email protected]',
password: 'securePassword',
age: 25,
preferences: {
newsletter: true,
theme: 'dark'
}
};
const errors = validateRegistrationForm(formData);API Data Validation
import { _typeCheck, addTypeTest } from '@knighttower/type-check';
// Custom validation for ISO date strings
addTypeTest('isoDate', (value) => {
return typeof value === 'string' && !isNaN(Date.parse(value));
});
// API endpoint with validation
async function fetchUserOrders(userId) {
// Validate input
typeCheck(userId, 'number');
const response = await fetch(`/api/users/${userId}/orders`);
const data = await response.json();
// Validate API response structure
const isValid = _typeCheck(data, `{
orders: [{
id: number,
status: enum=pending/processing/shipped/delivered,
items: [{name: string, quantity: number, price: number}],
createdAt: isoDate,
total: number
}],
pagination: {page: number, totalPages: number}
}`).test();
if (!isValid) {
throw new Error('Invalid API response format');
}
return data;
}Function Parameter Validation
import { _tc, _tcx } from '@knighttower/type-check';
// Database query function with validation
const findUsers = _tc(
['{filters?: {name?: string, age?: number, active?: boolean}, limit?: number}'],
function(options = {}) {
const { filters = {}, limit = 10 } = options;
// Build and execute query
console.log('Searching users with filters:', filters);
return mockDatabaseQuery(filters, limit);
}
);
// Math function with input and output validation
const calculateCompoundInterest = _tcx(
['number', 'number', 'number', 'number'],
function(principal, rate, time, compound) {
return principal * Math.pow((1 + rate / compound), compound * time);
},
{ validOutput: 'number' }
);
// Usage
const users = findUsers({
filters: { active: true, age: 25 },
limit: 5
});
const investment = calculateCompoundInterest(1000, 0.05, 10, 12).return();Configuration Validation
import { typeCheck, addTypeTest } from '@knighttower/type-check';
// Custom port number validation
addTypeTest('port', (value) => {
return typeof value === 'number' && value >= 1 && value <= 65535;
});
// Application configuration
const configPattern = `{
server: {
host: string,
port: port,
ssl: boolean
},
database: {
url: string,
pool: {min: number, max: number}
},
features: {
auth: boolean,
logging: enum=debug/info/warn/error,
rateLimit?: {
windowMs: number,
max: number
}
}
}`;
function validateConfig(config) {
try {
typeCheck(config, configPattern);
console.log('Configuration is valid');
return true;
} catch (error) {
console.error('Configuration error:', error.message);
return false;
}
}
// Usage
const appConfig = {
server: {
host: 'localhost',
port: 3000,
ssl: false
},
database: {
url: 'postgresql://localhost:5432/myapp',
pool: { min: 2, max: 10 }
},
features: {
auth: true,
logging: 'info',
rateLimit: {
windowMs: 900000,
max: 100
}
}
};
validateConfig(appConfig);Real-time Data Validation
import { _typeCheck } from '@knighttower/type-check';
// WebSocket message validation
function handleWebSocketMessage(message) {
// Log validation details in development
const validation = _typeCheck(message, `{
type: enum=user_joined/user_left/message/typing,
payload: {
userId: number,
username: string,
content?: string,
timestamp: number
}
}`).log();
if (!validation.test()) {
console.warn('Invalid message format received');
return;
}
// Process valid message
const { type, payload } = message;
switch (type) {
case 'message':
displayMessage(payload);
break;
case 'user_joined':
showUserJoined(payload);
break;
// ... other cases
}
}
// Event handler validation
const handleUserAction = _tc(
['{action: enum=click/hover/focus, target: string, data?: object}'],
function(event) {
console.log(`User ${event.action} on ${event.target}`);
if (event.data) {
console.log('Additional data:', event.data);
}
}
);⚡ Performance
'[{key1: type | type}]' // returns test to test all key with one or more '[{key1: type, key2: type}]' // returns '[{key1: type, key2: type}, {key1: type, key2: type}]' '[{key1: type | type, key2: type | type}, {key1: type | type, key2: type | type}]' '[{key1: type, any: type}]'
## ⚡ Performance
TypeCheck JS is designed for production use with minimal performance overhead:
### Benchmarks
- **Lightweight**: ~6k gzipped, minimal bundle impact
- **Fast Execution**: Micro-optimized for runtime operations
- **Caching**: Built-in caching for type patterns and validations
- **Memory Efficient**: Reuses validation functions and patterns
### Performance Comparison
```javascript
// Benchmark example (1000 iterations)
import { _tc, _tcx, typeCheck } from '@knighttower/type-check';
// _tc: ~3ms for 1000 function calls with validation
const fastFunction = _tc(['[number]'], (arr) => arr.reduce((a, b) => a + b, 0));
// _tcx: ~4ms for 1000 function calls with input/output validation
const robustFunction = _tcx(['[number]'], (arr) => arr.reduce((a, b) => a + b, 0), {
validOutput: 'number'
});
// Direct typeCheck: ~2ms for 1000 direct validations
const numbers = [1, 2, 3, 4, 5];
for (let i = 0; i < 1000; i++) {
typeCheck(numbers, '[number]');
}Optimization Tips
- Reuse wrapped functions: Create
_tcand_tcxwrapped functions once, use many times - Use
validType()for boolean checks: Faster than_typeCheck().test() - Cache complex patterns: The library automatically caches, but avoid recreating patterns
- Prefer simpler patterns:
'string'is faster than'string|number|boolean'
🧪 Tests
Comprehensive test coverage ensures reliability:
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run performance benchmarks
npm run benchmarkTest Files
tests/TypeCheck.test.js- Core functionality teststests/TestBuilder.Unit.test.js- Pattern parsing teststests/BuildExports.unit.test.js- Export validation teststype-patterns.txt- Extended pattern examples
Example Test Cases
// Basic type validation
expect(validType(123, 'number')).toBe(true);
expect(validType('hello', 'number')).toBe(false);
// Complex object validation
expect(validType({
user: { name: 'John', age: 30 },
items: [{ id: 1, name: 'Item' }]
}, '{user: {name: string, age: number}, items: [{id: number, name: string}]}')).toBe(true);
// Custom type tests
addTypeTest('even', x => typeof x === 'number' && x % 2 === 0);
expect(validType(4, 'even')).toBe(true);
expect(validType(3, 'even')).toBe(false);
// Function wrapper tests
const fn = _tc(['string'], (str) => str.toUpperCase());
expect(() => fn('hello')).not.toThrow();
expect(() => fn(123)).toThrow();🔧 Advanced Usage
TypeScript Integration
TypeCheck JS works alongside TypeScript for runtime validation:
import { typeCheck, validType } from '@knighttower/type-check';
interface User {
id: number;
name: string;
email: string;
}
function processUser(data: unknown): User {
// Runtime validation
typeCheck(data, '{id: number, name: string, email: string}');
// Now TypeScript knows data is valid
return data as User;
}
// API response validation
async function fetchUser(id: number): Promise<User> {
const response = await fetch(`/api/users/${id}`);
const data = await response.json();
if (!validType(data, '{id: number, name: string, email: string}')) {
throw new Error('Invalid user data from API');
}
return data;
}Error Handling
import { typeCheck, _typeCheck } from '@knighttower/type-check';
// Custom error messages
try {
typeCheck(invalidData, 'string', {
error: 'User input must be a valid string'
});
} catch (error) {
console.error('Validation failed:', error.message);
}
// Graceful validation
function safeValidation(data, pattern) {
const result = _typeCheck(data, pattern);
if (!result.test()) {
console.warn('Data validation failed for pattern:', pattern);
return null;
}
return result.return();
}
// Multiple validation attempts
function validateWithFallback(data) {
const patterns = [
'{id: number, name: string}',
'{id: string, name: string}',
'{name: string}'
];
for (const pattern of patterns) {
if (validType(data, pattern)) {
console.log('Matched pattern:', pattern);
return data;
}
}
throw new Error('Data does not match any expected pattern');
}Custom Validation Library
import { addTypeTest, typeCheck } from '@knighttower/type-check';
// Build a custom validation library
class CustomValidators {
static init() {
// Email validation
addTypeTest('email', (value) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return typeof value === 'string' && emailRegex.test(value);
});
// Phone number validation
addTypeTest('phone', (value) => {
const phoneRegex = /^\+?[\d\s\-\(\)]+$/;
return typeof value === 'string' && phoneRegex.test(value);
});
// URL validation
addTypeTest('url', (value) => {
try {
new URL(value);
return true;
} catch {
return false;
}
});
// Credit card validation (basic)
addTypeTest('creditCard', (value) => {
const ccRegex = /^\d{4}\s?\d{4}\s?\d{4}\s?\d{4}$/;
return typeof value === 'string' && ccRegex.test(value.replace(/\s/g, ''));
});
// Strong password validation
addTypeTest('strongPassword', (value) => {
const strongRegex = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
return typeof value === 'string' && strongRegex.test(value);
});
}
}
// Initialize custom validators
CustomValidators.init();
// Use custom validators
const userRegistration = {
email: '[email protected]',
phone: '+1-555-123-4567',
website: 'https://example.com',
password: 'MyStr0ng!Pass'
};
typeCheck(userRegistration, `{
email: email,
phone: phone,
website: url,
password: strongPassword
}`);🤝 Contributing
We welcome contributions! Here's how to get started:
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Make your changes with tests
- Run the test suite:
npm test - Submit a pull request
Development Setup
git clone https://github.com/knighttower/typeCheckJs.git
cd typeCheckJs
npm install
npm test📄 License
MIT License - see LICENSE file for details.
🔗 Related Projects
Check out other tools in the Knight Tower ecosystem:
- Utility JS - Additional JavaScript utilities
- DOM Observer - DOM change detection
- Proxy Object - Object state management
Check out other cool stuff at https://knighttower.io and help support open source projects.
