Expressions

Intersection

Union

All unions are automatically discriminated to optimize check time and error message clarity.

Brand

Narrow

Morph

Unit

While embedded literal syntax is usually ideal for defining exact primitive values, === and type.unit can be helpful for referencing a non-serialiazable value like a symbol from your type.

Enumerated

type.enumerated defines a type based on a list of allowed values. It is semantically equivalent to type.unit if provided a single value.

Meta

Cast

Parenthetical

By default, ArkType's operators follow the same precedence as TypeScript's. Also like in TypeScript, this can be overridden by wrapping an expression in parentheses.

// hover to see the distinction!
const groups = type({
  stringOrArrayOfNumbers: "string | number[]",
  arrayOfStringsOrNumbers: "(string | number)[]",
});

this

this is a special keyword that can be used to create a recursive type referencing the root of the current definition.

const fetchGift = async () => null;
// ---cut---
const disappointingGift = type({ label: "string", "box?": "this" });
const myGift = disappointingGift.assert(await fetchGift());
 
// hover me
const chainable = myGift.box?.box?.label;

Unlike its TypeScript counterpart, ArkType's this is not limited to interfaces. It can also be used from within a tuple expression.

// boxes now expects an array of our gift object
const disappointingGifts = type({ label: "string", boxes: "this" }, "[]");

Referencing this from within a scope will result in a ParseError. For similar behavior within a scoped definition, just reference the alias by name:

const types = scope({
  disappointingGift: {
    label: "string",
    // Resolves correctly to the root of the current type
    "box?": "disappointingGift",
  },
}).export();

On this page