{"id":12211,"library":"typanion","title":"Typanion","description":"Typanion is a lean, type-safe runtime TypeScript validator library with zero external runtime dependencies. It excels at validating complex, nested data structures and provides strong type inference, which allows TypeScript to refine types based on successful validation. Unlike some alternatives, Typanion emphasizes a functional and tree-shakeable API, making it efficient for bundlers. It provides detailed error reports and supports coercions, enabling data transformation during validation. While it may not have the extensive ecosystem of libraries like Zod or Yup, its core differentiators lie in its minimal footprint, functional design, and robust TypeScript inference. Currently, in version 3.14.0, its release cadence appears less frequent, suggesting a focus on stability over rapid iteration, with the last major activity around two years ago.","status":"active","version":"3.14.0","language":"javascript","source_language":"en","source_url":"https://github.com/arcanis/typanion","tags":["javascript"],"install":[{"cmd":"npm install typanion","lang":"bash","label":"npm"},{"cmd":"yarn add typanion","lang":"bash","label":"yarn"},{"cmd":"pnpm add typanion","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"The primary API is exposed as a namespace import, commonly aliased as `t`. While CJS `require` can work, ESM `import * as t` is the idiomatic and type-safe approach, especially with TypeScript.","wrong":"const t = require('typanion')","symbol":"t","correct":"import * as t from 'typanion'"},{"note":"While `t` is the common namespace import, individual predicates like `isString` can also be directly imported for better tree-shaking and explicit usage in some bundlers or environments.","wrong":"import { t.isString } from 'typanion'","symbol":"isString, isNumber, isObject","correct":"import { isString, isNumber, isObject } from 'typanion'"},{"note":"The `Coercion` type is used when enabling data coercion during validation. It's an internal type representing operations to be applied, typically used with the `{ coercions }` option in validation predicates.","wrong":"type Coercion = any[]","symbol":"Coercion","correct":"import { Coercion } from 'typanion'"}],"quickstart":{"code":"import * as t from 'typanion';\n\n// Define a schema for a user object\nconst isUser = t.isObject({\n  id: t.isNumber(),\n  name: t.isString(),\n  email: t.isOptional(t.isString()),\n  age: t.cascade(t.isNumber(), [t.isInteger(), t.isInInclusiveRange(0, 120)]),\n  roles: t.isArray(t.isString(), { maxLength: 3 }),\n  isActive: t.isBoolean(),\n});\n\n// Example valid data\nconst validUserData = {\n  id: 123,\n  name: 'Alice',\n  email: 'alice@example.com',\n  age: 30,\n  roles: ['admin', 'editor'],\n  isActive: true,\n};\n\n// Example invalid data\nconst invalidUserData = {\n  id: 'abc', // Should be number\n  name: 123,  // Should be string\n  age: 150,   // Out of range\n  roles: ['guest', 'viewer', 'reporter', 'qa'], // Too many roles\n  unknownProp: 'oops' // Extraneous property (fails by default)\n};\n\ninterface User {\n  id: number;\n  name: string;\n  email?: string;\n  age: number;\n  roles: string[];\n  isActive: boolean;\n}\n\n// Validate valid data\nconst errorsForValid: string[] = [];\nif (isUser(validUserData, { errors: errorsForValid })) {\n  console.log('Valid user data:', validUserData);\n  // TypeScript knows validUserData is now of type User\n  const user: User = validUserData;\n  console.log(user.name);\n} else {\n  console.error('Validation failed for valid data:', errorsForValid);\n}\n\nconsole.log('\\n--- Attempting to validate invalid data ---');\n\n// Validate invalid data\nconst errorsForInvalid: string[] = [];\nif (isUser(invalidUserData, { errors: errorsForInvalid })) {\n  console.log('Invalid user data (unexpected success):', invalidUserData);\n} else {\n  console.error('Validation failed for invalid data:');\n  errorsForInvalid.forEach(error => console.error(`- ${error}`));\n  // TypeScript still considers invalidUserData as 'unknown' here\n  // because validation failed.\n}\n\n// Example with coercion (though not typical for this schema)\nconst isCoercibleNumber = t.applyCoercion(t.isNumber(), t.isString());\nconst coercions: t.Coercion[] = [];\nconst potentiallyNumber = '42';\n\nif (isCoercibleNumber(potentiallyNumber, { coercions })) {\n    for (const [p, op] of coercions) op();\n    console.log('\\nCoerced value:', potentiallyNumber); // will be 42 (number)\n    const num: number = potentiallyNumber;\n    console.log(typeof num); // 'number'\n} else {\n    console.error('Coercion failed');\n}","lang":"typescript","description":"This quickstart demonstrates how to define a schema for a user object, validate both valid and invalid data, collect detailed error messages, leverage TypeScript's type inference upon successful validation, and briefly showcases a coercion example."},"warnings":[{"fix":"To allow extraneous properties, pass `extra: t.isUnknown()` or a specific schema for extra properties to `t.isObject` (e.g., `t.isObject({ /* ... */ }, { extra: t.isUnknown() })` or `t.isObject({ /* ... */ }, { extra: t.isDict(t.isUnknown()) })`).","message":"When validating objects, `typanion` is strict by default and will report errors for extraneous properties not defined in the schema. This differs from some other validators that might ignore unknown properties.","severity":"gotcha","affected_versions":">=3.0"},{"fix":"For stricter date validation, consider using `t.cascade` with a custom regex predicate (e.g., `t.isString()` combined with `t.matches()` for ISO8601) before `t.isDate()`, or implement custom date parsing logic if milliseconds are critical. (Refer to GitHub issue #39 and #36).","message":"The `isDate()` predicate has known limitations regarding ISO8601 string parsing and does not natively support milliseconds, which can lead to unexpected validation failures for certain date formats.","severity":"gotcha","affected_versions":">=3.0"},{"fix":"Instead of `isHexColor`, which might be missing or unsupported in `cascade`, use `t.isString()` combined with `t.matches(/^#[0-9a-fA-F]{3,6}$/)` for basic hex color string validation. (Refer to GitHub issue #41).","message":"When using `t.cascade()` with `isHexColor`, the predicate may not be supported directly, leading to validation issues for hex color strings.","severity":"gotcha","affected_versions":">=3.0"},{"fix":"Carefully review the inferred types when using deeply nested `isEnum`. If type widening occurs, consider breaking down complex schemas or using explicit type assertions after validation to enforce the desired type. (Refer to GitHub issue #14).","message":"Unexpected type widening can occur when using nested `isEnum` predicates, potentially leading to less precise type inference than expected in complex schemas.","severity":"gotcha","affected_versions":">=3.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Inspect the `errors` array returned by the validation function for detailed messages. Adjust the input data to conform to the schema or refine the schema to accurately reflect the expected data shape. For example, if 'Expected number, received string' ensure the field is parsed as a number before validation.","cause":"An input value did not match the expected type or structure defined by the schema.","error":"Validation failed for path: <path>. Expected <type>, received <other_type>."},{"fix":"Ensure you are using `import * as t from 'typanion'` and accessing predicates as `t.isObject` or explicitly named imports `import { isObject } from 'typanion'`. Avoid `const { isObject } = require('typanion')` if the package is primarily ESM.","cause":"Incorrect import of predicate functions, often due to mixing CommonJS `require` with ESM named imports or attempting to destructure `t` itself.","error":"TypeError: (0 , typanion_1.isObject) is not a function"},{"fix":"Wrap the code that uses the validated value within the `if (validator(value))` block. `typanion` uses type predicates, so TypeScript's type narrowing only applies inside the conditional block where validation is successful. If coercion is used, ensure `coercions` are flushed.","cause":"Attempting to assign a value that failed a `typanion` predicate (e.g., `t.isNumber()`) to a TypeScript type that expects the validated type.","error":"Argument of type 'string' is not assignable to parameter of type 'number'."}],"ecosystem":"npm"}