Socket
Socket
Sign inDemoInstall

arktype

Package Overview
Dependencies
Maintainers
1
Versions
100
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

arktype - npm Package Compare versions

Comparing version 2.0.0-dev.7 to 2.0.0-dev.8

__tests__/pipe.test.ts

48

__tests__/array.test.ts

@@ -17,11 +17,11 @@ import { attest, contextualize } from "@arktype/attest"

attest(t.allows([])).equals(true)
attest(t([]).out).snap([])
attest(t([])).snap([])
attest(t.allows(["foo", "bar"])).equals(true)
attest(t(["foo", "bar"]).out).snap(["foo", "bar"])
attest(t(["foo", "bar"])).snap(["foo", "bar"])
attest(t.allows(["foo", "bar", 5])).equals(false)
attest(t(["foo", "bar", 5]).errors?.summary).snap(
attest(t(["foo", "bar", 5]).toString()).snap(
"value at [2] must be a string (was number)"
)
attest(t.allows([5, "foo", "bar"])).equals(false)
attest(t([5, "foo", "bar"]).errors?.summary).snap(
attest(t([5, "foo", "bar"]).toString()).snap(
"value at [0] must be a string (was number)"

@@ -35,11 +35,11 @@ )

attest(t.allows([])).equals(true)
attest(t([]).out).snap([])
attest(t([])).snap([])
attest(t.allows([["foo"]])).equals(true)
attest(t([["foo"]]).out).snap([["foo"]])
attest(t([["foo"]])).snap([["foo"]])
attest(t.allows(["foo"])).equals(false)
attest(t(["foo"]).errors?.summary).snap(
attest(t(["foo"]).toString()).snap(
"value at [0] must be an array (was string)"
)
attest(t.allows([["foo", 5]])).equals(false)
attest(t([["foo", 5]]).errors?.summary).snap(
attest(t([["foo", 5]]).toString()).snap(
"value at [0][1] must be a string (was number)"

@@ -84,9 +84,9 @@ )

attest(t.allows(["", 0])).equals(true)
attest(t(["", 0]).out).snap(["", 0])
attest(t(["", 0])).snap(["", 0])
attest(t.allows([true, 0])).equals(false)
attest(t([true, 0]).errors?.summary).snap(
attest(t([true, 0]).toString()).snap(
"value at [0] must be a string (was true)"
)
attest(t.allows([0, false])).equals(false)
attest(t([0, false]).errors?.summary)
attest(t([0, false]).toString())
.snap(`value at [0] must be a string (was number)

@@ -96,8 +96,6 @@ value at [1] must be a number (was false)`)

attest(t.allows([""])).equals(false)
attest(t([""]).errors?.summary).snap(
'must be exactly length 2 (was [""])'
)
attest(t([""]).toString()).snap('must be exactly length 2 (was [""])')
// too long
attest(t.allows(["", 0, 1])).equals(false)
attest(t(["", 0, 1]).errors?.summary).snap(
attest(t(["", 0, 1]).toString()).snap(
'must be exactly length 2 (was ["",0,1])'

@@ -118,3 +116,3 @@ )

1: 0
}).errors?.summary
}).toString()
).snap("must be an array (was object)")

@@ -138,6 +136,6 @@ })

attest(t.allows(valid)).equals(true)
attest(t(valid).out).equals(valid)
attest(t(valid)).equals(valid)
const invalid = [["", 0], [{ a: 0n, b: [undefined] }]]
attest(t.allows(invalid)).equals(false)
attest(t(invalid).errors?.summary).snap(
attest(t(invalid).toString()).snap(
"value at [1][0].b[0] must be null (was undefined)"

@@ -150,8 +148,8 @@ )

attest<[string?]>(t.infer)
attest(t([]).errors).equals(undefined)
attest(t(["foo"]).errors).equals(undefined)
attest(t([5]).errors?.summary).snap(
attest(t([])).equals([])
attest(t(["foo"])).equals(["foo"])
attest(t([5]).toString()).snap(
"value at [0] must be a string (was number)"
)
attest(t(["foo", "bar"]).errors?.summary).snap(
attest(t(["foo", "bar"]).toString()).snap(
"must be at most length 1 (was 2)"

@@ -171,4 +169,4 @@ )

attest<[string, ...number[]]>(wellRested.infer)
attest(wellRested(["foo"]).out).equals(["foo"])
attest(wellRested(["foo", 1, 2]).out).equals(["foo", 1, 2])
attest(wellRested(["foo"])).equals(["foo"])
attest(wellRested(["foo", 1, 2])).equals(["foo", 1, 2])
})

@@ -397,3 +395,3 @@

// const stringArray = type("string[]")
// attest(stringArray([1, 2]).errors?.summary).snap(
// attest(stringArray([1, 2]).toString()).snap(
// "Item at index 0 must be a string (was number)\nItem at index 1 must be a string (was number)"

@@ -400,0 +398,0 @@ // )

@@ -15,7 +15,7 @@ import { attest, contextualize } from "@arktype/attest"

attest(types.a.description).equals(description)
attest(types.a(1).errors?.summary).snap(
attest(types.a(1).toString()).snap(
"must be a series of characters (was number)"
)
attest<{ a: string }>(types.b.infer)
attest(types.b({ a: true }).errors?.summary).snap(
attest(types.b({ a: true }).toString()).snap(
"a must be a series of characters (was true)"

@@ -34,3 +34,3 @@ )

)
attest(t({ monster: 196882 }).errors?.summary).snap(
attest(t({ monster: 196882 }).toString()).snap(
"monster must be the number of dimensions in the monster group (was 196882)"

@@ -43,3 +43,3 @@ )

attest<true>(t.infer)
attest(t(false).errors?.summary).snap("must be unfalse (was false)")
attest(t(false).toString()).snap("must be unfalse (was false)")
})

@@ -50,3 +50,3 @@

const t = type({ myKey: unfalse })
attest(t({ myKey: "500" }).errors?.summary).snap(
attest(t({ myKey: "500" }).toString()).snap(
`myKey must be unfalse (was "500")`

@@ -67,3 +67,3 @@ )

attest<{ myKey: false }>(t.infer)
attest(t({ myKey: true }).errors?.summary).snap(
attest(t({ myKey: true }).toString()).snap(
"myKey must be untrue (was true)"

@@ -84,8 +84,8 @@ )

age: true
}).errors?.summary
}).toString()
).snap("age must be a number (was true)")
// should give the shallow custom error
attest(user(null).errors?.summary).snap("must be a valid user (was null)")
attest(user(null).toString()).snap("must be a valid user (was null)")
})
})

@@ -80,3 +80,3 @@ // import { attest } from "@arktype/attest"

// const data = getCyclicData()
// attest(types.package(data).out).snap({
// attest(types.package(data)).snap({
// name: "arktype",

@@ -92,3 +92,3 @@ // dependencies: [{ name: "typescript" }, "(cycle)" as any as Package],

// data.contributors[0].email = "ssalbdivad"
// attest(types.package(data).errors?.summary).snap(
// attest(types.package(data).toString()).snap(
// "dependencies/1/contributors/0/email must be a valid email (was 'ssalbdivad')\ncontributors/0/email must be a valid email (was 'ssalbdivad')"

@@ -105,3 +105,3 @@ // )

// ])
// attest(nonSelfDependent(data).errors?.summary).snap(
// attest(nonSelfDependent(data).toString()).snap(
// 'must be valid (was {"name":"arktype","dependencies":[{"name":"typescript"},"(cycle)"],"contributors":[{"email":"david@arktype.io"}]})'

@@ -108,0 +108,0 @@ // )

@@ -9,3 +9,3 @@ // describe("snippets", () => {

// }
// attest(typeSnippet.errors?.summary).snap(
// attest(typeSnippet.toString()).snap(
// "contributors must be more than 1 items long (was 1)"

@@ -23,3 +23,3 @@ // )

// }
// attest(typeSnippet.errors?.summary).snap(
// attest(typeSnippet.toString()).snap(
// "device/platform must be 'android' or 'ios' (was 'enigma')"

@@ -39,3 +39,3 @@ // )

// // }
// // attest(scopeSnippet.errors?.summary).snap(
// // attest(scopeSnippet.toString()).snap(
// // "dependencies/0/dependencies/0/contributors/0/email must be a valid email (was 'david@sharktypeio')\ncontributors/0/email must be a valid email (was 'david@sharktypeio')"

@@ -42,0 +42,0 @@ // // )

@@ -16,4 +16,4 @@ import { attest, contextualize } from "@arktype/attest"

const e = new Error()
attest(t(e).out).equals(e)
attest(t({}).errors?.summary).snap("must be an Error (was object)")
attest(t(e)).equals(e)
attest(t({}).toString()).snap("must be an Error (was object)")
})

@@ -26,4 +26,4 @@ it("inherited", () => {

// attest<TypeError>(t.infer)
attest(t(e).out).equals(e)
attest(t(new Error()).errors?.summary).snap(
attest(t(e)).equals(e)
attest(t(new Error()).toString()).snap(
"must be an instance of TypeError (was Error)"

@@ -42,3 +42,3 @@ )

const sub = new Sub()
attest(t(sub).out).equals(sub)
attest(t(sub)).equals(sub)
})

@@ -65,4 +65,4 @@ it("multiple branches", () => {

const a = new ArkClass()
attest(ark(a).out).equals(a)
attest(ark({}).errors?.summary).snap(
attest(ark(a)).equals(a)
attest(ark({}).toString()).snap(
"must be an instance of ArkClass (was object)"

@@ -69,0 +69,0 @@ )

@@ -45,5 +45,5 @@ import { attest, contextualize } from "@arktype/attest"

it("chained deep intersections", () => {
const b = type({ b: "boolean" }, "=>", (o) => [o.b])
const b = type({ b: "boolean" }, "=>", o => [o.b])
const t = type({
a: ["string", "=>", (s) => s.length]
a: ["string", "=>", s => s.length]
})

@@ -50,0 +50,0 @@ .and({

@@ -9,3 +9,3 @@ // TODO: reenable

// const dataWithExtraneousB = getExtraneousB()
// attest(t(dataWithExtraneousB).out).equals(dataWithExtraneousB)
// attest(t(dataWithExtraneousB)).equals(dataWithExtraneousB)
// })

@@ -17,3 +17,3 @@ //

// })
// attest(o({ a: 2 }).errors?.summary).snap(
// attest(o({ a: 2 }).toString()).snap(
// 'a must be a string or removed (was {"a":2})'

@@ -27,4 +27,4 @@ // )

// }).configure({ keys: "distilled" })
// attest(t({ a: "ok" }).out).equals({ a: "ok" })
// attest(t(getExtraneousB()).out).snap({ a: "ok" })
// attest(t({ a: "ok" })).equals({ a: "ok" })
// attest(t(getExtraneousB())).snap({ a: "ok" })
// })

@@ -36,10 +36,10 @@ //

// })
// attest(o({ a: ["shawn@arktype.io"] }).out).snap({
// attest(o({ a: ["shawn@arktype.io"] })).snap({
// a: ["shawn@arktype.io"]
// })
// attest(o({ a: ["notAnEmail"] }).errors?.summary).snap(
// attest(o({ a: ["notAnEmail"] }).toString()).snap(
// "a/0 must be a valid email (was 'notAnEmail')"
// )
// // can handle missing keys
// attest(o({ b: ["shawn"] }).errors?.summary).snap("a must be defined")
// attest(o({ b: ["shawn"] }).toString()).snap("a must be defined")
// })

@@ -52,7 +52,7 @@ //

// // can distill to first branch
// attest(o({ a: "to", z: "bra" }).out).snap({ a: "to" })
// attest(o({ a: "to", z: "bra" })).snap({ a: "to" })
// // can distill to second branch
// attest(o({ b: true, c: false }).out).snap({ b: true })
// attest(o({ b: true, c: false })).snap({ b: true })
// // can handle missing keys
// attest(o({ a: 2 }).errors?.summary).snap(
// attest(o({ a: 2 }).toString()).snap(
// 'a must be a string or b must be defined (was {"a":2})'

@@ -66,4 +66,4 @@ // )

// }).configure({ keys: "strict" })
// attest(t({ a: "ok" }).out).equals({ a: "ok" })
// attest(t(getExtraneousB()).errors?.summary).snap("b must be removed")
// attest(t({ a: "ok" })).equals({ a: "ok" })
// attest(t(getExtraneousB()).toString()).snap("b must be removed")
// })

@@ -75,7 +75,7 @@ //

// })
// attest(o({ a: ["shawn"] }).out).snap({ a: ["shawn"] })
// attest(o({ a: [2] }).errors?.summary).snap(
// attest(o({ a: ["shawn"] })).snap({ a: ["shawn"] })
// attest(o({ a: [2] }).toString()).snap(
// "a/0 must be a string (was number)"
// )
// attest(o({ b: ["shawn"] }).errors?.summary).snap(
// attest(o({ b: ["shawn"] }).toString()).snap(
// "b must be removed\na must be defined"

@@ -82,0 +82,0 @@ // )

import { attest, contextualize } from "@arktype/attest"
import { rawSchema } from "@arktype/schema"
import { type } from "arktype"
import { ark, type } from "arktype"

@@ -31,3 +31,3 @@ contextualize(

attest<string>(string.infer)
attest(string("string").out).snap("string")
attest(string("string")).snap("string")
})

@@ -43,2 +43,8 @@

it("any in expression", () => {
const t = type("string&any")
attest<any>(t.infer)
attest(t.json).equals(ark.string.json)
})
it("boolean", () => {

@@ -64,2 +70,9 @@ const boolean = type("boolean")

// TODO: ??
it("never in union", () => {
const t = type("string|never")
attest<string>(t.infer)
attest(t.json).equals(ark.string.json)
})
it("unknown", () => {

@@ -84,7 +97,7 @@ const expected = rawSchema({})

// const integer = type("integer")
// attest(integer(123).out).equals(123)
// attest(integer("123").errors?.summary).equals(
// attest(integer(123)).equals(123)
// attest(integer("123").toString()).equals(
// "must be a number (was string)"
// )
// attest(integer(12.12).errors?.summary).equals(
// attest(integer(12.12).toString()).equals(
// "must be an integer (was 12.12)"

@@ -95,4 +108,4 @@ // )

// const alpha = type("alpha")
// attest(alpha("user").out).equals("user")
// attest(alpha("user123").errors?.summary).equals(
// attest(alpha("user")).equals("user")
// attest(alpha("user123").toString()).equals(
// "must be only letters (was 'user123')"

@@ -103,6 +116,6 @@ // )

// const alphanumeric = type("alphanumeric")
// attest(alphanumeric("user123").out).equals("user123")
// attest(alphanumeric("user").out).equals("user")
// attest(alphanumeric("123").out).equals("123")
// attest(alphanumeric("abc@123").errors?.summary).equals(
// attest(alphanumeric("user123")).equals("user123")
// attest(alphanumeric("user")).equals("user")
// attest(alphanumeric("123")).equals("123")
// attest(alphanumeric("abc@123").toString()).equals(
// "must be only letters and digits (was 'abc@123')"

@@ -113,4 +126,4 @@ // )

// const lowercase = type("lowercase")
// attest(lowercase("var").out).equals("var")
// attest(lowercase("newVar").errors?.summary).equals(
// attest(lowercase("var")).equals("var")
// attest(lowercase("newVar").toString()).equals(
// "must be only lowercase letters (was 'newVar')"

@@ -121,7 +134,7 @@ // )

// const uppercase = type("uppercase")
// attest(uppercase("VAR").out).equals("VAR")
// attest(uppercase("CONST_VAR").errors?.summary).equals(
// attest(uppercase("VAR")).equals("VAR")
// attest(uppercase("CONST_VAR").toString()).equals(
// "must be only uppercase letters (was 'CONST_VAR')"
// )
// attest(uppercase("myVar").errors?.summary).equals(
// attest(uppercase("myVar").toString()).equals(
// "must be only uppercase letters (was 'myVar')"

@@ -132,4 +145,4 @@ // )

// const email = type("email")
// attest(email("shawn@mail.com").out).equals("shawn@mail.com")
// attest(email("shawn@email").errors?.summary).equals(
// attest(email("shawn@mail.com")).equals("shawn@mail.com")
// attest(email("shawn@email").toString()).equals(
// "must be a valid email (was 'shawn@email')"

@@ -140,6 +153,6 @@ // )

// const uuid = type("uuid")
// attest(uuid("f70b8242-dd57-4e6b-b0b7-649d997140a0").out).equals(
// attest(uuid("f70b8242-dd57-4e6b-b0b7-649d997140a0")).equals(
// "f70b8242-dd57-4e6b-b0b7-649d997140a0"
// )
// attest(uuid("1234").errors?.summary).equals(
// attest(uuid("1234").toString()).equals(
// "must be a valid UUID (was '1234')"

@@ -150,5 +163,5 @@ // )

// const parsedNumber = type("parsedNumber")
// attest(parsedNumber("5").out).equals(5)
// attest(parsedNumber("5.5").out).equals(5.5)
// attest(parsedNumber("five").errors?.summary).equals(
// attest(parsedNumber("5")).equals(5)
// attest(parsedNumber("5.5")).equals(5.5)
// attest(parsedNumber("five").toString()).equals(
// "must be a well-formed numeric string (was 'five')"

@@ -159,13 +172,13 @@ // )

// const parsedInteger = type("parsedInteger")
// attest(parsedInteger("5").out).equals(5)
// attest(parsedInteger("5.5").errors?.summary).equals(
// attest(parsedInteger("5")).equals(5)
// attest(parsedInteger("5.5").toString()).equals(
// "must be a well-formed integer string (was '5.5')"
// )
// attest(parsedInteger("five").errors?.summary).equals(
// attest(parsedInteger("five").toString()).equals(
// "must be a well-formed integer string (was 'five')"
// )
// attest(parsedInteger(5).errors?.summary).equals(
// attest(parsedInteger(5).toString()).equals(
// "must be a string (was number)"
// )
// attest(parsedInteger("9007199254740992").errors?.summary).equals(
// attest(parsedInteger("9007199254740992").toString()).equals(
// "must be an integer in the range Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER (was '9007199254740992')"

@@ -179,6 +192,6 @@ // )

// )
// attest(parsedDate("foo").errors?.summary).equals(
// attest(parsedDate("foo").toString()).equals(
// "must be a valid date (was 'foo')"
// )
// attest(parsedDate(5).errors?.summary).equals(
// attest(parsedDate(5).toString()).equals(
// "must be a string (was number)"

@@ -189,4 +202,4 @@ // )

// const json = type("json")
// attest(json('{"a": "hello"}').out).equals({ a: "hello" })
// attest(json(123).errors?.summary).equals(
// attest(json('{"a": "hello"}')).equals({ a: "hello" })
// attest(json(123).toString()).equals(
// "must be a JSON-parsable string (was number)"

@@ -197,5 +210,5 @@ // )

// const validCC = "5489582921773376"
// attest(ark.creditCard(validCC).out).equals(validCC)
// attest(ark.creditCard(validCC)).equals(validCC)
// // Regex validation
// attest(ark.creditCard("0".repeat(16)).errors?.summary).equals(
// attest(ark.creditCard("0".repeat(16)).toString()).equals(
// "must be a valid credit card number (was '0000000000000000')"

@@ -205,3 +218,3 @@ // )

// attest(
// ark.creditCard(validCC.slice(0, -1) + "0").errors?.summary
// ark.creditCard(validCC.slice(0, -1) + "0").toString()
// ).equals(

@@ -212,4 +225,4 @@ // "must be a valid credit card number (was '5489582921773370')"

// it("semver", () => {
// attest(ark.semver("1.0.0").out).equals("1.0.0")
// attest(ark.semver("-1.0.0").errors?.summary).equals(
// attest(ark.semver("1.0.0")).equals("1.0.0")
// attest(ark.semver("-1.0.0").toString()).equals(
// "must be a valid semantic version (see https://semver.org/) (was '-1.0.0')"

@@ -216,0 +229,0 @@ // )

@@ -18,4 +18,4 @@ import { attest, contextualize } from "@arktype/attest"

attest<symbol>(t.infer)
attest(t(s).out).equals(s)
attest(t("test").errors?.summary).snap(
attest(t(s)).equals(s)
attest(t("test").toString()).snap(
'must be (symbol anonymous) (was "test")'

@@ -22,0 +22,0 @@ )

@@ -6,5 +6,5 @@ import { bench } from "@arktype/attest"

const matcher = match()
.when("string", (s) => s)
.when("number", (n) => n)
.when("boolean", (b) => b)
.when("string", s => s)
.when("number", n => n)
.when("boolean", b => b)
.orThrow()

@@ -22,5 +22,5 @@

.only<string | number | boolean>()
.when("string", (s) => s)
.when("number", (n) => n)
.when("boolean", (b) => b)
.when("string", s => s)
.when("number", n => n)
.when("boolean", b => b)
.finalize()

@@ -27,0 +27,0 @@

import { attest, contextualize } from "@arktype/attest"
import type { Narrowed, Out, of, string } from "@arktype/schema"
import { type equals, reference } from "@arktype/util"
import { type Type, type } from "arktype"
import { reference, type equals } from "@arktype/util"
import { type, type Type } from "arktype"

@@ -13,11 +13,9 @@ contextualize(() => {

attest(odd.json).equals({ domain: "number", predicate: [isOddRef] })
attest(odd(1).out).equals(1)
attest(odd(2).errors?.summary).snap(
"must be valid according to isOdd (was 2)"
)
attest(odd(1)).equals(1)
attest(odd(2).toString()).snap("must be valid according to isOdd (was 2)")
})
it("implicit problem anonymous", () => {
const even = type("number", ":", (n) => n % 2 === 0)
attest(even(1).errors?.summary).snap(
const even = type("number", ":", n => n % 2 === 0)
attest(even(1).toString()).snap(
"must be valid according to an anonymous predicate (was 1)"

@@ -31,5 +29,5 @@ )

":",
(n, ctx) => n % 3 === 0 || ctx.invalid({ expected: "divisible by 3" })
(n, ctx) => n % 3 === 0 || ctx.invalid("divisible by 3")
])
attest(even(1).errors?.summary).snap("must be divisible by 3 (was 1)")
attest(even(1).toString()).snap("must be divisible by 3 (was 1)")
})

@@ -45,5 +43,4 @@

({ a, b }, ctx) => {
if (a === b) {
return true
}
if (a === b) return true
ctx.error({ expected: "equal to b", path: ["a"] })

@@ -54,4 +51,4 @@ ctx.error({ expected: "equal to a", path: ["b"] })

])
attest(abEqual({ a: 1, b: 1 }).out).equals({ a: 1, b: 1 })
attest(abEqual({ a: 1, b: 2 }).errors?.summary).snap(
attest(abEqual({ a: 1, b: 1 })).equals({ a: 1, b: 1 })
attest(abEqual({ a: 1, b: 2 }).toString()).snap(
'a must be equal to b (was {"a":1,"b":2})\nb must be equal to a (was {"a":1,"b":2})'

@@ -72,7 +69,4 @@ )

attest<number | boolean[]>(
type([
"number|boolean[]",
":",
(data) => validateNumberOrBooleanList(data)
]).infer
type(["number|boolean[]", ":", data => validateNumberOrBooleanList(data)])
.infer
)

@@ -93,4 +87,4 @@ attest(() => {

attest<Type<string.narrowed>>(palindrome)
attest(palindrome("dad").out).snap("dad")
attest(palindrome("david").errors?.summary).snap(
attest(palindrome("dad")).snap("dad")
attest(palindrome("david").toString()).snap(
'must be a palindrome (was "david")'

@@ -102,3 +96,3 @@ )

const t = type("string")
.morph((s) => s.length)
.pipe(s => s.length)
.narrow((n): n is 5 => n === 5)

@@ -105,0 +99,0 @@

@@ -95,5 +95,5 @@ import { attest, contextualize } from "@arktype/attest"

// const o = type({ "a?": "string" }).configure({ keys: "strict" })
// attest(o({ a: "a" }).out).snap({ a: "a" })
// attest(o({}).out).snap({})
// attest(o({ a: 1 }).errors?.summary).snap("a must be a string (was number)")
// attest(o({ a: "a" })).snap({ a: "a" })
// attest(o({})).snap({})
// attest(o({ a: 1 }).toString()).snap("a must be a string (was number)")
// })

@@ -105,3 +105,3 @@

// })
// attest(t({ a: 1, b: 2 }).errors?.summary).snap(
// attest(t({ a: 1, b: 2 }).toString()).snap(
// "a must be a string (was number)\nb must be boolean (was number)"

@@ -108,0 +108,0 @@ // )

@@ -109,3 +109,3 @@ import { bench } from "@arktype/attest"

bench("filter-tuple", () => {
const _ = type(["boolean", ":", (b) => b])
const _ = type(["boolean", ":", b => b])
})

@@ -116,3 +116,3 @@ .median([8.04, "us"])

bench("filter-chain", () => {
const _ = type("boolean").narrow((b) => b)
const _ = type("boolean").narrow(b => b)
})

@@ -123,3 +123,3 @@ .median([12.19, "us"])

bench("morph-tuple", () => {
const _ = type(["boolean", "=>", (b) => b])
const _ = type(["boolean", "=>", b => b])
})

@@ -130,5 +130,5 @@ .median([8.96, "us"])

bench("morph-chain", () => {
const _ = type("boolean").morph((b) => b)
const _ = type("boolean").pipe(b => b)
})
.median([2.98, "us"])
.types([26, "instantiations"])

@@ -56,18 +56,8 @@ import { attest, contextualize } from "@arktype/attest"

const $ = scope({
a: ["string", "=>", (s) => s.length]
a: ["string", "=>", s => s.length]
})
attest<{ a: number }>($.infer)
// TODO: API?
// attest<{ a: string }>($.in.infer)
attest<{ a: string }>($.inferIn)
})
// TODO: remove if not preserving
// it("scope.scope", () => {
// const $ = scope({
// a: "string"
// })
// const importer = $.scope({ b: "a[]" })
// attest<{ b: string[] }>(importer.infer)
// const t = importer.type("b")
// attest(t.json).equals(type("string[]").json)
// })

@@ -155,4 +145,4 @@ it("infers its own helpers", () => {

const { out: data } = X({ pear: { tasty: true } })
attest(data).snap({ pear: { tasty: true } })
const out = X({ pear: { tasty: true } })
attest(out).snap({ pear: { tasty: true } })
})

@@ -159,0 +149,0 @@ describe("define", () => {

@@ -7,4 +7,4 @@ import { attest, contextualize } from "@arktype/attest"

const t = type("number%2")
attest(t(4).out).snap(4)
attest(t(5).errors?.summary).snap("must be a multiple of 2 (was 5)")
attest(t(4)).snap(4)
attest(t(5).toString()).snap("must be a multiple of 2 (was 5)")
})

@@ -14,4 +14,4 @@

const t = type("number>2")
attest(t(3).out).snap(3)
attest(t(2).errors?.summary).snap("must be more than 2 (was 2)")
attest(t(3)).snap(3)
attest(t(2).toString()).snap("must be more than 2 (was 2)")
})

@@ -21,4 +21,4 @@

const t = type("number")
attest(t(5).out).snap(5)
attest(t("foo").errors?.summary).snap("must be a number (was string)")
attest(t(5)).snap(5)
attest(t("foo").toString()).snap("must be a number (was string)")
})

@@ -28,4 +28,4 @@

const t = type("/.*@arktype.io/")
attest(t("shawn@arktype.io").out).snap("shawn@arktype.io")
attest(t("shawn@hotmail.com").errors?.summary).snap(
attest(t("shawn@arktype.io")).snap("shawn@arktype.io")
attest(t("shawn@hotmail.com").toString()).snap(
'must be matched by .*@arktype.io (was "shawn@hotmail.com")'

@@ -41,7 +41,7 @@ )

})
attest(t({ name: "Shawn", age: 99 }).out).snap({
attest(t({ name: "Shawn", age: 99 })).snap({
name: "Shawn",
age: 99
})
attest(t({ name: "Shawn" }).errors?.summary).snap("age must be defined")
attest(t({ name: "Shawn" }).toString()).snap("age must be defined")
})

@@ -54,8 +54,8 @@

divisor: {
expected: (ctx) => `% ${ctx.rule} !== 0`,
problem: (ctx) => `${ctx.actual} ${ctx.expected}`
expected: ctx => `% ${ctx.rule} !== 0`,
problem: ctx => `${ctx.actual} ${ctx.expected}`
}
}
).export()
attest(types.isEven(3).errors?.summary).snap("3 % 2 !== 0")
attest(types.isEven(3).toString()).snap("3 % 2 !== 0")
})

@@ -65,7 +65,5 @@

const t = type("string|number[]")
attest(t([1]).out).snap([1])
attest(t("hello").out).snap("hello")
attest(t(2).errors?.summary).snap(
"must be a string or an array (was number)"
)
attest(t([1])).snap([1])
attest(t("hello")).snap("hello")
attest(t(2).toString()).snap("must be a string or an array (was number)")
})

@@ -76,4 +74,4 @@

const data: typeof t.infer = ["foo", 5, "boo", []]
attest(t(data).out).equals(data)
attest(t(["hello"]).errors?.summary).snap(
attest(t(data)).equals(data)
attest(t(["hello"]).toString()).snap(
'must be exactly length 4 (was ["hello"])'

@@ -84,6 +82,9 @@ )

it("branches", () => {
const t = type([{ a: "string" }, "|", { b: "boolean" }])
attest(t({ a: "ok" }).out).snap({ a: "ok" })
attest(t({ b: true }).out).snap({ b: true })
attest(t({}).errors?.summary).snap("a must be defined or b must be defined")
const t = type({ bar: "boolean" }, "|", { foo: "string" })
attest(t({ foo: "ok" })).snap({ foo: "ok" })
attest(t({ bar: true })).snap({ bar: true })
attest(t({}).toString()).snap("bar must be defined or foo must be defined")
attest(t({ bar: "swapped", foo: true }).toString()).snap(
'bar must be boolean (was "swapped") or foo must be a string (was true)'
)
})

@@ -93,5 +94,5 @@

const t = type({ key: [{ a: "string" }, "|", { b: "boolean" }] })
attest(t({ key: { a: "ok" } }).out).snap({ key: { a: "ok" } })
attest(t({ key: { b: true } }).out).snap({ key: { b: true } })
attest(t({ key: {} }).errors?.summary).snap(
attest(t({ key: { a: "ok" } })).snap({ key: { a: "ok" } })
attest(t({ key: { b: true } })).snap({ key: { b: true } })
attest(t({ key: {} }).toString()).snap(
"key.a must be defined or key.b must be defined"

@@ -103,8 +104,8 @@ )

const t = type({ a: "string" }).or({ a: "null" }).or({ a: "number" })
attest(t({ a: "ok" }).out).snap({ a: "ok" })
attest(t({ a: 5 }).out).snap({ a: 5 })
attest(t({ a: "ok" })).snap({ a: "ok" })
attest(t({ a: 5 })).snap({ a: 5 })
// value isn't present
attest(t({}).errors?.summary).snap("a must be defined")
attest(t({}).toString()).snap("a must be defined")
// unsatisfying value
attest(t({ a: false }).errors?.summary).snap(
attest(t({ a: false }).toString()).snap(
"a must be a number, a string or null (was false)"

@@ -121,4 +122,4 @@ )

}).export()
attest(types.d({}).errors?.summary).snap("foo must be defined")
attest(types.d({ foo: null }).errors?.summary).snap(
attest(types.d({}).toString()).snap("foo must be defined")
attest(types.d({ foo: null }).toString()).snap(
"foo must be a function, a number or a string (was null)"

@@ -130,3 +131,3 @@ )

const naturalNumber = type("integer>0")
attest(naturalNumber(-1.2).errors?.summary).snap(
attest(naturalNumber(-1.2).toString()).snap(
`must be...

@@ -139,3 +140,3 @@ • an integer

})
attest(naturalAtPath({ natural: -0.1 }).errors?.summary).snap(
attest(naturalAtPath({ natural: -0.1 }).toString()).snap(
`natural must be...

@@ -142,0 +143,0 @@ • an integer

@@ -8,8 +8,5 @@ import { attest, contextualize } from "@arktype/attest"

const t = type("string")
const { out, errors: errors } = t("")
if (errors) {
errors.throw()
} else {
attest<string>(out)
}
const out = t("")
if (out instanceof type.errors) out.throw()
else attest<string>(out)
})

@@ -23,12 +20,13 @@

attest<number>(data)
} else {
throw new Error()
}
} else throw new Error()
attest(t.allows(5)).equals(false)
})
// TODO: ?
it("errors can be thrown", () => {
const t = type("number")
try {
attest(t("invalid").errors?.throw())
const result = t("invalid")
attest(result instanceof type.errors && result.throw())
} catch (e) {

@@ -35,0 +33,0 @@ attest(e instanceof ArkError).equals(true)

@@ -1,2 +0,7 @@

import { type Ark, type inferred, keywordNodes } from "@arktype/schema"
import {
type Ark,
type ArkErrors,
type inferred,
keywordNodes
} from "@arktype/schema"
import type { Generic } from "./generic.js"

@@ -28,18 +33,16 @@ import type { MatchParser } from "./match.js"

export const type: TypeParser<{}> = ambient.type.bind(ambient) as never
export const type: TypeParser<{}> = ambient.type as never
export namespace type {
export type cast<to> = {
[inferred]?: to
export type cast<t> = {
[inferred]?: t
}
export type errors = ArkErrors
}
export const match: MatchParser<{}> = ambient.match.bind(ambient) as never
export const match: MatchParser<{}> = ambient.match as never
export const define: DefinitionParser<{}> = ambient.define.bind(
ambient
) as never
export const define: DefinitionParser<{}> = ambient.define as never
export const declare: DeclarationParser<{}> = ambient.declare.bind(
ambient
) as never
export const declare: DeclarationParser<{}> = ambient.declare as never

@@ -7,3 +7,3 @@ import {

} from "@arktype/schema"
import { Callable, type conform, flatMorph } from "@arktype/util"
import { Callable, type conform } from "@arktype/util"
import type { inferDefinition } from "./parser/definition.js"

@@ -61,9 +61,11 @@ import type {

super((...args: unknown[]) => {
const argNodes = flatMorph(params, (i, param: string) => [
param,
$.parseRoot(args[i])
])
return $.parseRoot(def, { args: argNodes }) as never
// const argNodes = flatMorph(params, (i, param: string) => [
// param,
// $.parseRoot(args[i])
// ])
// { args: argNodes }
args
return $.parseRoot(def) as never
})
}
}

@@ -0,9 +1,3 @@

import type { Narrowed, distillOut, inferIntersection } from "@arktype/schema"
import type {
Morph,
Narrowed,
RawSchema,
distillOut,
inferIntersection
} from "@arktype/schema"
import type {
ErrorMessage,

@@ -166,65 +160,60 @@ isDisjoint,

export const createMatchParser = <$>($: Scope): MatchParser<$> => {
const matchParser = (isRestricted: boolean) => {
const handledCases: { when: RawSchema; then: Morph }[] = []
let defaultCase: ((x: unknown) => unknown) | null = null
return (() => {}).bind($) as never
// const matchParser = (isRestricted: boolean) => {
// const handledCases: { when: RawSchema; then: Morph }[] = []
// let defaultCase: ((x: unknown) => unknown) | null = null
const parser = {
when: (when: unknown, then: Morph) => {
handledCases.push({ when: $.parseRoot(when, {}), then })
// const parser = {
// when: (when: unknown, then: Morph) => {
// handledCases.push({ when: $.parseRoot(when, {}), then })
return parser
},
// return parser
// },
finalize: () => {
// TODO: exhaustiveness checking
// const branches = handledCases.flatMap(({ when, then }) => {
// if (when.root.kind === "union") {
// return when.root.branches.map((branch) => ({
// in: branch,
// morph: then
// }))
// }
// if (when.root.kind === "morph") {
// return [{ in: when, morph: [when.root.morph, then] }]
// }
// return [{ in: when.root, morph: then }]
// })
// if (defaultCase) {
// branches.push({ in: new Type("unknown", $), morph: defaultCase })
// }
// const matchers = schema.union({
// branches,
// ordered: true
// })
// return (data: unknown) => {
// const result = matchers.apply(data)
// if (result.errors) {
// throw result.errors
// }
// return result.out
// }
},
// finalize: () => {
// // TODO: exhaustiveness checking
// const branches = handledCases.flatMap(({ when, then }) => {
// if (when.kind === "union") {
// return when.branches.map((branch) => ({
// from: branch,
// morph: then
// }))
// }
// if (when.kind === "morph") {
// return [{ from: when, morph: [when.morph, then] }]
// }
// return [{ from: when, morph: then }]
// })
// if (defaultCase) {
// branches.push({ from: keywordNodes.unknown, morph: defaultCase })
// }
// const matchers = $.node("union", {
// branches,
// ordered: true
// })
// return matchers.assert
// },
orThrow: () => {
// implicitly finalize, we don't need to do anything else because we throw either way
return parser.finalize()
},
// orThrow: () => {
// // implicitly finalize, we don't need to do anything else because we throw either way
// return parser.finalize()
// },
default: (x: unknown) => {
if (x instanceof Function) {
defaultCase = x as never
} else {
defaultCase = () => x
}
// default: (x: unknown) => {
// if (x instanceof Function) {
// defaultCase = x as never
// } else {
// defaultCase = () => x
// }
return parser.finalize()
}
}
// return parser.finalize()
// }
// }
return parser
}
// return parser
// }
return Object.assign(() => matchParser(false), {
only: () => matchParser(true)
}) as never
// return Object.assign(() => matchParser(false), {
// only: () => matchParser(true)
// }) as never
}

@@ -1,2 +0,2 @@

import { type Ark, type inferred } from "@arktype/schema";
import { type Ark, type ArkErrors, type inferred } from "@arktype/schema";
import type { Generic } from "./generic.js";

@@ -20,5 +20,6 @@ import type { MatchParser } from "./match.js";

export declare namespace type {
type cast<to> = {
[inferred]?: to;
type cast<t> = {
[inferred]?: t;
};
type errors = ArkErrors;
}

@@ -25,0 +26,0 @@ export declare const match: MatchParser<{}>;

@@ -7,6 +7,6 @@ import { keywordNodes } from "@arktype/schema";

export const ark = ambient.export();
export const type = ambient.type.bind(ambient);
export const match = ambient.match.bind(ambient);
export const define = ambient.define.bind(ambient);
export const declare = ambient.declare.bind(ambient);
export const type = ambient.type;
export const match = ambient.match;
export const define = ambient.define;
export const declare = ambient.declare;
//# sourceMappingURL=ark.js.map
import { arkKind } from "@arktype/schema";
import { Callable, flatMorph } from "@arktype/util";
import { Callable } from "@arktype/util";
export class Generic extends Callable {

@@ -12,7 +12,9 @@ params;

super((...args) => {
const argNodes = flatMorph(params, (i, param) => [
param,
$.parseRoot(args[i])
]);
return $.parseRoot(def, { args: argNodes });
// const argNodes = flatMorph(params, (i, param: string) => [
// param,
// $.parseRoot(args[i])
// ])
// { args: argNodes }
args;
return $.parseRoot(def);
});

@@ -19,0 +21,0 @@ this.params = params;

export const createMatchParser = ($) => {
const matchParser = (isRestricted) => {
const handledCases = [];
let defaultCase = null;
const parser = {
when: (when, then) => {
handledCases.push({ when: $.parseRoot(when, {}), then });
return parser;
},
finalize: () => {
// TODO: exhaustiveness checking
// const branches = handledCases.flatMap(({ when, then }) => {
// if (when.root.kind === "union") {
// return when.root.branches.map((branch) => ({
// in: branch,
// morph: then
// }))
// }
// if (when.root.kind === "morph") {
// return [{ in: when, morph: [when.root.morph, then] }]
// }
// return [{ in: when.root, morph: then }]
// })
// if (defaultCase) {
// branches.push({ in: new Type("unknown", $), morph: defaultCase })
// }
// const matchers = schema.union({
// branches,
// ordered: true
// })
// return (data: unknown) => {
// const result = matchers.apply(data)
// if (result.errors) {
// throw result.errors
// }
// return result.out
// }
},
orThrow: () => {
// implicitly finalize, we don't need to do anything else because we throw either way
return parser.finalize();
},
default: (x) => {
if (x instanceof Function) {
defaultCase = x;
}
else {
defaultCase = () => x;
}
return parser.finalize();
}
};
return parser;
};
return Object.assign(() => matchParser(false), {
only: () => matchParser(true)
});
return (() => { }).bind($);
// const matchParser = (isRestricted: boolean) => {
// const handledCases: { when: RawSchema; then: Morph }[] = []
// let defaultCase: ((x: unknown) => unknown) | null = null
// const parser = {
// when: (when: unknown, then: Morph) => {
// handledCases.push({ when: $.parseRoot(when, {}), then })
// return parser
// },
// finalize: () => {
// // TODO: exhaustiveness checking
// const branches = handledCases.flatMap(({ when, then }) => {
// if (when.kind === "union") {
// return when.branches.map((branch) => ({
// from: branch,
// morph: then
// }))
// }
// if (when.kind === "morph") {
// return [{ from: when, morph: [when.morph, then] }]
// }
// return [{ from: when, morph: then }]
// })
// if (defaultCase) {
// branches.push({ from: keywordNodes.unknown, morph: defaultCase })
// }
// const matchers = $.node("union", {
// branches,
// ordered: true
// })
// return matchers.assert
// },
// orThrow: () => {
// // implicitly finalize, we don't need to do anything else because we throw either way
// return parser.finalize()
// },
// default: (x: unknown) => {
// if (x instanceof Function) {
// defaultCase = x as never
// } else {
// defaultCase = () => x
// }
// return parser.finalize()
// }
// }
// return parser
// }
// return Object.assign(() => matchParser(false), {
// only: () => matchParser(true)
// }) as never
};
//# sourceMappingURL=match.js.map

@@ -9,10 +9,10 @@ import { type nominal } from "@arktype/util";

export declare const parseGenericParams: (def: string) => string[];
export type parseGenericParams<def extends string> = $parseParams<def, "", []> extends infer result extends string[] ? "" extends result[number] ? GenericParamsParseError<emptyGenericParameterMessage> : result : never;
export type parseGenericParams<def extends string> = _parseParams<def, "", []> extends infer result extends string[] ? "" extends result[number] ? GenericParamsParseError<emptyGenericParameterMessage> : result : never;
export declare const emptyGenericParameterMessage = "An empty string is not a valid generic parameter name";
export type emptyGenericParameterMessage = typeof emptyGenericParameterMessage;
type $parseParams<unscanned extends string, param extends string, result extends string[]> = unscanned extends `${infer lookahead}${infer nextUnscanned}` ? lookahead extends "," ? $parseParams<nextUnscanned, "", [...result, param]> : lookahead extends Scanner.WhiteSpaceToken ? param extends "" ? $parseParams<Scanner.skipWhitespace<nextUnscanned>, "", result> : Scanner.skipWhitespace<nextUnscanned> extends (`${infer nextNonWhitespace}${infer rest}`) ? nextNonWhitespace extends "," ? $parseParams<rest, "", [...result, param]> : GenericParamsParseError<writeUnexpectedCharacterMessage<nextNonWhitespace, ",">> : [
type _parseParams<unscanned extends string, param extends string, result extends string[]> = unscanned extends `${infer lookahead}${infer nextUnscanned}` ? lookahead extends "," ? _parseParams<nextUnscanned, "", [...result, param]> : lookahead extends Scanner.WhiteSpaceToken ? param extends "" ? _parseParams<Scanner.skipWhitespace<nextUnscanned>, "", result> : Scanner.skipWhitespace<nextUnscanned> extends (`${infer nextNonWhitespace}${infer rest}`) ? nextNonWhitespace extends "," ? _parseParams<rest, "", [...result, param]> : GenericParamsParseError<writeUnexpectedCharacterMessage<nextNonWhitespace, ",">> : [
...result,
param
] : $parseParams<nextUnscanned, `${param}${lookahead}`, result> : param extends "" ? result : [...result, param];
] : _parseParams<nextUnscanned, `${param}${lookahead}`, result> : param extends "" ? result : [...result, param];
export {};
//# sourceMappingURL=generic.d.ts.map
import { throwParseError } from "@arktype/util";
import { writeUnexpectedCharacterMessage } from "./string/shift/operator/operator.js";
import { Scanner } from "./string/shift/scanner.js";
export const parseGenericParams = (def) => $parseGenericParams(new Scanner(def));
export const parseGenericParams = (def) => _parseGenericParams(new Scanner(def));
export const emptyGenericParameterMessage = "An empty string is not a valid generic parameter name";
const $parseGenericParams = (scanner) => {
const _parseGenericParams = (scanner) => {
const param = scanner.shiftUntilNextTerminator();
if (param === "") {
if (param === "")
throwParseError(emptyGenericParameterMessage);
}
scanner.shiftUntilNonWhitespace();
const nextNonWhitespace = scanner.shift();
return (nextNonWhitespace === "" ? [param]
: nextNonWhitespace === "," ? [param, ...$parseGenericParams(scanner)]
: nextNonWhitespace === "," ? [param, ..._parseGenericParams(scanner)]
: throwParseError(writeUnexpectedCharacterMessage(nextNonWhitespace, ",")));
};
//# sourceMappingURL=generic.js.map

@@ -25,8 +25,7 @@ import { tsKeywords } from "@arktype/schema";

// because the currently parsed definition will overwrite them.
spreadNode.prop?.forEach((spreadRequired) => !parsedEntries.some(({ inner: innerKey }) => innerKey === spreadRequired.key) && propNodes.push(spreadRequired));
spreadNode.prop?.forEach(spreadRequired => !parsedEntries.some(({ inner: innerKey }) => innerKey === spreadRequired.key) && propNodes.push(spreadRequired));
}
for (const entry of parsedEntries) {
if (entry.kind === "spread") {
if (entry.kind === "spread")
return throwParseError(nonLeadingSpreadError);
}
if (entry.kind === "index") {

@@ -33,0 +32,0 @@ // handle key parsing first to match type behavior

import type { arkKind, GenericProps, PrivateDeclaration, writeMissingSubmoduleAccessMessage } from "@arktype/schema";
import type { BigintLiteral, charsAfterFirst, Completion, ErrorMessage, writeMalformedNumericLiteralMessage } from "@arktype/util";
import type { BigintLiteral, charsAfterFirst, Completion, ErrorMessage, isAnyOrNever, writeMalformedNumericLiteralMessage } from "@arktype/util";
import type { Comparator } from "../string/reduce/shared.js";

@@ -19,3 +19,3 @@ import type { writeInvalidGenericArgsMessage } from "../string/shift/operand/genericArgs.js";

export type writePrefixedPrivateReferenceMessage<def extends PrivateDeclaration> = `Private type references should not include '#'. Use '${charsAfterFirst<def>}' instead.`;
type validateStringAst<def extends string, $> = def extends `${infer n extends number}` ? number extends n ? ErrorMessage<writeMalformedNumericLiteralMessage<def, "number">> : undefined : def extends BigintLiteral<infer b> ? bigint extends b ? ErrorMessage<writeMalformedNumericLiteralMessage<def, "bigint">> : undefined : maybeExtractAlias<def, $> extends infer alias extends keyof $ ? $[alias] extends null ? def : def extends PrivateDeclaration ? ErrorMessage<writePrefixedPrivateReferenceMessage<def>> : $[alias] extends GenericProps ? ErrorMessage<writeInvalidGenericArgsMessage<def, $[alias]["params"], []>> : $[alias] extends {
type validateStringAst<def extends string, $> = def extends `${infer n extends number}` ? number extends n ? ErrorMessage<writeMalformedNumericLiteralMessage<def, "number">> : undefined : def extends BigintLiteral<infer b> ? bigint extends b ? ErrorMessage<writeMalformedNumericLiteralMessage<def, "bigint">> : undefined : maybeExtractAlias<def, $> extends infer alias extends keyof $ ? isAnyOrNever<$[alias]> extends true ? def : def extends PrivateDeclaration ? ErrorMessage<writePrefixedPrivateReferenceMessage<def>> : $[alias] extends GenericProps ? ErrorMessage<writeInvalidGenericArgsMessage<def, $[alias]["params"], []>> : $[alias] extends {
[arkKind]: "module";

@@ -22,0 +22,0 @@ } ? ErrorMessage<writeMissingSubmoduleAccessMessage<def>> : undefined : def extends ErrorMessage ? def : undefined;

@@ -42,5 +42,4 @@ import { isKeyOf, throwInternalError, throwParseError } from "@arktype/util";

finalize(finalizer) {
if (this.groups.length) {
if (this.groups.length)
return this.error(writeUnclosedGroupMessage(")"));
}
this.finalizeBranches();

@@ -51,5 +50,4 @@ this.finalizer = finalizer;

const invertedComparator = invertedComparators[comparator];
if (!isKeyOf(invertedComparator, minComparators)) {
if (!isKeyOf(invertedComparator, minComparators))
return this.error(writeUnpairableComparatorMessage(comparator));
}
if (this.branches.leftBound) {

@@ -73,5 +71,4 @@ return this.error(writeMultipleLeftBoundsMessage(this.branches.leftBound.limit, this.branches.leftBound.comparator, limit, invertedComparator));

}
else {
else
this.applyPrefixes();
}
}

@@ -81,5 +78,4 @@ finalizeGroup() {

const topBranchState = this.groups.pop();
if (!topBranchState) {
if (!topBranchState)
return this.error(writeUnmatchedGroupCloseMessage(this.scanner.unscanned));
}
this.branches = topBranchState;

@@ -86,0 +82,0 @@ }

@@ -12,11 +12,9 @@ import { throwParseError, tryParseNumber } from "@arktype/util";

const stringParsedDate = new Date(source);
if (isValidDate(stringParsedDate)) {
if (isValidDate(stringParsedDate))
return stringParsedDate;
}
const epochMillis = tryParseNumber(source);
if (epochMillis !== undefined) {
const numberParsedDate = new Date(epochMillis);
if (isValidDate(numberParsedDate)) {
if (isValidDate(numberParsedDate))
return numberParsedDate;
}
}

@@ -23,0 +21,0 @@ return errorOnFail ?

@@ -5,7 +5,6 @@ import { isKeyOf } from "@arktype/util";

const enclosed = s.scanner.shiftUntil(untilLookaheadIsClosing[enclosingTokens[enclosing]]);
if (s.scanner.lookahead === "") {
if (s.scanner.lookahead === "")
return s.error(writeUnterminatedEnclosedMessage(enclosed, enclosing));
}
// Shift the scanner one additional time for the second enclosing token
const token = `${enclosing}${enclosed}${s.scanner.shift()}`;
s.scanner.shift();
if (enclosing === "/") {

@@ -19,5 +18,4 @@ // fail parsing if the regex is invalid

}
else if (isKeyOf(enclosing, enclosingQuote)) {
else if (isKeyOf(enclosing, enclosingQuote))
s.root = s.ctx.$.node("unit", { unit: enclosed });
}
else {

@@ -44,5 +42,5 @@ const date = tryParseDate(enclosed, writeInvalidDateMessage(enclosed));

export const untilLookaheadIsClosing = {
"'": (scanner) => scanner.lookahead === `'`,
'"': (scanner) => scanner.lookahead === `"`,
"/": (scanner) => scanner.lookahead === `/`
"'": scanner => scanner.lookahead === `'`,
'"': scanner => scanner.lookahead === `"`,
"/": scanner => scanner.lookahead === `/`
};

@@ -49,0 +47,0 @@ const enclosingCharDescriptions = {

@@ -12,5 +12,5 @@ import type { RawSchema } from "@arktype/schema";

export declare const parseGenericArgs: (name: string, params: string[], s: DynamicState) => ParsedArgs<RawSchema[]>;
export type parseGenericArgs<name extends string, params extends string[], unscanned extends string, $, args> = $parseGenericArgs<name, params, unscanned, $, args, [], []>;
declare const $parseGenericArgs: (name: string, params: string[], s: DynamicState, argDefs: string[], argNodes: RawSchema[]) => ParsedArgs<RawSchema[]>;
type $parseGenericArgs<name extends string, params extends string[], unscanned extends string, $, args, argDefs extends string[], argAsts extends unknown[]> = parseUntilFinalizer<state.initialize<unscanned>, $, args> extends (infer finalArgState extends StaticState) ? {
export type parseGenericArgs<name extends string, params extends string[], unscanned extends string, $, args> = _parseGenericArgs<name, params, unscanned, $, args, [], []>;
declare const _parseGenericArgs: (name: string, params: string[], s: DynamicState, argDefs: string[], argNodes: RawSchema[]) => ParsedArgs<RawSchema[]>;
type _parseGenericArgs<name extends string, params extends string[], unscanned extends string, $, args, argDefs extends string[], argAsts extends unknown[]> = parseUntilFinalizer<state.initialize<unscanned>, $, args> extends (infer finalArgState extends StaticState) ? {
defs: [

@@ -26,3 +26,3 @@ ...argDefs,

unscanned: infer nextUnscanned extends string;
}) ? finalArgState["finalizer"] extends ">" ? nextAsts["length"] extends params["length"] ? ParsedArgs<nextAsts, nextUnscanned> : state.error<writeInvalidGenericArgsMessage<name, params, nextDefs>> : finalArgState["finalizer"] extends "," ? $parseGenericArgs<name, params, nextUnscanned, $, args, nextDefs, nextAsts> : finalArgState["finalizer"] extends ErrorMessage ? finalArgState : state.error<writeUnclosedGroupMessage<">">> : never : never;
}) ? finalArgState["finalizer"] extends ">" ? nextAsts["length"] extends params["length"] ? ParsedArgs<nextAsts, nextUnscanned> : state.error<writeInvalidGenericArgsMessage<name, params, nextDefs>> : finalArgState["finalizer"] extends "," ? _parseGenericArgs<name, params, nextUnscanned, $, args, nextDefs, nextAsts> : finalArgState["finalizer"] extends ErrorMessage ? finalArgState : state.error<writeUnclosedGroupMessage<">">> : never : never;
export declare const writeInvalidGenericArgsMessage: <name extends string, params extends string[], argDefs extends string[]>(name: name, params: params, argDefs: argDefs) => `${name}<${join<params, ", ", "">}> requires exactly ${params["length"]} args (got ${argDefs["length"]}${argDefs["length"] extends 0 ? "" : `: ${join<argDefs, ",", "">}`})`;

@@ -29,0 +29,0 @@ export type writeInvalidGenericArgsMessage<name extends string, params extends string[], argDefs extends string[]> = `${name}<${join<params, ", ">}> requires exactly ${params["length"]} args (got ${argDefs["length"]}${argDefs["length"] extends (0) ? "" : `: ${join<argDefs, ",">}`})`;

import { writeUnclosedGroupMessage } from "../../reduce/shared.js";
export const parseGenericArgs = (name, params, s) => $parseGenericArgs(name, params, s, [], []);
const $parseGenericArgs = (name, params, s, argDefs, argNodes) => {
export const parseGenericArgs = (name, params, s) => _parseGenericArgs(name, params, s, [], []);
const _parseGenericArgs = (name, params, s, argDefs, argNodes) => {
const argState = s.parseUntilFinalizer();

@@ -17,5 +17,4 @@ // remove the finalizing token from the argDef

}
if (argState.finalizer === ",") {
return $parseGenericArgs(name, params, s, argDefs, argNodes);
}
if (argState.finalizer === ",")
return _parseGenericArgs(name, params, s, argDefs, argNodes);
return argState.error(writeUnclosedGroupMessage(">"));

@@ -22,0 +21,0 @@ };

@@ -1,3 +0,3 @@

import { type GenericProps, RawSchema, type SchemaModule, type writeNonSubmoduleDotMessage, writeUnresolvableMessage } from "@arktype/schema";
import { type BigintLiteral, type Completion, type ErrorMessage, type join } from "@arktype/util";
import { type GenericProps, RawSchema, type writeNonSubmoduleDotMessage, writeUnresolvableMessage } from "@arktype/schema";
import { type BigintLiteral, type Completion, type ErrorMessage, type isAnyOrNever, type join } from "@arktype/util";
import type { Generic } from "../../../../generic.js";

@@ -12,6 +12,6 @@ import type { Module } from "../../../../module.js";

export declare const parseUnenclosed: (s: DynamicState) => void;
export type parseUnenclosed<s extends StaticState, $, args> = Scanner.shiftUntilNextTerminator<s["unscanned"]> extends (Scanner.shiftResult<infer token, infer unscanned>) ? token extends "keyof" ? state.addPrefix<s, "keyof", unscanned> : tryResolve<s, token, $, args> extends infer result ? result extends ErrorMessage<infer message> ? state.error<message> : result extends keyof $ ? $[result] extends GenericProps ? parseGenericInstantiation<token, $[result], state.scanTo<s, unscanned>, $, args> : state.setRoot<s, result, unscanned> : state.setRoot<s, result, unscanned> : never : never;
export type parseUnenclosed<s extends StaticState, $, args> = Scanner.shiftUntilNextTerminator<s["unscanned"]> extends (Scanner.shiftResult<infer token, infer unscanned>) ? token extends "keyof" ? state.addPrefix<s, "keyof", unscanned> : tryResolve<s, token, $, args> extends infer result ? result extends ErrorMessage<infer message> ? state.error<message> : result extends keyof $ ? isAnyOrNever<$[result]> extends true ? state.setRoot<s, result, unscanned> : $[result] extends GenericProps ? parseGenericInstantiation<token, $[result], state.scanTo<s, unscanned>, $, args> : state.setRoot<s, result, unscanned> : state.setRoot<s, result, unscanned> : never : never;
export declare const parseGenericInstantiation: (name: string, g: Generic, s: DynamicState) => RawSchema;
export type parseGenericInstantiation<name extends string, g extends GenericProps, s extends StaticState, $, args> = Scanner.skipWhitespace<s["unscanned"]> extends `<${infer unscanned}` ? parseGenericArgs<name, g["params"], unscanned, $, args> extends (infer result) ? result extends ParsedArgs<infer argAsts, infer nextUnscanned> ? state.setRoot<s, GenericInstantiationAst<g, argAsts>, nextUnscanned> : result : never : state.error<writeInvalidGenericArgsMessage<name, g["params"], []>>;
type tryResolve<s extends StaticState, token extends string, $, args> = token extends keyof $ ? token : `#${token}` extends keyof $ ? token : token extends keyof args ? token : token extends `${number}` ? token : token extends BigintLiteral ? token : token extends (`${infer submodule extends keyof $ & string}.${infer reference}`) ? $[submodule] extends (SchemaModule<infer sub$> | Module<infer sub$>) ? reference extends keyof sub$ ? token : unknown extends sub$ ? ErrorMessage<writeNonSubmoduleDotMessage<submodule>> : unresolvableError<s, reference, $[submodule], args, [submodule]> : ErrorMessage<writeNonSubmoduleDotMessage<submodule>> : unresolvableError<s, token, $, args, []>;
type tryResolve<s extends StaticState, token extends string, $, args> = token extends keyof $ ? token : `#${token}` extends keyof $ ? token : token extends keyof args ? token : token extends `${number}` ? token : token extends BigintLiteral ? token : token extends (`${infer submodule extends keyof $ & string}.${infer reference}`) ? $[submodule] extends Module<infer sub$> ? reference extends keyof sub$ ? token : unresolvableError<s, reference, $[submodule], args, [submodule]> : ErrorMessage<writeNonSubmoduleDotMessage<submodule>> : unresolvableError<s, token, $, args, []>;
/** Provide valid completions for the current token, or fallback to an

@@ -18,0 +18,0 @@ * unresolvable error if there are none */

@@ -7,8 +7,6 @@ import { RawSchema, hasArkKind, writeUnresolvableMessage } from "@arktype/schema";

const token = s.scanner.shiftUntilNextTerminator();
if (token === "keyof") {
if (token === "keyof")
s.addPrefix("keyof");
}
else {
else
s.root = unenclosedToNode(s, token);
}
};

@@ -18,5 +16,4 @@ export const parseGenericInstantiation = (name, g, s) => {

const lookahead = s.scanner.shift();
if (lookahead !== "<") {
if (lookahead !== "<")
return s.error(writeInvalidGenericArgsMessage(name, g.params, []));
}
const parsedArgs = parseGenericArgs(name, g.params, s);

@@ -49,9 +46,7 @@ const remainingChars = parsedArgs.unscanned.length;

const maybeNumber = tryParseNumber(token, { strict: true });
if (maybeNumber !== undefined) {
if (maybeNumber !== undefined)
return s.ctx.$.node("unit", { unit: maybeNumber });
}
const maybeBigint = tryParseWellFormedBigint(token);
if (maybeBigint !== undefined) {
if (maybeBigint !== undefined)
return s.ctx.$.node("unit", { unit: maybeBigint });
}
};

@@ -58,0 +53,0 @@ export const writeMissingOperandMessage = (s) => {

@@ -78,5 +78,4 @@ import { internalKeywords, jsObjects, tsKeywords, writeUnboundableMessage } from "@arktype/schema";

if (!limitNode.hasKind("unit") ||
(typeof limitNode.unit !== "number" && !(limitNode.unit instanceof Date))) {
(typeof limitNode.unit !== "number" && !(limitNode.unit instanceof Date)))
return s.error(writeInvalidLimitMessage(comparator, limitToken, "right"));
}
const limit = limitNode.unit;

@@ -86,12 +85,9 @@ // apply the newly-parsed right bound

// if the comparator is ==, both the min and max of that pair will be applied
for (const kind of getBoundKinds(comparator, typeof limit === "number" ? limit : limitToken, previousRoot, "right")) {
for (const kind of getBoundKinds(comparator, typeof limit === "number" ? limit : limitToken, previousRoot, "right"))
s.constrainRoot(kind, { rule: limit, exclusive });
}
if (!s.branches.leftBound) {
if (!s.branches.leftBound)
return;
}
// if there's an open left bound, perform additional validation and apply it
if (!isKeyOf(comparator, maxComparators)) {
if (!isKeyOf(comparator, maxComparators))
return s.error(writeUnpairableComparatorMessage(comparator));
}
const lowerBoundKind = getBoundKinds(s.branches.leftBound.comparator, s.branches.leftBound.limit, previousRoot, "left");

@@ -98,0 +94,0 @@ s.constrainRoot(lowerBoundKind[0], openLeftBoundToSchema(s.branches.leftBound));

@@ -7,5 +7,4 @@ import { tryParseInteger } from "@arktype/util";

});
if (divisor === 0) {
if (divisor === 0)
s.error(writeInvalidDivisorMessage(0));
}
s.root = s.root.constrain("divisor", divisor);

@@ -12,0 +11,0 @@ };

@@ -23,8 +23,6 @@ import { isKeyOf } from "@arktype/util";

if (condition(this, shifted)) {
if (shifted[shifted.length - 1] === Scanner.escapeToken) {
if (shifted[shifted.length - 1] === Scanner.escapeToken)
shifted = shifted.slice(0, -1);
}
else {
else
break;
}
}

@@ -31,0 +29,0 @@ shifted += this.shift();

@@ -17,5 +17,4 @@ import { throwInternalError, throwParseError } from "@arktype/util";

export const parseUntilFinalizer = (s) => {
while (s.finalizer === undefined) {
while (s.finalizer === undefined)
next(s);
}
return s;

@@ -22,0 +21,0 @@ };

@@ -18,5 +18,4 @@ import { jsObjects, makeRootAndArrayPropertiesMutable, tsKeywords } from "@arktype/schema";

if (def[i] === "?") {
if (spread) {
if (spread)
return throwParseError(spreadOptionalMessage);
}
optional = true;

@@ -26,17 +25,16 @@ i++;

if (spread) {
if (!element.extends(jsObjects.Array)) {
if (!element.extends(jsObjects.Array))
return throwParseError(writeNonArraySpreadMessage(element.expression));
}
// a spread must be distributed over branches e.g.:
// def: [string, ...(number[] | [true, false])]
// nodes: [string, ...number[]] | [string, true, false]
sequences = sequences.flatMap((base) =>
sequences = sequences.flatMap(base =>
// since appendElement mutates base, we have to shallow-ish clone it for each branch
element.branches.map((branch) => appendSpreadBranch(makeRootAndArrayPropertiesMutable(base), branch)));
element.branches.map(branch => appendSpreadBranch(makeRootAndArrayPropertiesMutable(base), branch)));
}
else {
sequences = sequences.map((base) => appendElement(base, optional ? "optional" : "required", element));
sequences = sequences.map(base => appendElement(base, optional ? "optional" : "required", element));
}
}
return ctx.$.raw.schema(sequences.map((sequence) => ({
return ctx.$.raw.schema(sequences.map(sequence => ({
proto: Array,

@@ -93,6 +91,6 @@ sequence

}
spread.prefix.forEach((node) => appendElement(base, "required", node));
spread.optional.forEach((node) => appendElement(base, "optional", node));
spread.prefix.forEach(node => appendElement(base, "required", node));
spread.optional.forEach(node => appendElement(base, "optional", node));
spread.variadic && appendElement(base, "variadic", spread.variadic);
spread.postfix.forEach((node) => appendElement(base, "required", node));
spread.postfix.forEach(node => appendElement(base, "required", node));
return base;

@@ -125,5 +123,4 @@ };

const parseBranchTuple = (def, ctx) => {
if (def[2] === undefined) {
if (def[2] === undefined)
return throwParseError(writeMissingRightOperandMessage(def[1], ""));
}
const l = ctx.$.parse(def[0], ctx);

@@ -140,3 +137,3 @@ const r = ctx.$.parse(def[2], ctx);

// TODO: nested morphs?
return ctx.$.parse(def[0], ctx).morph(def[2]);
return ctx.$.parse(def[0], ctx).pipe(def[2]);
};

@@ -167,3 +164,3 @@ export const writeMalformedFunctionalExpressionMessage = (operator, value) => `${operator === ":" ? "Narrow" : "Morph"} expression requires a function following '${operator}' (was ${typeof value})`;

.slice(1)
.map((ctor) => typeof ctor === "function" ?
.map(ctor => typeof ctor === "function" ?
ctx.$.node("proto", { proto: ctor })

@@ -170,0 +167,0 @@ : throwParseError(writeInvalidConstructorMessage(objectKindOrDomainOf(ctor))));

@@ -1,3 +0,3 @@

import { type ArkConfig, type GenericProps, type NodeParseOptions, type PreparsedNodeResolution, type RawSchema, type RawSchemaResolutions, RawSchemaScope, type SchemaScope, type ambient, type arkKind, type destructuredExportContext, type destructuredImportContext, type exportedNameOf } from "@arktype/schema";
import { type nominal, type show } from "@arktype/util";
import { type ArkConfig, type GenericProps, type NodeParseContext, type NodeParseOptions, type PreparsedNodeResolution, type RawSchema, type RawSchemaResolutions, RawSchemaScope, type SchemaScope, type ambient, type arkKind, type destructuredExportContext, type destructuredImportContext, type exportedNameOf } from "@arktype/schema";
import { type isAnyOrNever, type nominal, type show } from "@arktype/util";
import type { type } from "./ark.js";

@@ -9,3 +9,3 @@ import { Generic } from "./generic.js";

import { type GenericDeclaration, type GenericParamsParseError, parseGenericParams } from "./parser/generic.js";
import type { DeclarationParser, DefinitionParser, Type, TypeParser } from "./type.js";
import { type DeclarationParser, type DefinitionParser, RawTypeParser, type Type, type TypeParser } from "./type.js";
export type ScopeParser = <const def>(def: validateScope<def>, config?: ArkConfig) => Scope<inferBootstrapped<bootstrapAliases<def>>>;

@@ -36,3 +36,3 @@ type validateScope<def> = {

type extractGenericParameters<k> = k extends GenericDeclaration<string, infer params> ? params : never;
export type resolve<reference extends keyof $ | keyof args, $, args> = (reference extends keyof args ? args[reference] : $[reference & keyof $]) extends infer resolution ? resolution extends Def<infer def> ? def extends null ? resolution : inferDefinition<def, $, args> : resolution : never;
export type resolve<reference extends keyof $ | keyof args, $, args> = (reference extends keyof args ? args[reference] : $[reference & keyof $]) extends infer resolution ? isAnyOrNever<resolution> extends true ? resolution : resolution extends Def<infer def> ? inferDefinition<def, $, args> : resolution : never;
export type moduleKeyOf<$> = {

@@ -44,3 +44,3 @@ [k in keyof $]: $[k] extends {

export type tryInferSubmoduleReference<$, token> = token extends `${infer submodule extends moduleKeyOf<$>}.${infer subalias}` ? subalias extends keyof $[submodule] ? $[submodule][subalias] extends type.cast<infer t> ? t : never : never : never;
export interface ParseContext extends NodeParseOptions {
export interface ParseContext extends NodeParseContext {
$: RawScope;

@@ -60,8 +60,8 @@ }

constructor(def: Record<string, unknown>, config?: ArkConfig);
type(...args: unknown[]): RawSchema | Generic;
type: RawTypeParser;
match: MatchParser<$>;
declare(): {
type: RawScope["type"];
declare: () => {
type: RawTypeParser;
};
define(def: unknown): unknown;
define: (def: unknown) => unknown;
preparseRoot(def: unknown): unknown;

@@ -68,0 +68,0 @@ parseRoot(def: unknown, opts?: NodeParseOptions): RawSchema;

@@ -9,2 +9,3 @@ import { RawSchemaScope, hasArkKind } from "@arktype/schema";

import { fullStringParse } from "./parser/string/string.js";
import { RawTypeParser } from "./type.js";
export const scope = ((def, config = {}) => new RawScope(def, config));

@@ -25,40 +26,18 @@ export class RawScope extends RawSchemaScope {

}
type(...args) {
if (args.length === 1) {
// treat as a simple definition
return this.parseRoot(args[0]);
}
if (args.length === 2 &&
typeof args[0] === "string" &&
args[0][0] === "<" &&
args[0].at(-1) === ">") {
// if there are exactly two args, the first of which looks like <${string}>,
// treat as a generic
const params = parseGenericParams(args[0].slice(1, -1));
const def = args[1];
// TODO: validateUninstantiatedGeneric, remove this cast
return new Generic(params, def, this);
}
// otherwise, treat as a tuple expression. technically, this also allows
// non-expression tuple definitions to be parsed, but it's not a supported
// part of the API as specified by the associated types
return this.parseRoot(args);
}
type = new RawTypeParser(this);
match = createMatchParser(this);
declare() {
return { type: this.type.bind(this) };
}
define(def) {
return def;
}
declare = (() => ({
type: this.type
})).bind(this);
define = ((def) => def).bind(this);
preparseRoot(def) {
if (isThunk(def) && !hasArkKind(def, "generic")) {
if (isThunk(def) && !hasArkKind(def, "generic"))
return def();
}
return def;
}
parseRoot(def, opts) {
// args: { this: {} as RawSchema },
return this.parse(def, {
args: { this: {} },
$: this,
raw: def,
...opts

@@ -69,3 +48,3 @@ }).bindScope(this);

if (typeof def === "string") {
if (ctx.args && Object.keys(ctx.args).every((k) => !def.includes(k))) {
if (ctx.args && Object.keys(ctx.args).every(k => !def.includes(k))) {
// we can only rely on the cache if there are no contextual

@@ -75,5 +54,4 @@ // resolutions like "this" or generic args

}
if (!this.parseCache[def]) {
if (!this.parseCache[def])
this.parseCache[def] = this.parseString(def, ctx);
}
return this.parseCache[def];

@@ -80,0 +58,0 @@ }

@@ -1,9 +0,12 @@

import { type BaseMeta, type Morph, type NodeDef, type Out, type Predicate, type PrimitiveConstraintKind, type Schema, type ambient, type constrain, type constraintKindOf, type distillConstrainableIn, type distillConstrainableOut, type distillIn, type distillOut, type includesMorphs, type inferIntersection, type inferMorphOut, type inferNarrow } from "@arktype/schema";
import type { Constructor, array, conform } from "@arktype/util";
import type { Generic, validateParameterString } from "./generic.js";
import { ArkErrors, type BaseMeta, type BaseRoot, type Disjoint, type Morph, type NodeDef, type Out, type Predicate, type PrimitiveConstraintKind, RawSchema, type Schema, type ambient, type constrain, type constraintKindOf, type distillConstrainableOut, type distillIn, type distillOut, type includesMorphs, type inferIntersection, type inferMorphOut, type inferNarrow, type inferPipes, type internalImplementationOf } from "@arktype/schema";
import { Callable, type Constructor, type array, type conform } from "@arktype/util";
import { Generic, type validateParameterString } from "./generic.js";
import type { inferDefinition, validateDeclared, validateDefinition } from "./parser/definition.js";
import type { parseGenericParams } from "./parser/generic.js";
import { parseGenericParams } from "./parser/generic.js";
import type { IndexOneOperator, IndexZeroOperator, TupleInfixOperator } from "./parser/tuple.js";
import type { Scope, bindThis } from "./scope.js";
export type TypeParser<$> = {
import type { RawScope, Scope, bindThis } from "./scope.js";
export interface TypeParserAttachments {
errors: typeof ArkErrors;
}
export interface TypeParser<$> extends TypeParserAttachments {
<const def>(def: validateTypeRoot<def, $>): Type<inferTypeRoot<def, $>, $>;

@@ -14,19 +17,35 @@ <const zero, const one, const rest extends array>(_0: zero extends IndexZeroOperator ? zero : validateTypeRoot<zero, $>, _1: zero extends "keyof" ? validateTypeRoot<one, $> : zero extends "instanceof" ? conform<one, Constructor> : zero extends "===" ? conform<one, unknown> : conform<one, IndexOneOperator>, ..._2: zero extends "===" ? rest : zero extends "instanceof" ? conform<rest, readonly Constructor[]> : one extends TupleInfixOperator ? one extends ":" ? [Predicate<distillIn<inferTypeRoot<zero, $>>>] : one extends "=>" ? [Morph<distillOut<inferTypeRoot<zero, $>>, unknown>] : one extends "@" ? [string | BaseMeta] : [validateTypeRoot<rest[0], $>] : []): Type<inferTypeRoot<[zero, one, ...rest], $>, $>;

}>): Generic<parseGenericParams<params>, def, $>;
};
}
export declare class RawTypeParser extends Callable<(...args: unknown[]) => RawSchema | Generic, TypeParserAttachments> {
constructor($: RawScope);
}
export type DeclarationParser<$> = <preinferred>() => {
type: <def>(def: validateDeclared<preinferred, def, $ & ambient, bindThis<def>>) => Type<preinferred, $>;
};
declare class _Type<t = unknown, $ = any> extends BaseRoot<t, $> implements internalImplementationOf<Schema> {
$: Scope<$>;
get in(): Type<this["tIn"], $>;
get out(): Type<this["tOut"], $>;
intersect<def>(def: validateTypeRoot<def, $>): Type<inferIntersection<t, inferTypeRoot<def, $>>> | Disjoint;
and<def>(def: validateTypeRoot<def, $>): Type<inferIntersection<t, inferTypeRoot<def, $>>, $>;
or<def>(def: validateTypeRoot<def, $>): Type<t | inferTypeRoot<def, $>, $>;
array(): Type<t[], $>;
keyof(): Type<keyof this["inferIn"], $>;
pipe<a extends Morph<this["infer"]>>(a: a): Type<inferPipes<t, [a]>, $>;
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>>(a: a, b: b): Type<inferPipes<t, [a, b]>, $>;
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>, c extends Morph<inferMorphOut<b>>>(a: a, b: b, c: c): Type<inferPipes<t, [a, b, c]>, $>;
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>, c extends Morph<inferMorphOut<b>>, d extends Morph<inferMorphOut<c>>>(a: a, b: b, c: c, d: d): Type<inferPipes<t, [a, b, c, d]>, $>;
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>, c extends Morph<inferMorphOut<b>>, d extends Morph<inferMorphOut<c>>, e extends Morph<inferMorphOut<d>>>(a: a, b: b, c: c, d: d, e: e): Type<inferPipes<t, [a, b, c, d, e]>, $>;
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>, c extends Morph<inferMorphOut<b>>, d extends Morph<inferMorphOut<c>>, e extends Morph<inferMorphOut<d>>, f extends Morph<inferMorphOut<e>>>(a: a, b: b, c: c, d: d, e: e, f: f): Type<inferPipes<t, [a, b, c, d, e, f]>, $>;
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>, c extends Morph<inferMorphOut<b>>, d extends Morph<inferMorphOut<c>>, e extends Morph<inferMorphOut<d>>, f extends Morph<inferMorphOut<e>>, g extends Morph<inferMorphOut<f>>>(a: a, b: b, c: c, d: d, e: e, f: f, g: g): Type<inferPipes<t, [a, b, c, d, e, f, g]>, $>;
narrow<def extends Predicate<distillConstrainableOut<t>>>(def: def): Type<includesMorphs<t> extends true ? (In: this["tIn"]) => Out<inferNarrow<this["infer"], def>> : inferNarrow<this["infer"], def>, $>;
equals<def>(def: validateTypeRoot<def, $>): this is Type<inferTypeRoot<def>, $>;
extract<def>(r: validateTypeRoot<def, $>): Type<t, $>;
exclude<def>(r: validateTypeRoot<def, $>): Type<t, $>;
extends<def>(other: validateTypeRoot<def, $>): this is Type<inferTypeRoot<def>, $>;
constrain<kind extends PrimitiveConstraintKind, const def extends NodeDef<kind>>(kind: conform<kind, constraintKindOf<this["inferIn"]>>, def: def): Type<constrain<t, kind, def>, $>;
}
export interface Type<
/** @ts-expect-error allow instantiation assignment to the base type */
out t = unknown, $ = any> extends Schema<t, $> {
and: (<def>(def: validateTypeRoot<def, $>) => Type<inferIntersection<t, inferTypeRoot<def, $>>, $>) & Schema<t, $>["and"];
or: (<def>(def: validateTypeRoot<def, $>) => Type<t | inferTypeRoot<def, $>, $>) & Schema<t, $>["or"];
get in(): Type<distillConstrainableIn<t>, $>;
get out(): Type<distillConstrainableOut<t>, $>;
array(): Type<t[], $>;
morph: (<morph extends Morph<this["infer"]>, outValidatorDef = never>(morph: morph, outValidator?: validateTypeRoot<outValidatorDef, $>) => Type<(In: distillConstrainableIn<t>) => Out<[
outValidatorDef
] extends [never] ? inferMorphOut<morph> : distillConstrainableOut<inferTypeRoot<outValidatorDef, $>>>, $>) & Schema<t, $>["morph"];
narrow<def extends Predicate<distillConstrainableOut<t>>>(def: def): Type<includesMorphs<t> extends true ? (In: distillIn<t>) => Out<inferNarrow<this["infer"], def>> : inferNarrow<this["infer"], def>, $>;
constrain<kind extends PrimitiveConstraintKind, const def extends NodeDef<kind>>(kind: conform<kind, constraintKindOf<this["in"]["infer"]>>, def: def): Type<constrain<t, kind, def>, $>;
out t = unknown, $ = any> extends _Type<t, $> {
}

@@ -38,2 +57,3 @@ export type TypeConstructor<t = unknown, $ = any> = new (def: unknown, $: Scope<$>) => Type<t, $>;

export type inferTypeRoot<def, $ = {}> = inferDefinition<def, $ & ambient, bindThis<def>>;
export {};
//# sourceMappingURL=type.d.ts.map

@@ -1,3 +0,34 @@

import { RawSchema } from "@arktype/schema";
import { ArkErrors, RawSchema } from "@arktype/schema";
import { Callable } from "@arktype/util";
import { Generic } from "./generic.js";
import { parseGenericParams } from "./parser/generic.js";
const typeParserAttachments = Object.freeze({
errors: ArkErrors
});
export class RawTypeParser extends Callable {
constructor($) {
super((...args) => {
if (args.length === 1) {
// treat as a simple definition
return $.parseRoot(args[0]);
}
if (args.length === 2 &&
typeof args[0] === "string" &&
args[0][0] === "<" &&
args[0].at(-1) === ">") {
// if there are exactly two args, the first of which looks like <${string}>,
// treat as a generic
const params = parseGenericParams(args[0].slice(1, -1));
const def = args[1];
// TODO: validateUninstantiatedGeneric, remove this cast
return new Generic(params, def, $);
}
// otherwise, treat as a tuple expression. technically, this also allows
// non-expression tuple definitions to be parsed, but it's not a supported
// part of the API as specified by the associated types
return $.parseRoot(args);
}, { bind: $, attach: typeParserAttachments });
}
}
export const Type = RawSchema;
//# sourceMappingURL=type.js.map
{
"name": "arktype",
"description": "TypeScript's 1:1 validator, optimized from editor to runtime",
"version": "2.0.0-dev.7",
"version": "2.0.0-dev.8",
"license": "MIT",

@@ -41,5 +41,5 @@ "author": {

"dependencies": {
"@arktype/util": "0.0.33",
"@arktype/schema": "0.0.7"
"@arktype/util": "0.0.34",
"@arktype/schema": "0.0.8"
}
}

@@ -16,6 +16,6 @@ import { type nominal, throwParseError } from "@arktype/util"

export const parseGenericParams = (def: string): string[] =>
$parseGenericParams(new Scanner(def))
_parseGenericParams(new Scanner(def))
export type parseGenericParams<def extends string> =
$parseParams<def, "", []> extends infer result extends string[] ?
_parseParams<def, "", []> extends infer result extends string[] ?
"" extends result[number] ?

@@ -31,7 +31,6 @@ GenericParamsParseError<emptyGenericParameterMessage>

const $parseGenericParams = (scanner: Scanner): string[] => {
const _parseGenericParams = (scanner: Scanner): string[] => {
const param = scanner.shiftUntilNextTerminator()
if (param === "") {
throwParseError(emptyGenericParameterMessage)
}
if (param === "") throwParseError(emptyGenericParameterMessage)
scanner.shiftUntilNonWhitespace()

@@ -41,3 +40,3 @@ const nextNonWhitespace = scanner.shift()

nextNonWhitespace === "" ? [param]
: nextNonWhitespace === "," ? [param, ...$parseGenericParams(scanner)]
: nextNonWhitespace === "," ? [param, ..._parseGenericParams(scanner)]
: throwParseError(writeUnexpectedCharacterMessage(nextNonWhitespace, ","))

@@ -47,3 +46,3 @@ )

type $parseParams<
type _parseParams<
unscanned extends string,

@@ -54,7 +53,7 @@ param extends string,

unscanned extends `${infer lookahead}${infer nextUnscanned}` ?
lookahead extends "," ? $parseParams<nextUnscanned, "", [...result, param]>
lookahead extends "," ? _parseParams<nextUnscanned, "", [...result, param]>
: lookahead extends Scanner.WhiteSpaceToken ?
param extends "" ?
// if the next char is whitespace and we aren't in the middle of a param, skip to the next one
$parseParams<Scanner.skipWhitespace<nextUnscanned>, "", result>
_parseParams<Scanner.skipWhitespace<nextUnscanned>, "", result>
: Scanner.skipWhitespace<nextUnscanned> extends (

@@ -64,3 +63,3 @@ `${infer nextNonWhitespace}${infer rest}`

nextNonWhitespace extends "," ?
$parseParams<rest, "", [...result, param]>
_parseParams<rest, "", [...result, param]>
: GenericParamsParseError<

@@ -71,4 +70,4 @@ writeUnexpectedCharacterMessage<nextNonWhitespace, ",">

[...result, param]
: $parseParams<nextUnscanned, `${param}${lookahead}`, result>
: _parseParams<nextUnscanned, `${param}${lookahead}`, result>
: param extends "" ? result
: [...result, param]

@@ -49,3 +49,3 @@ import {

spreadNode.prop?.forEach(
(spreadRequired) =>
spreadRequired =>
!parsedEntries.some(

@@ -57,5 +57,3 @@ ({ inner: innerKey }) => innerKey === spreadRequired.key

for (const entry of parsedEntries) {
if (entry.kind === "spread") {
return throwParseError(nonLeadingSpreadError)
}
if (entry.kind === "spread") return throwParseError(nonLeadingSpreadError)

@@ -62,0 +60,0 @@ if (entry.kind === "index") {

@@ -12,2 +12,3 @@ import type {

ErrorMessage,
isAnyOrNever,
writeMalformedNumericLiteralMessage

@@ -85,5 +86,3 @@ } from "@arktype/util"

: maybeExtractAlias<def, $> extends infer alias extends keyof $ ?
$[alias] extends null ?
// handle any/never
def
isAnyOrNever<$[alias]> extends true ? def
: def extends PrivateDeclaration ?

@@ -90,0 +89,0 @@ ErrorMessage<writePrefixedPrivateReferenceMessage<def>>

@@ -80,5 +80,4 @@ import type { LimitLiteral, RawSchema } from "@arktype/schema"

finalize(finalizer: Scanner.FinalizingLookahead): void {
if (this.groups.length) {
return this.error(writeUnclosedGroupMessage(")"))
}
if (this.groups.length) return this.error(writeUnclosedGroupMessage(")"))
this.finalizeBranches()

@@ -90,5 +89,5 @@ this.finalizer = finalizer

const invertedComparator = invertedComparators[comparator]
if (!isKeyOf(invertedComparator, minComparators)) {
if (!isKeyOf(invertedComparator, minComparators))
return this.error(writeUnpairableComparatorMessage(comparator))
}
if (this.branches.leftBound) {

@@ -118,5 +117,3 @@ return this.error(

this.root = this.branches.intersection
} else {
this.applyPrefixes()
}
} else this.applyPrefixes()
}

@@ -127,5 +124,5 @@

const topBranchState = this.groups.pop()
if (!topBranchState) {
if (!topBranchState)
return this.error(writeUnmatchedGroupCloseMessage(this.scanner.unscanned))
}
this.branches = topBranchState

@@ -132,0 +129,0 @@ }

@@ -43,11 +43,8 @@ import type { DateLiteral } from "@arktype/schema"

const stringParsedDate = new Date(source)
if (isValidDate(stringParsedDate)) {
return stringParsedDate
}
if (isValidDate(stringParsedDate)) return stringParsedDate
const epochMillis = tryParseNumber(source)
if (epochMillis !== undefined) {
const numberParsedDate = new Date(epochMillis)
if (isValidDate(numberParsedDate)) {
return numberParsedDate
}
if (isValidDate(numberParsedDate)) return numberParsedDate
}

@@ -54,0 +51,0 @@ return errorOnFail ?

@@ -24,7 +24,7 @@ import { isKeyOf } from "@arktype/util"

)
if (s.scanner.lookahead === "") {
if (s.scanner.lookahead === "")
return s.error(writeUnterminatedEnclosedMessage(enclosed, enclosing))
}
// Shift the scanner one additional time for the second enclosing token
const token = `${enclosing}${enclosed}${s.scanner.shift()}`
s.scanner.shift()
if (enclosing === "/") {

@@ -41,5 +41,5 @@ // fail parsing if the regex is invalid

)
} else if (isKeyOf(enclosing, enclosingQuote)) {
} else if (isKeyOf(enclosing, enclosingQuote))
s.root = s.ctx.$.node("unit", { unit: enclosed })
} else {
else {
const date = tryParseDate(enclosed, writeInvalidDateMessage(enclosed))

@@ -98,5 +98,5 @@ s.root = s.ctx.$.node("unit", { unit: date, description: enclosed })

> = {
"'": (scanner) => scanner.lookahead === `'`,
'"': (scanner) => scanner.lookahead === `"`,
"/": (scanner) => scanner.lookahead === `/`
"'": scanner => scanner.lookahead === `'`,
'"': scanner => scanner.lookahead === `"`,
"/": scanner => scanner.lookahead === `/`
}

@@ -103,0 +103,0 @@

@@ -20,3 +20,3 @@ import type { RawSchema } from "@arktype/schema"

s: DynamicState
): ParsedArgs<RawSchema[]> => $parseGenericArgs(name, params, s, [], [])
): ParsedArgs<RawSchema[]> => _parseGenericArgs(name, params, s, [], [])

@@ -29,5 +29,5 @@ export type parseGenericArgs<

args
> = $parseGenericArgs<name, params, unscanned, $, args, [], []>
> = _parseGenericArgs<name, params, unscanned, $, args, [], []>
const $parseGenericArgs = (
const _parseGenericArgs = (
name: string,

@@ -52,9 +52,9 @@ params: string[],

}
if (argState.finalizer === ",") {
return $parseGenericArgs(name, params, s, argDefs, argNodes)
}
if (argState.finalizer === ",")
return _parseGenericArgs(name, params, s, argDefs, argNodes)
return argState.error(writeUnclosedGroupMessage(">"))
}
type $parseGenericArgs<
type _parseGenericArgs<
name extends string,

@@ -91,3 +91,3 @@ params extends string[],

: finalArgState["finalizer"] extends "," ?
$parseGenericArgs<
_parseGenericArgs<
name,

@@ -94,0 +94,0 @@ params,

@@ -5,3 +5,2 @@ import {

RawSchema,
type SchemaModule,
hasArkKind,

@@ -15,2 +14,3 @@ type writeNonSubmoduleDotMessage,

type ErrorMessage,
type isAnyOrNever,
type join,

@@ -38,7 +38,4 @@ printable,

const token = s.scanner.shiftUntilNextTerminator()
if (token === "keyof") {
s.addPrefix("keyof")
} else {
s.root = unenclosedToNode(s, token)
}
if (token === "keyof") s.addPrefix("keyof")
else s.root = unenclosedToNode(s, token)
}

@@ -54,3 +51,5 @@

: result extends keyof $ ?
$[result] extends GenericProps ?
isAnyOrNever<$[result]> extends true ?
state.setRoot<s, result, unscanned>
: $[result] extends GenericProps ?
parseGenericInstantiation<

@@ -75,5 +74,5 @@ token,

const lookahead = s.scanner.shift()
if (lookahead !== "<") {
if (lookahead !== "<")
return s.error(writeInvalidGenericArgsMessage(name, g.params, []))
}
const parsedArgs = parseGenericArgs(name, g.params, s)

@@ -136,9 +135,8 @@ const remainingChars = parsedArgs.unscanned.length

const maybeNumber = tryParseNumber(token, { strict: true })
if (maybeNumber !== undefined) {
if (maybeNumber !== undefined)
return s.ctx.$.node("unit", { unit: maybeNumber })
}
const maybeBigint = tryParseWellFormedBigint(token)
if (maybeBigint !== undefined) {
if (maybeBigint !== undefined)
return s.ctx.$.node("unit", { unit: maybeBigint })
}
}

@@ -155,12 +153,5 @@

) ?
$[submodule] extends (
SchemaModule<infer sub$> | Module<infer sub$> // TODO: shouldn't need both checks?
) ?
reference extends keyof sub$ ? token
: unknown extends sub$ ?
// not sure why we need the additional check here, but for now TS seems to
// hit this branch for a non-scope dot access rather than failing
// initially when we try to infer r. if this can be removed without breaking
// any submodule test cases, do it!
ErrorMessage<writeNonSubmoduleDotMessage<submodule>>
$[submodule] extends Module<infer sub$> ?
reference extends keyof sub$ ?
token
: unresolvableError<s, reference, $[submodule], args, [submodule]>

@@ -167,0 +158,0 @@ : ErrorMessage<writeNonSubmoduleDotMessage<submodule>>

@@ -184,5 +184,4 @@ import {

(typeof limitNode.unit !== "number" && !(limitNode.unit instanceof Date))
) {
)
return s.error(writeInvalidLimitMessage(comparator, limitToken, "right"))
}

@@ -198,12 +197,11 @@ const limit = limitNode.unit

"right"
)) {
))
s.constrainRoot(kind, { rule: limit, exclusive })
}
if (!s.branches.leftBound) {
return
}
if (!s.branches.leftBound) return
// if there's an open left bound, perform additional validation and apply it
if (!isKeyOf(comparator, maxComparators)) {
if (!isKeyOf(comparator, maxComparators))
return s.error(writeUnpairableComparatorMessage(comparator))
}
const lowerBoundKind = getBoundKinds(

@@ -210,0 +208,0 @@ s.branches.leftBound.comparator,

@@ -11,5 +11,4 @@ import { tryParseInteger } from "@arktype/util"

})
if (divisor === 0) {
s.error(writeInvalidDivisorMessage(0))
}
if (divisor === 0) s.error(writeInvalidDivisorMessage(0))
s.root = s.root.constrain("divisor", divisor)

@@ -16,0 +15,0 @@ }

@@ -30,7 +30,5 @@ import { type Dict, isKeyOf } from "@arktype/util"

if (condition(this, shifted)) {
if (shifted[shifted.length - 1] === Scanner.escapeToken) {
if (shifted[shifted.length - 1] === Scanner.escapeToken)
shifted = shifted.slice(0, -1)
} else {
break
}
else break
}

@@ -37,0 +35,0 @@ shifted += this.shift()

@@ -65,5 +65,4 @@ import type { RawSchema } from "@arktype/schema"

export const parseUntilFinalizer = (s: DynamicState): DynamicStateWithRoot => {
while (s.finalizer === undefined) {
next(s)
}
while (s.finalizer === undefined) next(s)
return s as DynamicStateWithRoot

@@ -70,0 +69,0 @@ }

@@ -56,5 +56,4 @@ import {

if (def[i] === "?") {
if (spread) {
return throwParseError(spreadOptionalMessage)
}
if (spread) return throwParseError(spreadOptionalMessage)
optional = true

@@ -64,11 +63,11 @@ i++

if (spread) {
if (!element.extends(jsObjects.Array)) {
if (!element.extends(jsObjects.Array))
return throwParseError(writeNonArraySpreadMessage(element.expression))
}
// a spread must be distributed over branches e.g.:
// def: [string, ...(number[] | [true, false])]
// nodes: [string, ...number[]] | [string, true, false]
sequences = sequences.flatMap((base) =>
sequences = sequences.flatMap(base =>
// since appendElement mutates base, we have to shallow-ish clone it for each branch
element.branches.map((branch) =>
element.branches.map(branch =>
appendSpreadBranch(makeRootAndArrayPropertiesMutable(base), branch)

@@ -78,3 +77,3 @@ )

} else {
sequences = sequences.map((base) =>
sequences = sequences.map(base =>
appendElement(base, optional ? "optional" : "required", element)

@@ -86,3 +85,3 @@ )

sequences.map(
(sequence) =>
sequence =>
({

@@ -150,6 +149,6 @@ proto: Array,

}
spread.prefix.forEach((node) => appendElement(base, "required", node))
spread.optional.forEach((node) => appendElement(base, "optional", node))
spread.prefix.forEach(node => appendElement(base, "required", node))
spread.optional.forEach(node => appendElement(base, "optional", node))
spread.variadic && appendElement(base, "variadic", spread.variadic)
spread.postfix.forEach((node) => appendElement(base, "required", node))
spread.postfix.forEach(node => appendElement(base, "required", node))
return base

@@ -422,5 +421,5 @@ }

const parseBranchTuple: PostfixParser<"|" | "&"> = (def, ctx) => {
if (def[2] === undefined) {
if (def[2] === undefined)
return throwParseError(writeMissingRightOperandMessage(def[1], ""))
}
const l = ctx.$.parse(def[0], ctx)

@@ -468,3 +467,3 @@ const r = ctx.$.parse(def[2], ctx)

// TODO: nested morphs?
return ctx.$.parse(def[0], ctx).morph(def[2] as Morph)
return ctx.$.parse(def[0], ctx).pipe(def[2] as Morph)
}

@@ -528,3 +527,3 @@

.slice(1)
.map((ctor) =>
.map(ctor =>
typeof ctor === "function" ?

@@ -531,0 +530,0 @@ ctx.$.node("proto", { proto: ctor as Constructor })

import {
type ArkConfig,
type GenericProps,
type NodeParseContext,
type NodeParseOptions,

@@ -21,2 +22,3 @@ type PreparsedNodeResolution,

hasDomain,
type isAnyOrNever,
isThunk,

@@ -44,7 +46,8 @@ type nominal,

import { fullStringParse } from "./parser/string/string.js"
import type {
DeclarationParser,
DefinitionParser,
Type,
TypeParser
import {
type DeclarationParser,
type DefinitionParser,
RawTypeParser,
type Type,
type TypeParser
} from "./type.js"

@@ -131,8 +134,5 @@

) extends infer resolution ?
resolution extends Def<infer def> ?
def extends null ?
// handle resolution of any and never
resolution
: inferDefinition<def, $, args>
: resolution
isAnyOrNever<resolution> extends true ? resolution
: resolution extends Def<infer def> ? inferDefinition<def, $, args>
: resolution
: never

@@ -154,3 +154,3 @@

export interface ParseContext extends NodeParseOptions {
export interface ParseContext extends NodeParseContext {
$: RawScope

@@ -198,40 +198,15 @@ }

type(...args: unknown[]): RawSchema | Generic {
if (args.length === 1) {
// treat as a simple definition
return this.parseRoot(args[0])
}
if (
args.length === 2 &&
typeof args[0] === "string" &&
args[0][0] === "<" &&
args[0].at(-1) === ">"
) {
// if there are exactly two args, the first of which looks like <${string}>,
// treat as a generic
const params = parseGenericParams(args[0].slice(1, -1))
const def = args[1]
// TODO: validateUninstantiatedGeneric, remove this cast
return new Generic(params, def, this as never) as never
}
// otherwise, treat as a tuple expression. technically, this also allows
// non-expression tuple definitions to be parsed, but it's not a supported
// part of the API as specified by the associated types
return this.parseRoot(args)
}
type = new RawTypeParser(this as never)
match: MatchParser<$> = createMatchParser(this as never) as never
declare(): { type: RawScope["type"] } {
return { type: this.type.bind(this) }
}
declare = (() => ({
type: this.type
})).bind(this)
define(def: unknown): unknown {
return def
}
define = ((def: unknown) => def).bind(this)
override preparseRoot(def: unknown): unknown {
if (isThunk(def) && !hasArkKind(def, "generic")) {
return def()
}
if (isThunk(def) && !hasArkKind(def, "generic")) return def()
return def

@@ -241,5 +216,6 @@ }

override parseRoot(def: unknown, opts?: NodeParseOptions): RawSchema {
// args: { this: {} as RawSchema },
return this.parse(def, {
args: { this: {} as RawSchema },
$: this as never,
raw: def,
...opts

@@ -251,3 +227,3 @@ }).bindScope(this)

if (typeof def === "string") {
if (ctx.args && Object.keys(ctx.args).every((k) => !def.includes(k))) {
if (ctx.args && Object.keys(ctx.args).every(k => !def.includes(k))) {
// we can only rely on the cache if there are no contextual

@@ -257,5 +233,5 @@ // resolutions like "this" or generic args

}
if (!this.parseCache[def]) {
if (!this.parseCache[def])
this.parseCache[def] = this.parseString(def, ctx)
}
return this.parseCache[def]

@@ -262,0 +238,0 @@ }

import {
ArkErrors,
type BaseMeta,
type BaseRoot,
type Disjoint,
type Morph,

@@ -13,3 +16,2 @@ type NodeDef,

type constraintKindOf,
type distillConstrainableIn,
type distillConstrainableOut,

@@ -21,6 +23,13 @@ type distillIn,

type inferMorphOut,
type inferNarrow
type inferNarrow,
type inferPipes,
type internalImplementationOf
} from "@arktype/schema"
import type { Constructor, array, conform } from "@arktype/util"
import type { Generic, validateParameterString } from "./generic.js"
import {
Callable,
type Constructor,
type array,
type conform
} from "@arktype/util"
import { Generic, type validateParameterString } from "./generic.js"
import type {

@@ -31,3 +40,3 @@ inferDefinition,

} from "./parser/definition.js"
import type { parseGenericParams } from "./parser/generic.js"
import { parseGenericParams } from "./parser/generic.js"
import type {

@@ -38,5 +47,8 @@ IndexOneOperator,

} from "./parser/tuple.js"
import type { Scope, bindThis } from "./scope.js"
import type { RawScope, Scope, bindThis } from "./scope.js"
export interface TypeParserAttachments {
errors: typeof ArkErrors
}
export type TypeParser<$> = {
export interface TypeParser<$> extends TypeParserAttachments {
// Parse and check the definition, returning either the original input for a

@@ -75,2 +87,40 @@ // valid definition or a string representing an error message.

const typeParserAttachments = Object.freeze({
errors: ArkErrors
} satisfies TypeParserAttachments)
export class RawTypeParser extends Callable<
(...args: unknown[]) => RawSchema | Generic,
TypeParserAttachments
> {
constructor($: RawScope) {
super(
(...args) => {
if (args.length === 1) {
// treat as a simple definition
return $.parseRoot(args[0])
}
if (
args.length === 2 &&
typeof args[0] === "string" &&
args[0][0] === "<" &&
args[0].at(-1) === ">"
) {
// if there are exactly two args, the first of which looks like <${string}>,
// treat as a generic
const params = parseGenericParams(args[0].slice(1, -1))
const def = args[1]
// TODO: validateUninstantiatedGeneric, remove this cast
return new Generic(params, def, $ as never) as never
}
// otherwise, treat as a tuple expression. technically, this also allows
// non-expression tuple definitions to be parsed, but it's not a supported
// part of the API as specified by the associated types
return $.parseRoot(args)
},
{ bind: $, attach: typeParserAttachments }
)
}
}
export type DeclarationParser<$> = <preinferred>() => {

@@ -83,36 +133,84 @@ // for some reason, making this a const parameter breaks preinferred validation

export interface Type<
/** @ts-expect-error allow instantiation assignment to the base type */
out t = unknown,
$ = any
> extends Schema<t, $> {
and: (<def>(
// this is declared as a class internally so we can ensure all "abstract"
// methods of BaseRoot are overridden, but we end up exporting it as an interface
// to ensure it is not accessed as a runtime value
declare class _Type<t = unknown, $ = any>
extends BaseRoot<t, $>
implements internalImplementationOf<Schema>
{
$: Scope<$>;
get in(): Type<this["tIn"], $>
get out(): Type<this["tOut"], $>
intersect<def>(
def: validateTypeRoot<def, $>
) => Type<inferIntersection<t, inferTypeRoot<def, $>>, $>) &
Schema<t, $>["and"]
): Type<inferIntersection<t, inferTypeRoot<def, $>>> | Disjoint
or: (<def>(
and<def>(
def: validateTypeRoot<def, $>
) => Type<t | inferTypeRoot<def, $>, $>) &
Schema<t, $>["or"]
): Type<inferIntersection<t, inferTypeRoot<def, $>>, $>
get in(): Type<distillConstrainableIn<t>, $>
get out(): Type<distillConstrainableOut<t>, $>
or<def>(def: validateTypeRoot<def, $>): Type<t | inferTypeRoot<def, $>, $>
array(): Type<t[], $>
morph: (<morph extends Morph<this["infer"]>, outValidatorDef = never>(
morph: morph,
outValidator?: validateTypeRoot<outValidatorDef, $>
) => Type<
(
In: distillConstrainableIn<t>
) => Out<
[outValidatorDef] extends [never] ? inferMorphOut<morph>
: distillConstrainableOut<inferTypeRoot<outValidatorDef, $>>
>,
$
>) &
Schema<t, $>["morph"]
keyof(): Type<keyof this["inferIn"], $>
pipe<a extends Morph<this["infer"]>>(a: a): Type<inferPipes<t, [a]>, $>
pipe<a extends Morph<this["infer"]>, b extends Morph<inferMorphOut<a>>>(
a: a,
b: b
): Type<inferPipes<t, [a, b]>, $>
pipe<
a extends Morph<this["infer"]>,
b extends Morph<inferMorphOut<a>>,
c extends Morph<inferMorphOut<b>>
>(a: a, b: b, c: c): Type<inferPipes<t, [a, b, c]>, $>
pipe<
a extends Morph<this["infer"]>,
b extends Morph<inferMorphOut<a>>,
c extends Morph<inferMorphOut<b>>,
d extends Morph<inferMorphOut<c>>
>(a: a, b: b, c: c, d: d): Type<inferPipes<t, [a, b, c, d]>, $>
pipe<
a extends Morph<this["infer"]>,
b extends Morph<inferMorphOut<a>>,
c extends Morph<inferMorphOut<b>>,
d extends Morph<inferMorphOut<c>>,
e extends Morph<inferMorphOut<d>>
>(a: a, b: b, c: c, d: d, e: e): Type<inferPipes<t, [a, b, c, d, e]>, $>
pipe<
a extends Morph<this["infer"]>,
b extends Morph<inferMorphOut<a>>,
c extends Morph<inferMorphOut<b>>,
d extends Morph<inferMorphOut<c>>,
e extends Morph<inferMorphOut<d>>,
f extends Morph<inferMorphOut<e>>
>(
a: a,
b: b,
c: c,
d: d,
e: e,
f: f
): Type<inferPipes<t, [a, b, c, d, e, f]>, $>
pipe<
a extends Morph<this["infer"]>,
b extends Morph<inferMorphOut<a>>,
c extends Morph<inferMorphOut<b>>,
d extends Morph<inferMorphOut<c>>,
e extends Morph<inferMorphOut<d>>,
f extends Morph<inferMorphOut<e>>,
g extends Morph<inferMorphOut<f>>
>(
a: a,
b: b,
c: c,
d: d,
e: e,
f: f,
g: g
): Type<inferPipes<t, [a, b, c, d, e, f, g]>, $>
// TODO: based on below, should maybe narrow morph output if used after

@@ -123,3 +221,3 @@ narrow<def extends Predicate<distillConstrainableOut<t>>>(

includesMorphs<t> extends true ?
(In: distillIn<t>) => Out<inferNarrow<this["infer"], def>>
(In: this["tIn"]) => Out<inferNarrow<this["infer"], def>>
: inferNarrow<this["infer"], def>,

@@ -129,2 +227,13 @@ $

equals<def>(
def: validateTypeRoot<def, $>
): this is Type<inferTypeRoot<def>, $>
// TODO: i/o
extract<def>(r: validateTypeRoot<def, $>): Type<t, $>
exclude<def>(r: validateTypeRoot<def, $>): Type<t, $>
extends<def>(
other: validateTypeRoot<def, $>
): this is Type<inferTypeRoot<def>, $>
constrain<

@@ -134,3 +243,3 @@ kind extends PrimitiveConstraintKind,

>(
kind: conform<kind, constraintKindOf<this["in"]["infer"]>>,
kind: conform<kind, constraintKindOf<this["inferIn"]>>,
def: def

@@ -140,2 +249,8 @@ ): Type<constrain<t, kind, def>, $>

export interface Type<
/** @ts-expect-error allow instantiation assignment to the base type */
out t = unknown,
$ = any
> extends _Type<t, $> {}
export type TypeConstructor<t = unknown, $ = any> = new (

@@ -142,0 +257,0 @@ def: unknown,

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc