francis
francis
Explore posts from servers
Aarktype
Created by francis on 9/23/2024 in #questions
Is there currently a known issue with arktype + trpc compatibility?
This is with latest RC.12
TypeError: Cannot read properties of undefined (reading 'traverse')
at assert (/node_modules/@ark/schema/out/roots/root.js:80:29)
at inputMiddleware (/node_modules/@trpc/server/dist/index.mjs:278:33)
at callRecursive (/node_modules/@trpc/server/dist/index.mjs:452:38)
at Object.next (/node_modules/@trpc/server/dist/index.mjs:461:32)
at eval (/src/lib/trpc/middleware.ts:21:15)
at callRecursive (/node_modules/@trpc/server/dist/index.mjs:452:38)
at resolve (/node_modules/@trpc/server/dist/index.mjs:482:30)
at callProcedure (/node_modules/@trpc/server/dist/config-d5fdbd39.mjs:155:12)
at inputToProcedureCall (/node_modules/@trpc/server/dist/resolveHTTPResponse-2fc435bb.mjs:46:28)`
TypeError: Cannot read properties of undefined (reading 'traverse')
at assert (/node_modules/@ark/schema/out/roots/root.js:80:29)
at inputMiddleware (/node_modules/@trpc/server/dist/index.mjs:278:33)
at callRecursive (/node_modules/@trpc/server/dist/index.mjs:452:38)
at Object.next (/node_modules/@trpc/server/dist/index.mjs:461:32)
at eval (/src/lib/trpc/middleware.ts:21:15)
at callRecursive (/node_modules/@trpc/server/dist/index.mjs:452:38)
at resolve (/node_modules/@trpc/server/dist/index.mjs:482:30)
at callProcedure (/node_modules/@trpc/server/dist/config-d5fdbd39.mjs:155:12)
at inputToProcedureCall (/node_modules/@trpc/server/dist/resolveHTTPResponse-2fc435bb.mjs:46:28)`
This occurs when I do .input(type(anything).assert). If I do something such as .input((i) => type(anything).assert(i)), it works fine. How on earth is it ending up with this being undefined when it is run this way?
4 replies
Aarktype
Created by francis on 9/23/2024 in #questions
How would you define an object with optional keys, but require at least one of the keys to be filled
An example of a very basic schema:
const schema = type({ a: type.string.optional(), b: type.string.optional() });
const schema = type({ a: type.string.optional(), b: type.string.optional() });
I'd like this to accept values {a: 'foo'}, { b: 'foo' }, and { a: 'foo', b: 'bar' }, but fail on {}. It would be a lovely bonus for the type to be inferred as { a: string, b?: string } | { a?: string, b: string } as well. Is there a way to do this without explicitly specifying that inferred type as an arktype union using .or?
15 replies
Aarktype
Created by francis on 9/21/2024 in #questions
Is there a recommended way to transform a type union into a discriminated union by adding a tag?
I'm not sure I'm describing this well, but I have a situation with two types that I am .or-ing together. It all works, but I'm interacting with a library that needs a discriminated union to function properly for type narrowing, and I am not sure how to add a discriminated union tag based on which type in the Or resolved (if that makes sense?) Here's a simple example to demonstrate:
const first = type({ key: "string" });
const second = type({ key: "number" });
const combined = first.or(second);
const first = type({ key: "string" });
const second = type({ key: "number" });
const combined = first.or(second);
I'd like to have this be resolve to e.g. { key: string, tag: 'first' } | { key: number, tag: 'second' } based on which branch in the union was followed. I've tried it with this:
const first = type({ key: "string" }).pipe((o) => ({ ...o, _tag: "first" }) as const);
const second = type({ key: "number" }).pipe((o) => ({ ...o, _tag: "second" }) as const);
const combined = first.or(second);
const first = type({ key: "string" }).pipe((o) => ({ ...o, _tag: "first" }) as const);
const second = type({ key: "number" }).pipe((o) => ({ ...o, _tag: "second" }) as const);
const combined = first.or(second);
and it works - but seems inelegant. Is there a more idiomatic solution?
13 replies
Aarktype
Created by francis on 9/21/2024 in #questions
Is there a way to do a case insensitive literal match?
I can pipe a string.lower to a lower-case literal but that seems complicated for this.
27 replies
Aarktype
Created by francis on 9/21/2024 in #questions
Is there a way to perform schema parsing generically?
My reasoning is to integrate Arktype with https://effect.website/ This most simple example fails:
function genericDemo<T>(schema: Type<T>, u: unknown): T {
return schema.assert(u);
}
function genericDemo<T>(schema: Type<T>, u: unknown): T {
return schema.assert(u);
}
This fails as the return type of .assert is finalizeDistillation<T, _distill<T, { endpoint: "out"; }>> Is there a way to coerce this back to a T? Or is there some constraint I need to put on the T input to make this work?
31 replies
Aarktype
Created by francis on 8/25/2024 in #questions
vscode intellisense errors on the same type definition in some files, but not others
e.g. the following type:
const exampleType = type({
email: "string.email",
});
const exampleType = type({
email: "string.email",
});
In some files, this works fine. In others, in the exact same project, this causes the following error:
Type '"string.email"' is not assignable to type '"'string' must reference a module to be accessed using dot syntax "'.
The expected type comes from property 'email' which is declared here on type 'validateObjectLiteral<{ readonly email: "string.email"; }, {}, bindThis<{ readonly email: "string.email"; }>>'
Type '"string.email"' is not assignable to type '"'string' must reference a module to be accessed using dot syntax "'.
The expected type comes from property 'email' which is declared here on type 'validateObjectLiteral<{ readonly email: "string.email"; }, {}, bindThis<{ readonly email: "string.email"; }>>'
Any ideas for what might be going on?
7 replies
Aarktype
Created by francis on 8/7/2024 in #questions
Are there examples of how to create mapped types?
e.g. a { [K in <SomeOtherType>]: SomeValueType } type, where SomeValueType is either a static type or is computed from K. I currently have a very basic setup where I have:
type MappedEnum<T extends string> = { readonly [K in T]: T };

const kitTypes = ["test_only", "test_self_serve", "test_guided_audit"];
const kitTypeValidator = type("===", ...kitTypes);
export type KitType = typeof kitTypeValidator.infer;
export const KitType = {
test_only: "test_only",
test_self_serve: "test_self_serve",
test_guided_audit: "test_guided_audit",
} as const satisfies MappedEnum<KitType>;
type MappedEnum<T extends string> = { readonly [K in T]: T };

const kitTypes = ["test_only", "test_self_serve", "test_guided_audit"];
const kitTypeValidator = type("===", ...kitTypes);
export type KitType = typeof kitTypeValidator.infer;
export const KitType = {
test_only: "test_only",
test_self_serve: "test_self_serve",
test_guided_audit: "test_guided_audit",
} as const satisfies MappedEnum<KitType>;
This pattern allows me to generate, from a string array, a validator for an element in that array, a type for an element of the resulting string union type, and a type for a runtime object that lets me access the values analogous to an enum. And it's great! My question is, I have the following type definition:
type KitCounts = { [K in KitType]?: number };
type KitCounts = { [K in KitType]?: number };
Is there a way to write an ArkType function that will generate a validator for this type (and the type definition itself), given the kitTypes array? My initial attempt is:
const kitCountsValidator = type(
Object.fromEntries(kitType.enumValues.map((k) => [`${k}?`, "number"])),
);
const kitCountsValidator = type(
Object.fromEntries(kitType.enumValues.map((k) => [`${k}?`, "number"])),
);
Obviously, this doesn't work, since the type information is completely lost. It actually works fine at runtime but the type is useless. Is there a way to do this without writing it out explicitly? (I have 5+ other enums that I'd like to process in a similar way)
22 replies
Aarktype
Created by francis on 8/2/2024 in #questions
How to accept a generic non-empty const string array for use in `type`?
Note: this may be a TS question, feel free to send me there instead. I have the following type: PgEnum<TValues extends [string, ...string[]]> { enumValues: TValues; } I'm attempting to create a function which accepts this object and returns an arktype instance of the union of the strings in the array, which is const with well-known values. If I call it directly from the const signature, e.g. type('===', obj.enumValues), it works fine. But I can't figure out how to accept this as a generic function parameter and use it in the body. I have tried:
function arktypeUnionFromEnum<A extends string, B extends string[]>(pgEnum: {
enumValues: [A, ...B];
}) {
return type("===", ...pgEnum.enumValues);
}
function arktypeUnionFromEnum<A extends string, B extends string[]>(pgEnum: {
enumValues: [A, ...B];
}) {
return type("===", ...pgEnum.enumValues);
}
This fails on the spread argument with
Argument of type 'A' is not assignable to parameter of type 'conform<A, unknown>'.
Type 'string' is not assignable to type 'conform<A, unknown>'.ts(2345)
Argument of type 'A' is not assignable to parameter of type 'conform<A, unknown>'.
Type 'string' is not assignable to type 'conform<A, unknown>'.ts(2345)
Unwinding the generic produces different errors:
function arktypeUnionFromEnum<T extends string[]>(pgEnum: { enumValues: T }) {
return type("===", ...pgEnum.enumValues);
}
function arktypeUnionFromEnum<T extends string[]>(pgEnum: { enumValues: T }) {
return type("===", ...pgEnum.enumValues);
}
leads to A spread argument must either have a tuple type or be passed to a rest parameter. Replacing string[] with [string, ...string[]] leads to the same issue. I suspect the two generic parameters is the closer approach, but I have no idea what this conform<> error is, or how to begin to address it.
3 replies