arktype
2.2.9 · 20 Oct 2026MIT3.4M / weekRepositoryHomepagenpmAtom feed
56 stable releases, newest first, by release line. Notes are quoted as the maintainers published them.
- 2.x · latest line
2.2.9
20 Oct 2026A predicate, a second pattern, a
Datebound or an array's non-index props is dropped from the schema it constrainsbigint,symbol, a non-JSON unit likeundefinedand any prototype other thanArraybecome{}A variadic tuple with postfix elements keeps its prefix and
minItems, but not itsitems
Keep tuple elements around defaults in
.inand.outCombining a tuple's defaultable elements with its other elements dropped some of them, depending on key order:
const T = type(["string", "number = 5", "boolean?"]) // was: [string, boolean?] // now: [string, number?, boolean?] T.in.expression // was: number[] // now: [number, string, ...number[]] type(["number", "string = 'foo'", "...", "number[]"]).out.expression
A bound that narrows two existing length constraints at once also no longer throws "multiple distinct intersection results":
// was: throws // now: string == 2 type("1 <= string <= 2").and("string >= 2")Reject
NaNin unions discriminated bytypeofnumberrejectsNaN, but compiled unions likenumber | nulldropped that check when they discriminated bytypeof, soNaNwas only rejected withjitless(#1702).const T = type("number | null") // was: NaN // now: ArkErrors: must be a number (was NaN) T(NaN)Don't treat
Object.prototypekeys as declaredInherited names like
toStringorconstructor, and an own__proto__key like the oneJSON.parsecreates, were treated as declared keys, so"+": "delete"kept them and"+": "reject"accepted them (#1701).const T = type({ a: "string", "+": "reject" }) // was: { a: "x", constructor: 1 } // now: ArkErrors: constructor must be removed T({ a: "x", constructor: 1 })Only emit referenced
$defsintoJsonSchemaWith
useRefs, or for a cyclic type, every node a type referenced was written to$defs, including discriminated union cases that never appear in the output. Some of those couldn't be converted, sotoJsonSchema()threwUnexpected JSON Schema input for structure: {}(#1689, fixes #1612, #1511 and #1546).const T = type.or( { a: type.enumerated("a", "b", "c"), b: "1" }, { a: type.enumerated("a", "e", "f"), b: "2" } ) // was: throws // now: only the $defs that a $ref points to T.toJsonSchema({ useRefs: true })Convert unrepresentable types in
~standard.jsonSchemainstead of throwing~standard.jsonSchema.inputand.outputnow throw only for an unsupportedtarget, i.e. one other thandraft-2020-12ordraft-07. Parts of a type that JSON Schema can't represent are converted instead (#1694):A predicate, a second pattern, a
Datebound or an array's non-index props is dropped from the schema it constrainsbigint,symbol, a non-JSON unit likeundefinedand any prototype other thanArraybecome{}A variadic tuple with postfix elements keeps its prefix and
minItems, but not itsitemsA default that isn't JSON is omitted
const T = type({ big: "bigint", even: type("number").narrow(n => n % 2 === 0) }) // was: throws // now: { type: "object", properties: { big: {}, even: { type: "number" } }, ... } T["~standard"].jsonSchema.input({ target: "draft-2020-12" })Fallbacks from a scope's
toJsonSchemaconfig or fromlibraryOptionsstill take precedence, andtoJsonSchema()itself still throws by default.A
defaultValuefallback can now returnundefinedto omit the default rather than writingdefault: undefined.2.2.8
7 Oct 2026Validates base58-encoded strings, which use the Bitcoin alphabet (no
0,O,Iorl):Add
string.base58Validates base58-encoded strings, which use the Bitcoin alphabet (no
0,O,Iorl):const Base58 = type("string.base58") // valid Base58("3mJr7AoUXx2Wqd") // ArkErrors: must be base58-encoded (was "0OIl") Base58("0OIl")Return empty
propsforobjecttype("object").propsthrew instead of returning the empty list of properties, liketype({}).propsdoes (#1682, fixes #1177).Keep object values from meta in JSON Schema
Meta values that aren't primitives, like an object or array
defaultor a custom key likex-unit, were emitted as internal$arkreferences instead of their JSON values (#1677). Defaults that aren't valid JSON, including functions, now go through thedefaultValuefallback.Report invalid generic definitions on TypeScript 7
TypeScript 7 only reports the error of the last overload that fails, which for an invalid generic definition was the tuple expression signature rather than ArkType's own message (#1681):
// TypeScript 7 previously: Argument of type '"<n extends nummer>"' is not assignable to parameter of type '"Array" | ... // now: 'nummer' is unresolvable type("<n extends nummer>", "n > 0")The generic and tuple expression signatures of
typeare now a single signature, so TypeScript 6 and 7 report the same errors directly, and errors in a generic's body point at the invalid property.2.2.7
1 Oct 2026Unions of objects disjoint at a key no longer throw
undefined is not a functionon Hermes (Expo, React Native), which doesn't preserveArraysubclasses throughmap.scope.moduleno longer referencesthisfrom a static arrow function, which Turbopack could compile toundefined.
Fix
thisin self-referential object typesReferencing an array of the enclosing type threw a spurious shallow resolution cycle error:
// previously threw, now parses const Node = type({ name: "string", "children?": "this[]" })Parse
string.date.epoch.parseinput as millisecondsThe validated integer string was passed directly to
new Date(), which runs the date string parser rather than reading it as a timestamp:const parseEpoch = type("string.date.epoch.parse") // previously 2000-01-01 local time, now 1970-01-01T00:00:00.000Z parseEpoch("0") // previously Invalid Date, now 2023-11-14T22:13:20.000Z parseEpoch("1700000000000")Keep uppercase UUIDs valid in
string.uuidJSON Schemastring.uuidaccepted uppercase hex digits via theiflag, which JSON Schemapatterncannot carry, so the exported schema rejected uppercase UUIDs the runtime check accepted. The patterns now list both cases explicitly. Thanks to @breken-ai.Render nested bigints correctly in error messages
Bigints inside arrays or objects were printed as quoted strings, e.g.
(was ["1n","0n","1n"]). They now print as(was [1n,0n,1n]). Thanks to @chatman-media.Release unused ids from the global registry
Repeatedly creating an equivalent type (e.g.
type("string")orT.pick("a")in a loop) registered a new id for each parse that nothing could reference, so memory grew without limit. Unused ids are now removed. Thanks to @isaacwasserman.Fix crashes on Hermes and Turbopack
Unions of objects disjoint at a key no longer throw
undefined is not a functionon Hermes (Expo, React Native), which doesn't preserveArraysubclasses throughmap.scope.moduleno longer referencesthisfrom a static arrow function, which Turbopack could compile toundefined.
2.2.6
30 Sep 2026ArkErrorsnow has amessagegetter returning the same human-readable string assummary, so code that handles a failed result like anErrorgets a useful message instead ofundefined:Add
ArkErrors.messageArkErrorsnow has amessagegetter returning the same human-readable string assummary, so code that handles a failed result like anErrorgets a useful message instead ofundefined:const out = T(data) if (out instanceof type.errors) console.error(out.message)
Fix a crash when
ctx.rejectwithoutexpectedfails in a unionRejecting from a narrow without an
expectedvalue could throw aTypeErrorinstead of returning errors when the failure occurred in a union that could not be discriminated:const T = type("string[] | Function").narrow( (v, ctx) => Array.isArray(v) || ctx.reject({ problem: "custom" }) ) // previously threw "Cannot read properties of undefined (reading 'name')" T(() => {})Predicate errors now have an explicit
expecteddefault that does not depend on the predicate being present in the error context.Preserve narrows on piped union branches through an intersection
Intersecting a union containing a piped and narrowed branch with another morph could drop that branch's narrow:
const T = type({ kind: "'a'", value: type("string.numeric.parse").narrow( (n, ctx) => n > 0 || ctx.mustBe("positive") ) }) .or({ kind: "'b'" }) .and(type("object").pipe(o => o)) // previously passed, now fails with "value must be positive (was -1)" T({ kind: "a", value: "-1" })Format times in
Dateerror messages independent of localeTimes in
Datedescriptions (e.g.must be after 2:30 PM, January 15, 2023) are now consistently formatted in 12-hour time rather than depending on the runtime's default locale, which previously produced output like14:30, January 15, 2023in 24-hour locales. Thanks to @WolfieLeader.2.2.5
24 Sep 2026Within a regex literal,
\\is now kept verbatim as an escaped backslash rather than collapsed to a single\, which silently changed the meaning of the pattern:Preserve escaped backslashes in regex literals
Within a regex literal,
\\is now kept verbatim as an escaped backslash rather than collapsed to a single\, which silently changed the meaning of the pattern:// previously parsed as /\d/, matching a digit // now matches a literal backslash followed by "d" const T = type("/\\\\d/")String literals are unaffected. If a definition relied on the old behavior, write the intended escape directly (e.g.
"/\\d/"for a digit). Thanks to @spokodev.Fix recursive discriminated unions referenced from a
RecordA cyclic alias referenced through
Record<string, ...>could cause valid values to be rejected, e.g. an array branch failing withmust be an array (was object). Bootstrapping alias references no longer overwrites references that were already resolved. This was a regression introduced in 2.2.2. Thanks to @xianjianlf2.Prevent a crash validating unions of object arrays
Inside a union branch, array validation now stops at the first failing element instead of continuing to traverse elements whose basis has already failed, which could throw rather than return an error. Thanks to @xianjianlf2.
Merge index-derived props with a declared key of the same name
Intersecting a structure with an index signature and one that rejects undeclared keys could produce a node with a duplicate key:
// previously { a: number, a: number, b: number, + (undeclared): reject } type({ a: "number", "[string]": "number" }).and({ a: "number", b: "number", "+": "reject" })Props derived from the index signature are now intersected with any declared prop of the same key, and the result is the same in either operand order.
Preserve parameter labels when a
type.fnimplementation annotates an optional parameterAnnotating an optional parameter, as in
type.fn("number?")((n?: number) => n), previously dropped every parameter label from the inferred signature. It now infers(n?: number | undefined) => number | undefined. Thanks to @aswinsvijay.2.2.3
7 Jul 2026type.fn.rawis documented as an untyped alias oftype.fn, but wasundefinedat runtime and threwtype.fn.raw is not a functionwhen called. It now references the underlying parser directly, so it parses, runs, and validates liketype.fnwithout type-level inference. Thanks to @aarsh767.Fix
type.fn.rawthrowing at runtimetype.fn.rawis documented as an untyped alias oftype.fn, but wasundefinedat runtime and threwtype.fn.raw is not a functionwhen called. It now references the underlying parser directly, so it parses, runs, and validates liketype.fnwithout type-level inference. Thanks to @aarsh767.Anchor versioned UUID validation
string.uuidno longer accepts strings that merely contain a UUID. The internal#versionedpattern is now anchored like the individual version keywords, so leading or trailing content is rejected. Thanks to @WolfieLeader.Fix inferred output of
declared morphsThe output side of a
declared definition now wraps its preinferred value inOut<...>, matching the inference of the equivalent definition withoutdeclare. Thanks to @eralmansouri.Allow
Object.prototypemethod names as keysKeys like
constructor,toString, andhasOwnPropertyare no longer incorrectly reported as duplicate keys, since duplicate detection now uses a prototype-free record. Thanks to @kaigritun.2.2.2
1 Jul 2026A private alias referenced only within its own scope is no longer skipped during JIT precompilation, so its optimized traversal is bound correctly instead of falling back to the unbound reference.
Fix precompilation of private aliases
A private alias referenced only within its own scope is no longer skipped during JIT precompilation, so its optimized traversal is bound correctly instead of falling back to the unbound reference.
Harden
ArkErrorsJSON serializationArkErrorsdoubles as a Standard Schemaissuesarray, soJSON.stringifyno longer assumes every indexed entry is anArkErrorwith atoJSONmethod (e.g. plain issue-shaped entries from other validators). Inherited array methods (map,filter,slice, …) now return a plainArrayviaSymbol.species, preventing callbacks that return primitives from producing a malformedArkErrors.2.2.1
17 Jun 2026See arkregex CHANGELOG for full notes.
2.2.0
4 Mar 2026|>string-embeddable pipe operatortype.valueOffor TS enumsstring.hex+string.regexkeywords
Full announcement: arktype.io/docs/blog/2.2
type.fn- Validated functionsDefine functions with runtime-validated parameters and return types. Supports defaults, optionals, and variadics.
const len = type.fn("string | unknown[]", ":", "number")(s => s.length) len("foo") // 3 len([1, 2]) // 2Type-safe regex via arkregex
Regex literals in definitions now carry full type inference.
x-prefix parses capture groups at runtime.const T = type({ birthday: "x/^(?<month>\\d{2})-(?<day>\\d{2})-(?<year>\\d{4})$/" }) T.assert({ birthday: "05-21-1993" }).birthday.groups.month // "05"@ark/json-schema- Bidirectional JSON SchemaParse JSON Schema into ArkType Types with the new
@ark/json-schemapackage, complementingtoJsonSchema(). Thanks to @TizzySaurus.Configurable
toJsonSchemaHandle incompatibilities between ArkType and JSON Schema with granular fallback codes. Supports
draft-07/draft-2020-12targets and cyclic types.Standard Schema as definitions
Any Standard Schema compliant validator (Zod, Valibot, etc.) can be embedded directly in ArkType definitions.
select- Deep reference introspectionQuery the internal structure of a type by node kind and predicate. Use selectors to configure specific references.
Improved
type.declareNow supports morph-aware declarations via a
sidecontext, and optionality via property values.N-ary operators
type.or,type.and,type.merge, andtype.pipeaccept variadic definitions.Additional highlights
|>string-embeddable pipe operatortype.valueOffor TS enumsstring.hex+string.regexkeywordsSerializable
ArkErrors(flatByPath,flatProblemsByPath,toJSON)TraversalErrorreplacesAggregateErrorexactOptionalPropertyTypesconfigES2020 + Hermes compatibility
In-docs playground
Better JSDoc + go-to-definition
Cyclic unions can now discriminate on nested paths
2.1.29
13 Dec 2025See arkregex CHANGELOG for full notes.
2.1.28
3 Dec 2025Adds support for the new Standard JSON Schema interface (see standardschema.dev)
Now accepts a
targetoption and can generate draft-07 in addition to draft-2020-12
JSON Schema improvements
Adds support for the new Standard JSON Schema interface (see standardschema.dev)
Now accepts a
targetoption and can generate draft-07 in addition to draft-2020-12
Standard Schema is now a valid definition
Any Standard Schema compliant validator can now be passed directly to
type, either directly or nested in a structural ArkType definition, and will be fully inferred and validated.import { type } from "arktype" import * as v from "valibot" import z from "zod" const ZodAddress = z.object({ street: z.string(), city: z.string() }) const User = type({ name: "string", age: v.number(), address: ZodAddress })e(x)ec mode for regex types
const User = type({ // x-prefix a regex literal to parse its type-safe capture groups birthday: "x/^(?<month>\\d{2})-(?<day>\\d{2})-(?<year>\\d{4})$/" }) const data = User.assert({ birthday: "05-21-1993" }) // fully type-safe via arkregex console.log(data.birthday.groups) // { month: "05", day: "21", year: "1993" }more flexible
type.declareOptionality can now be expressed via a property value in addition to its key:
type Expected = { f?: string } const T = type.declare<Expected>().type({ // previously failed with `"f?" is missing` f: "string?" })fixed a bug causing predicate errors after the first to not be reported
import { type } from "arktype" const Dates = type({ date1: "string.date", date2: "string.date", date3: "string.date" }) // now correctly reports the errors on `date2` and `date3` in addition to `date1` Dates.assert({ date1: "", date2: "", date3: "" })See #1557
2.1.26
10 Nov 2025Remove usages of newer prototypes methods like
.at()to better support legacy browserses2020 compatibility
Remove usages of newer prototypes methods like
.at()to better support legacy browsersimprove external generic inference
Some inference scenarios like the following involving default values are now more cooperative (thanks @Andarist) 🎉
function someFunction<TSchema extends Record<string, any>>( schema: Type<TSchema, {}> ): (typeof schema)["infer"] { const someData = { hello: "world" } return schema.assert(someData) } const schema = type({ hello: type("string").pipe(s => s === "world"), goodbye: "string='blah'" }) someFunction(schema)2.1.25
28 Oct 20252.1.24
28 Oct 2025Definitions like the following now throw a descriptive error:
2.1.21
2 Sep 2025Adds support for the upcoming StandardJSONSchemaSourceV1 spec (standardschema.dev)
2.1.20
16 Apr 2025Some ArkType features don't have JSON Schema equivalents. By default,
toJsonSchema()will throw in these cases.toJsonSchemaconfigSome ArkType features don't have JSON Schema equivalents. By default,
toJsonSchema()will throw in these cases.This behavior can be configured granularly to match your needs.
const T = type({ "[symbol]": "string", birthday: "Date" }) const schema = T.toJsonSchema({ fallback: { // ✅ the "default" key is a fallback for any non-explicitly handled code // ✅ ctx includes "base" (represents the schema being generated) and other code-specific props // ✅ returning `ctx.base` will effectively ignore the incompatible constraint default: ctx => ctx.base, // handle specific incompatibilities granularly date: ctx => ({ ...ctx.base, type: "string", format: "date-time", description: ctx.after ? `after ${ctx.after}` : "anytime" }) } }) const result = { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", properties: { // Date instance is now a date-time string as specified by the `date` handler birthday: { type: "string", format: "date-time", description: "anytime" } }, required: ["birthday"] // symbolic index signature ignored as specified by the `default` handler }a
defaulthandler can also be specified at the root of afallbackconfig:const T = type({ "[symbol]": "string", birthday: "Date" }) //--- cut --- const schema = T.toJsonSchema({ // "just make it work" fallback: ctx => ctx.base })These options can also be set at a global or scope-level.
Fallback Codes
This is the full list of configurable reasons
toJsonSchema()can fail.Code Description arrayObjectarrays with object properties arrayPostfixarrays with postfix elements defaultValuenon-serializable default value domainnon-serializable type keyword (always bigintorsymbol)morphtransformation patternIntersectionmultiple regex constraints predicatecustom narrow function protonon-serializable instanceofsymbolKeysymbolic key on an object unitnon-serializable ===reference (e.g.undefined)datea Date instance (supersedes protofor Dates)cyclic types can now be converted to JSON Schema
// previously this threw const schema = type("object.json").toJsonSchema() // now generates the following schema const result = { $ref: "#/$defs/intersection11", $defs: { intersection11: { type: "object", additionalProperties: { $ref: "#/$defs/jsonData1" } }, jsonData1: { anyOf: [ { $ref: "#/$defs/intersection11" }, { type: "number" }, { type: "string" }, { type: "boolean" }, { type: "null" } ] } } }temporarily disable discrimination for cyclic unions
This addresses multiple issues while we work on a permanent solution for accurately discriminating cyclic unions, tracked here.
2.1.19
7 Apr 2025Reading the note…
2.1.18
7 Apr 2025Reading the note…
2.1.17
4 Apr 2025Reading the note…
2.1.16
1 Apr 2025Reading the note…
2.1.15
27 Mar 2025Reading the note…
2.1.14
26 Mar 2025Reading the note…
2.1.13
26 Mar 2025Reading the note…
2.1.12
24 Mar 2025Reading the note…
2.1.11
24 Mar 2025Reading the note…
2.1.10
19 Mar 2025Reading the note…
2.1.9
8 Mar 2025Reading the note…
2.1.8
7 Mar 2025Reading the note…
2.1.7
6 Mar 2025Reading the note…
2.1.6
5 Mar 2025Reading the note…
2.1.5
5 Mar 2025Reading the note…
2.1.4
5 Mar 2025Reading the note…
2.1.3
4 Mar 2025Reading the note…
2.1.2
1 Mar 2025Reading the note…
2.1.1
1 Mar 2025Reading the note…
2.1.0
23 Feb 2025"assert": acceptunknown, throw if none of the cases match"never": accept an input based on inferred cases, throw if none match"reject": acceptunknown, returnArkErrorsif none of the cases match
matchThe
matchfunction provides a powerful way to handle different types of input and return corresponding outputs based on the input type, like a type-safeswitchstatement.Case Record API
The simplest way to define a matcher is with ArkType definition strings as keys with corresponding handlers as values:
import { match } from "arktype" const sizeOf = match({ "string | Array": v => v.length, number: v => v, bigint: v => v, default: "assert" }) // a match definition is complete once a `default` has been specified, // either as a case or via the .default() method sizeOf("abc") // 3 sizeOf([1, 2, 3, 4]) // 4 sizeOf(5n) // 5n // ArkErrors: must be an object, a string, a number or a bigint (was boolean) sizeOf(true)In this example,
sizeOfis a matcher that takes a string, array, number, or bigint as input. It returns the length of strings and arrays, and the value of numbers and bigints.defaultaccepts one of 4 values:"assert": acceptunknown, throw if none of the cases match"never": accept an input based on inferred cases, throw if none match"reject": acceptunknown, returnArkErrorsif none of the cases match(data: In) => unknown: handle data not matching other cases directly
Cases will be checked in the order they are specified, either as object literal keys or via chained methods.
Fluent API
The
matchfunction also provides a fluent API. This can be convenient for non-string-embeddable definitions:// the Case Record and Fluent APIs can be easily combined const sizeOf = match({ string: v => v.length, number: v => v, bigint: v => v }) // match any object with a numeric length property and extract it .case({ length: "number" }, o => o.length) // return 0 for all other data .default(() => 0) sizeOf("abc") // 3 sizeOf({ name: "David", length: 5 }) // 5 sizeOf(null) // 0Narrowing input with
in, property matching withattype Data = | { id: 1 oneValue: number } | { id: 2 twoValue: string } const discriminateValue = match // .in allows you to specify the input TypeScript allows for your matcher .in<Data>() // .at allows you to specify a key at which your input will be matched .at("id") .match({ 1: o => `${o.oneValue}!`, 2: o => o.twoValue.length, default: "assert" }) discriminateValue({ id: 1, oneValue: 1 }) // "1!" discriminateValue({ id: 2, twoValue: "two" }) // 3 discriminateValue({ oneValue: 3 })Builtin keywords can now be globally configured
This can be very helpful for customizing error messages without needing to create your own aliases or wrappers.
import { configure } from "arktype/config" configure({ keywords: { string: "shorthand description", "string.email": { actual: () => "definitely fake" } } })import "./config.ts" import { type } from "arktype" const user = type({ name: "string", email: "string.email" }) const out = user({ // ArkErrors: name must be shorthand description (was a number) name: 5, // ArkErrors: email must be an email address (was definitely fake) email: "449 Canal St" })The options you can provide here are identical to those used to configure a Type directly, and can also be extended at a type-level to include custom metadata.
Tuple and args expressions for
.toIf a morph returns an
ArkErrorsinstance, validation will fail with that result instead of it being treated as a value. This is especially useful for using other Types as morphs to validate output or chain transformations.To make this easier, there's a special
tooperator that can pipe to a parsed definition without having to wrap it intypeto make it a function.This was added before 2.0, but now it comes with a corresponding operator (
|>) so that it can be expressed via a tuple or args like most other expressions:const fluentStillWorks = type("string.numeric.parse").to("number % 2") const nowSoDoesTuple = type({ someKey: ["string.numeric.parse", "|>", "number % 2"] }) const andSpreadArgs = type("string.numeric.parse", "|>", "number % 2")Error configurations now accept a string directly
const customOne = type("1", "@", { // previously only a function returning a string was allowed here message: "Yikes." }) // ArkErrors: Yikes. customOne(2)Keep in mind, as mentioned in the docs, error configs like
messagecan clobber more granular config options likeexpectedandactualand cannot be included in composite errors e.g. for a union.Though generally, returning a string based on context is the best option, in situations where you always want the same static message, it's now easier to get that!
Type.toString() now wraps its syntactic representation in
Type<..>Previously,
Type.toString()just returnedType.expression. However, in contexts where the source of a message isn't always aType, it could be confusing:// < 2.1.0: "(was string)" // >= 2.1.0: "(was Type<string>)" console.log(`(was ${type.string})`)Hopefully if you interpolate a Type, you'll be less confused by the result from now on!
Improve how Type instances are inferred when wrapped in external generics
Previously, we used
NoInferin some Type method returns. After migrating those to inlined conditionals, we get the same benefit and external inference for cases like this is more reliable:function fn< T extends { schema: StandardSchemaV1 } >(_: T) { return {} as StandardSchemaV1.InferOutput<T["schema"]> } // was inferred as unknown (now correctly { name: string }) const arkRes = fn({ schema: type({ name: "string" }) })Fix an issue causing some discriminated unions to incorrectly reject default cases
const discriminated = type({ id: "0", k1: "number" }) .or({ id: "1", k1: "number" }) .or({ name: "string" }) // previously, this was rejected as requiring a "k1" key // will now hit the case discriminated for id: 1, // but still correctly be allowed via the { name: string } branch discriminated({ name: "foo", id: 1 })2.0.4
29 Jan 2025Reading the note…
2.0.3
26 Jan 2025Reading the note…
2.0.2
24 Jan 2025Reading the note…
2.0.1
23 Jan 2025Reading the note…
2.0.0
17 Jan 2025Initial stable release 🎉
- 0.6.x
0.6.0
15 Feb 2023Reading the note…
- 0.5.x
0.5.1
14 Feb 2023Reading the note…
0.5.0
13 Feb 2023Reading the note…
- 0.4.x
0.4.0
13 Feb 2023Reading the note…
- 0.3.x
0.3.0
10 Feb 2023Reading the note…
- 0.2.x
0.2.0
8 Feb 2023Reading the note…