Skip to content

Keywords

TypeScript

All* builtin TypeScript keywords are directly available.

const 
const keywords: Type<{
    string: string;
    date: Date;
}>
keywords
=
const type: TypeParser
<{
    readonly string: "string";
    readonly date: "Date";
}, Type<{
    string: string;
    date: Date;
}, {}>>(def: validateObjectLiteral<{
    readonly string: "string";
    readonly date: "Date";
}, {}, bindThis<{
    readonly string: "string";
    readonly date: "Date";
}>>) => Type<...> (+2 overloads)
type
({
string: "string", date: "Date" })

Subtype

Subtype keywords refine or transform their root type.

const 
const keywords: Type<{
    dateFormattedString: string.date;
    transformStringToDate: (In: string.date) => To<Date>;
    isoFormattedString: string.date.iso;
    transformIsoFormattedStringToDate: (In: string.date.iso) => To<Date>;
}>
keywords
=
const type: TypeParser
<{
    readonly dateFormattedString: "string.date";
    readonly transformStringToDate: "string.date.parse";
    readonly isoFormattedString: "string.date.iso";
    readonly transformIsoFormattedStringToDate: "string.date.iso.parse";
}, Type<...>>(def: validateObjectLiteral<...>) => Type<...> (+2 overloads)
type
({
dateFormattedString: "string.date", transformStringToDate: "string.date.parse", isoFormattedString: "string.date.iso", transformIsoFormattedStringToDate: "string.date.iso.parse" })

You can easily explore available subtypes via autocomplete by with a partial definition like "string.".

this

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

const 
const disappointingGift: Type<{
    label: string;
    box?: ...;
}>
disappointingGift
=
const type: TypeParser
<{
    readonly label: "string";
    readonly "box?": "this";
}, Type<{
    label: string;
    box?: ...;
}, {}>>(def: validateObjectLiteral<{
    readonly label: "string";
    readonly "box?": "this";
}, {}, bindThis<{
    readonly label: "string";
    readonly "box?": "this";
}>>) => Type<...> (+2 overloads)
type
({ label: "string", "box?": "this" })
const
const myGift: {
    label: string;
    box?: ...;
}
myGift
=
const disappointingGift: Type<{
    label: string;
    box?: ...;
}>
disappointingGift
.assert(await const fetchGift: () => Promise<null>fetchGift())
// hover me const const chainable: string | undefinedchainable =
const myGift: {
    label: string;
    box?: ...;
}
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 
const disappointingGifts: Type<{
    label: string;
    boxes: ...[];
}[]>
disappointingGifts
=
const type: TypeParser
<{
    readonly label: "string";
    readonly boxes: "this";
}, "[]", readonly [], Type<{
    label: string;
    boxes: ...[];
}[], {}>>(_0: validateObjectLiteral<{
    readonly label: "string";
    readonly boxes: "this";
}, {}, bindThis<{
    readonly label: "string";
    readonly boxes: "this";
}>>, _1: "[]") => Type<...> (+2 overloads)
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 
const types: Module<{
    disappointingGift: {
        label: string;
        box?: ...;
    };
}>
types
=
const scope: ScopeParser
<{
    readonly disappointingGift: {
        readonly label: "string";
        readonly "box?": "disappointingGift";
    };
}>(def: scope.validate<{
    readonly disappointingGift: {
        readonly label: "string";
        readonly "box?": "disappointingGift";
    };
}>, config?: ArkScopeConfig) => Scope<...>
scope
({
disappointingGift: { label: "string", // Resolves correctly to the root of the current type "box?": "disappointingGift" } }).export()