Typed Function
typed-function (current stable version 4.2.2) is a JavaScript utility library designed to centralize and manage runtime type checking and automatic type conversion for function arguments. It allows developers to define multiple signatures for a single function, supporting union types, the `any` type, and variable arguments. This approach helps in separating type validation logic from core business logic, leading to cleaner code and more informative error messages when functions are called with incorrect input. The library aims to improve robustness and debuggability in JavaScript applications by providing consistent and helpful error messages, preventing silent failures due to invalid inputs. It is actively maintained and supports various environments, including Node.js (>=18) and modern browsers. Its key differentiators include flexible signature definition, detailed error reporting, and optional type conversion.
Common errors
-
TypeError: Unexpected type of argument X (expected Y, got Z) in function functionName
cause A function was called with an argument whose type does not match any of the defined signatures for that argument, and no automatic conversion was possible.fixEnsure the arguments provided to the typed function strictly match one of its defined signatures. If type conversion is desired, ensure the necessary types and conversion rules are registered via `typed.addType`. -
TypeError: No matching signature found for function functionName with arguments (type1, type2, ..., typeN)
cause The arguments provided to the typed function do not match the number or types of any of the defined function signatures.fixReview the function's defined signatures and adjust the call to match an existing signature. Alternatively, add a new signature to the typed function that accommodates the intended argument types and count.
Warnings
- gotcha Runtime type checking inherently adds a performance overhead. While `typed-function` is optimized, applying it to every function call, especially in hot code paths, can impact performance.
- gotcha `typed-function` enforces strict input types, but over-applying this strictness can inadvertently reduce a function's flexibility, potentially violating Postel's law ('be liberal in what you accept and conservative in what you send').
- breaking Major version updates (e.g., v3 to v4) can introduce breaking changes to the type signature syntax, `addType` API, or default type conversion behaviors.
Install
-
npm install typed-function -
yarn add typed-function -
pnpm add typed-function
Imports
- typed
import { typed } from 'typed-function'import typed from 'typed-function'
- typed
const typed = require('typed-function') - addType
typed.addType({ name: 'MyType', test: (x) => x instanceof MyClass })
Quickstart
import typed from 'typed-function';
// Create a typed function with a single signature
const greet = typed({
'string, string': function (firstName, lastName) {
return `Hello, ${firstName} ${lastName}!`;
}
});
console.log(greet('John', 'Doe'));
// Expected output: "Hello, John Doe!"
// Create a typed function with multiple signatures (overloading)
// and a union type for one argument
const calculate = typed({
'number, number': function (a, b) {
return a + b;
},
'string, string': function (a, b) {
return a + b; // string concatenation
},
'number, number | string': function (a, b) {
// This signature allows a number and a number or string for the second argument.
// 'typed-function' will attempt type conversion if possible based on registered types.
return `Result: ${a + b}`;
}
});
console.log(calculate(5, 3));
// Expected output: 8
console.log(calculate('Hello', ' World'));
// Expected output: "Hello World"
try {
console.log(calculate(10, '20')); // Matches 'number, number | string'
} catch (e) {
console.error("Error calling calculate with number and string:", e.message);
}
// Example of a function designed to throw an error for unsupported types
const processDate = typed({
'Date': function(date) {
return `It's a date: ${date.toDateString()}`;
}
});
try {
console.log(processDate('not a date'));
} catch (e) {
console.error("Error calling processDate:", e.message);
}
// Expected: Error calling processDate: TypeError: Unexpected type of argument 1 (expected Date, got string) in function processDate