francis
francis
Explore posts from servers
DTDrizzle Team
Created by francis on 11/29/2024 in #help
Disambiguate optional one-to-one relationship
This is a similar problem to https://discord.com/channels/1043890932593987624/1084576896039260202/threads/1254869164607143998 - but instead involves two tables, one of which has a non-nullable foreign key to the other. https://drizzle.run/my887gq5kvpp1ogl3xpoe0zh I have table A that has an id column, and table B that has a nullable reference to table A on a unique column. This is an optional one-to-one relationship, however, there is another column on table B that is not unique and should have a many-to-one relationship to table A. It's possible to disambiguate many-to-one relationships, but I'm not sure how to disambiguate a one-to-one without including fields and references on the ambiguous one() on table A which makes the one-to-one relationship incorrectly non-nullable.
5 replies
Aarktype
Created by francis on 11/25/2024 in #questions
Is there a recommended way to create a Record using a type as a key?
None of these seem to work:
const stringKeys = type(
"===",
"CAR",
"ENDO",
"REP",
"DEV",
"GEN",
"NEU",
"ORG",
"IMM",
"RES",
"IRR",
"ECO",
);

const explicit = type.Record(stringKeys, type("number | null"));

const stringSyntax = type(
'Record<"CAR" | "ENDO" | "REP" | "DEV" | "GEN" | "NEU" | "ORG" | "IMM" | "RES" | "IRR" | "ECO", number | null>',
);
const stringKeys = type(
"===",
"CAR",
"ENDO",
"REP",
"DEV",
"GEN",
"NEU",
"ORG",
"IMM",
"RES",
"IRR",
"ECO",
);

const explicit = type.Record(stringKeys, type("number | null"));

const stringSyntax = type(
'Record<"CAR" | "ENDO" | "REP" | "DEV" | "GEN" | "NEU" | "ORG" | "IMM" | "RES" | "IRR" | "ECO", number | null>',
);
3 replies
Aarktype
Created by francis on 11/18/2024 in #questions
Are there docs on how to do non-trivial self reference?
I can't seem to find them. I'm aware of the this keyword, but I'm looking to do something like:
const example = type({
name: "string",
selves: "this[]",
});
const example = type({
name: "string",
selves: "this[]",
});
5 replies
Aarktype
Created by francis on 11/14/2024 in #questions
Is there a way to set a default value that is not valid?
This is due to svelte 5 - where you have to provide a meaningful non-undefined prop for bound values. e.g. for radio buttons, you need to default to "", not undefined. I am not sure how to define an Arktype type that accepts only an enum of values from the radio button, but defaults to empty-string. When I do the obvious inputType.default("") I get errors: ParseError: Default value is not assignable: must be "enum_option" (was "")
166 replies
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
DTDrizzle Team
Created by francis on 9/20/2024 in #help
How do you define two tables that have foreign keys to each other? drizzle-kit introspect fails
Drizzle-kit now generates a schema file with type errors - it was previously working prior to 0.24.0. In addition, the generated foreign key entry for multicolumn foreign keys has the columns in the incorrect order. (code below due to length limit)
5 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
DTDrizzle Team
Created by francis on 8/8/2024 in #help
What's the recommended way to do a basic filter by a boolean column's value?
I can't figure out how to use a non-filter expression for filtering. e.g., I would expect db.select().from(appointment).where(appointment.canceled) to generate the equivalent sql select * from appointment where appointment.canceled, which works exactly how I expect. .where(() => appointment.canceled) or .where((a) => a.canceled) don't work either. I can use
.where(sql`${appointment.canceled}`)
.where(sql`${appointment.canceled}`)
but surely there must be a simpler way? I can provide this column as an argument to a filter, so why can't I use this column itself as a filter?
3 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
DTDrizzle Team
Created by francis on 3/7/2024 in #help
New string mode date handling for postgres in 0.30.0 is potentially inconsistent
When selecting a value from a column of type timestamp with time zone, I receive the following string format: 2024-01-19 16:54:36.74526+00 When selecting a value from a column of type date, I receive the following string format: 1990-01-01T00:00:00.000Z It appears the serialization changes for the postgres driver may not be working - the ones here https://github.com/drizzle-team/drizzle-orm/blob/main/drizzle-orm/src/postgres-js/driver.ts#L27 If I define my own custom type as:
types: {
date_temp: {
to: 1082,
from: [1082],
serialize: (val: any) => val,
parse: (val: any) => val,
}
}
types: {
date_temp: {
to: 1082,
from: [1082],
serialize: (val: any) => val,
parse: (val: any) => val,
}
}
in the postgres-js options, then suddenly I receive the raw sql values I expect: 1990-01-01
2 replies
DTDrizzle Team
Created by francis on 1/28/2024 in #help
Issuing multiple sql queries in order, but without waiting for round trips?
I need to run several commands to set up transaction variables for my use case. They need to be run in order, but I don't need the result of any of them. Is there a way to issue e.g. 3 sequential commands in a single query to the database so I don't have to wait for the round trip for each one, like happens now with await tx.execute(.....) 3 times in a row?
21 replies
DTDrizzle Team
Created by francis on 1/16/2024 in #help
How do you create a scalar subquery in drizzle?
I want to create the drizzle analog of select * from table_a where id = (select a_id from table_b where id = <....>) This works in raw SQL, but I'm not sure how to construct the subquery to get only the a_id field to supply in the where condition.
drizzle.select().from(tableA).where(eq(tableA.id, drizzle.select(<WHAT GOES HERE>).from(tableB).where(eq(tableB.id, userInputBId))))
drizzle.select().from(tableA).where(eq(tableA.id, drizzle.select(<WHAT GOES HERE>).from(tableB).where(eq(tableB.id, userInputBId))))
11 replies
DTDrizzle Team
Created by francis on 1/14/2024 in #help
Is there a way to get the update count resulting from a query without returning?
I would like to assert that a statement in a transaction updates only the number of rows I expect, and fail if that number is different. I can do it with result.length and returning() but that includes a ton of data I don't need.
8 replies
DTDrizzle Team
Created by francis on 12/28/2023 in #help
Does calling `drizzle()` multiple times on the same db client instance consume more resources?
related to a question from: https://github.com/drizzle-team/drizzle-orm/issues/594 Would using the same postgres(...) client instance and creating multiple Drizzle instances from it, e.g. one for each request in a middleware, consume additional database connection resources compared to creating one drizzle instance for the whole server process? @Angelelz this is related to the question you asked in the github issue. I believe my current implementation doesn't have this problem since it uses proxies, but I was about to refactor to call drizzle() once per request and want to make sure I'm not about to blow up my database!
7 replies
DTDrizzle Team
Created by francis on 12/28/2023 in #help
Is there a better way to extract Typescript types for use in function args than what I'm doing here?
export const client = drizzle(adminPgClient, { schema });
export type DrizzleClient = typeof client;
export type DrizzleTransaction = Parameters<Parameters<DrizzleClient["transaction"]>[0]>[0];
export const client = drizzle(adminPgClient, { schema });
export type DrizzleClient = typeof client;
export type DrizzleTransaction = Parameters<Parameters<DrizzleClient["transaction"]>[0]>[0];
It works well enough, but this seems like something which should be exposed on a library level, maybe? I need it in order to e.g. write a function which takes in a transaction and performs operations on it, such that multiple functions can be called on a single transaction and then the transaction either committed or rolled back as one unit (so the client cannot be passed in instead).
12 replies