Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions ark/type/__tests__/fn.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,15 @@ contextualize(() => {
attest(f.name).snap("bound typed originalName")
})

it("raw", () => {
const len = type.fn.raw("string | unknown[]")((s: string) => s.length)

attest(len("foo")).equals(3)
attest(() => len(1)).throws.snap(
"TraversalError: value at [0] must be a string or an object (was a number)"
)
})

it("arg submodule completions", () => {
// @ts-expect-error
attest(() => type.fn("string.nu")).completions({
Expand Down
48 changes: 25 additions & 23 deletions ark/type/fn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,35 +73,37 @@ type FnParserAttachments = Omit<FnParser, never>

export class InternalFnParser extends Callable<(...args: unknown[]) => Fn> {
constructor($: InternalScope) {
const attach: FnParserAttachments = {
$: $ as never,
raw: $.fn
}
const parse = (...signature: unknown[]) => {
const returnOperatorIndex = signature.indexOf(":")
const lastParamIndex =
returnOperatorIndex === -1 ?
signature.length - 1
: returnOperatorIndex - 1

super(
(...signature) => {
const returnOperatorIndex = signature.indexOf(":")
const lastParamIndex =
returnOperatorIndex === -1 ?
signature.length - 1
: returnOperatorIndex - 1
const paramDefs = signature.slice(0, lastParamIndex + 1)

const paramDefs = signature.slice(0, lastParamIndex + 1)
const paramTuple = $.parse(paramDefs).assertHasKind("intersection")

const paramTuple = $.parse(paramDefs).assertHasKind("intersection")
let returnType: BaseRoot = $.intrinsic.unknown

if (returnOperatorIndex !== -1) {
if (returnOperatorIndex !== signature.length - 2)
return throwParseError(badFnReturnTypeMessage)
returnType = $.parse(signature[returnOperatorIndex + 1])
}

let returnType: BaseRoot = $.intrinsic.unknown
return (impl: Fn) => new InternalTypedFn(impl, paramTuple, returnType)
}

if (returnOperatorIndex !== -1) {
if (returnOperatorIndex !== signature.length - 2)
return throwParseError(badFnReturnTypeMessage)
returnType = $.parse(signature[returnOperatorIndex + 1])
}
// `raw` is an alias of `fn` itself with no type-level validation. It must
// reference `parse` directly rather than `$.fn`, which is still being
// constructed (and thus `undefined`) at this point.
const attach: FnParserAttachments = {
$: $ as never,
raw: parse
}

return (impl: Fn) => new InternalTypedFn(impl, paramTuple, returnType)
},
{ attach }
)
super(parse, { attach })
}
}

Expand Down
Loading