Roamin
Roamin
Aarktype
Created by Roamin on 9/1/2024 in #questions
Best way to pass `Type` around
Hello! First, thanks for building this really cool library 🙏 I first heard of arktype while I was looking at the code of a framework called MUD, and while I was discussing CLI libraries with @frolic the other day, I thought that maybe it'd be a cool idea to have a CLI library that leverages arktype for arguments and options validation/parsing. I basically would like to have a function that receives args that are generated from arktype definitions. This is the code I have so far:
import { type Type, type, validateAmbient } from "arktype";
import { type ErrorMessage } from "@ark/util";

type ValidateArguments<T> = {
[K in keyof T]: {
type: validateAmbient<T[K]>;
};
};

type ArkType = Type | Type<(_: any) => any>;

type InferredArkType<T> = T extends ArkType
? T["infer"]
: ErrorMessage<"invalid Ark type">;

type ParseArguments<T> = {
[K in keyof T]: InferredArkType<T[K]>;
};

type Command<T> = {
arguments: ValidateArguments<T>;
run(args: ParseArguments<T>): void | Promise<void>;
};

function defineCommand<const conf>(command: Command<conf>) {
console.log(command);
}

defineCommand({
arguments: {
a: {
type: type(`string>2`),
},
b: {
type: type("string").narrow((address, ctx) => {
if (address === [...address].reverse().join("")) {
return true;
}
return ctx.mustBe("a palindrome");
}),
},
c: {
type: type(["string", "=>", parseFloat]),
},
d: {
type: type("string.json").pipe.try(
(s): object => JSON.parse(s),
type({
name: "string",
version: "string.semver",
})
),
},
f: {
type: type("string|undefined"),
},
},
run(args) {
args.a;
// ^?
args.b;
// ^?
args.c;
// ^?
args.d;
// ^?
args.f;
// ^?
},
});
import { type Type, type, validateAmbient } from "arktype";
import { type ErrorMessage } from "@ark/util";

type ValidateArguments<T> = {
[K in keyof T]: {
type: validateAmbient<T[K]>;
};
};

type ArkType = Type | Type<(_: any) => any>;

type InferredArkType<T> = T extends ArkType
? T["infer"]
: ErrorMessage<"invalid Ark type">;

type ParseArguments<T> = {
[K in keyof T]: InferredArkType<T[K]>;
};

type Command<T> = {
arguments: ValidateArguments<T>;
run(args: ParseArguments<T>): void | Promise<void>;
};

function defineCommand<const conf>(command: Command<conf>) {
console.log(command);
}

defineCommand({
arguments: {
a: {
type: type(`string>2`),
},
b: {
type: type("string").narrow((address, ctx) => {
if (address === [...address].reverse().join("")) {
return true;
}
return ctx.mustBe("a palindrome");
}),
},
c: {
type: type(["string", "=>", parseFloat]),
},
d: {
type: type("string.json").pipe.try(
(s): object => JSON.parse(s),
type({
name: "string",
version: "string.semver",
})
),
},
f: {
type: type("string|undefined"),
},
},
run(args) {
args.a;
// ^?
args.b;
// ^?
args.c;
// ^?
args.d;
// ^?
args.f;
// ^?
},
});
9 replies