Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce type instantiations in e.literal #924

Merged
merged 12 commits into from Apr 3, 2024
2 changes: 1 addition & 1 deletion integration-tests/legacy/package.json
Expand Up @@ -16,7 +16,7 @@
"jest": "^29.5.0",
"superjson": "^1.12.4",
"ts-jest": "^29.1.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"dependencies": {}
}
103 changes: 85 additions & 18 deletions integration-tests/lts/bench.ts
@@ -1,43 +1,100 @@
import { bench } from "@arktype/attest";

import e from "./dbschema/edgeql-js";
import { type BaseTypeToTsType } from "./dbschema/edgeql-js/typesystem";

bench("scalar literal", () => {
bench("BaseTypeToTsType: scalar", () => {
const lit = e.int32(42);
return {} as BaseTypeToTsType<typeof lit>;
}).types([596, "instantiations"]);

bench("e.literal: scalar", () => {
const lit = e.literal(e.int32, 42);
return {} as typeof lit;
}).types([755, "instantiations"]);

bench("e.int32: scalar", () => {
const lit = e.int32(42);
return {} as typeof lit;
}).types([556, "instantiations"]);

bench("e.str: scalar", () => {
const lit = e.str("abcd");
return {} as typeof lit;
}).types([555, "instantiations"]);
}).types([894, "instantiations"]);

bench("array literal", () => {
bench("BaseTypeToTsType: array literal", () => {
const lit = e.array([e.str("abcd")]);
return {} as BaseTypeToTsType<typeof lit>;
}).types([2394, "instantiations"]);

bench("e.literal: array literal", () => {
const lit = e.literal(e.array(e.str), ["abcd"]);
return {} as typeof lit;
}).types([2407, "instantiations"]);
}).types([1980, "instantiations"]);

bench("e.array: array literal", () => {
const lit = e.array([e.str("abcd")]);
return {} as typeof lit;
}).types([2367, "instantiations"]);

bench("named tuple literal", () => {
bench("e.literal: named tuple literal", () => {
const lit = e.literal(e.tuple({ str: e.str }), {
str: "asdf",
});
return {} as typeof lit;
}).types([11597, "instantiations"]);
}).types([10765, "instantiations"]);

bench("e.tuple: named tuple literal", () => {
const lit = e.tuple({ str: e.str("asdf") });
return {} as typeof lit;
}).types([7564, "instantiations"]);

bench("e.literal: tuple literal", () => {
const lit = e.literal(e.tuple([e.str, e.int32]), ["asdf", 42]);
return {} as typeof lit;
}).types([4670, "instantiations"]);

bench("e.tuple: tuple literal", () => {
const lit = e.tuple([e.str("asdf"), e.int32(42)]);
return {} as typeof lit;
}).types([4836, "instantiations"]);

bench("e.literal: array of tuples", () => {
const lit = e.literal(e.array(e.tuple([e.str, e.int32])), [
["asdf", 42],
["qwer", 43],
]);
return {} as typeof lit;
}).types([5664, "instantiations"]);

bench("e.array: array of tuples", () => {
const lit = e.array([
e.tuple([e.str("asdf"), e.int32(42)]),
e.tuple([e.str("qwer"), e.int32(43)]),
]);
return {} as typeof lit;
}).types([20582, "instantiations"]);

bench("base type: array", () => {
const baseType = e.array(e.str);
return {} as typeof baseType;
}).types([348, "instantiations"]);
}).types([351, "instantiations"]);

bench("base type: named tuple", () => {
const baseType = e.tuple({ str: e.str });
return {} as typeof baseType;
}).types([2160, "instantiations"]);
}).types([3564, "instantiations"]);

bench("select: scalar", () => {
const query = e.select(e.int32(42));
return {} as typeof query;
}).types([1155, "instantiations"]);
}).types([1173, "instantiations"]);

bench("select: free object", () => {
const query = e.select({ meaning: e.int32(42) });
return {} as typeof query;
}).types([2012, "instantiations"]);
}).types([2027, "instantiations"]);

bench("select: id only", () => {
const query = e.select(e.User, () => ({ id: true }));
Expand All @@ -49,7 +106,7 @@ bench("select: filtered", () => {
filter_single: { id: e.uuid("123") },
}));
return {} as typeof query;
}).types([5019, "instantiations"]);
}).types([5100, "instantiations"]);

bench("select: nested", () => {
const user = e.select(e.User, () => ({
Expand All @@ -58,7 +115,7 @@ bench("select: nested", () => {
const query = e.select(user, () => ({ id: true }));

return {} as typeof query;
}).types([6037, "instantiations"]);
}).types([6116, "instantiations"]);

bench("select: complex", () => {
const query = e.select(e.Movie, () => ({
Expand All @@ -70,7 +127,7 @@ bench("select: complex", () => {
}),
}));
return {} as typeof query;
}).types([6342, "instantiations"]);
}).types([6352, "instantiations"]);

bench("select: with filter", () => {
const query = e.select(e.Hero, (hero) => ({
Expand All @@ -82,7 +139,7 @@ bench("select: with filter", () => {
filter_single: e.op(hero.name, "=", "Peter Parker"),
}));
return {} as typeof query;
}).types([6289, "instantiations"]);
}).types([6428, "instantiations"]);

bench("select: with order", () => {
const query = e.select(e.Hero, (hero) => ({
Expand All @@ -95,7 +152,7 @@ bench("select: with order", () => {
filter_single: e.op(hero.name, "=", "Peter Parker"),
}));
return {} as typeof query;
}).types([6624, "instantiations"]);
}).types([6765, "instantiations"]);

bench("select: with limit", () => {
const query = e.select(e.Hero, (hero) => ({
Expand All @@ -108,7 +165,7 @@ bench("select: with limit", () => {
filter_single: e.op(hero.name, "=", "Peter Parker"),
}));
return {} as typeof query;
}).types([6352, "instantiations"]);
}).types([6490, "instantiations"]);

bench("select: with offset", () => {
const query = e.select(e.Hero, (hero) => ({
Expand All @@ -121,7 +178,7 @@ bench("select: with offset", () => {
filter_single: e.op(hero.name, "=", "Peter Parker"),
}));
return {} as typeof query;
}).types([6391, "instantiations"]);
}).types([6533, "instantiations"]);

bench("params select", () => {
const query = e.params({ name: e.str }, (params) =>
Expand All @@ -135,4 +192,14 @@ bench("params select", () => {
}))
);
return {} as typeof query;
}).types([11865, "instantiations"]);
}).types([11290, "instantiations"]);

bench("e.op: str = str", () => {
const op = e.op(e.str("a"), "=", e.str("b"));
return {} as typeof op;
}).types([1854, "instantiations"]);

bench("e.op: str ilike str", () => {
const op = e.op(e.str("a"), "ilike", e.str("b"));
return {} as typeof op;
}).types([51413, "instantiations"]);
2 changes: 1 addition & 1 deletion integration-tests/lts/package.json
Expand Up @@ -24,7 +24,7 @@
"jest": "^29.5.0",
"superjson": "^1.12.4",
"ts-jest": "^29.1.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"dependencies": {}
}
12 changes: 9 additions & 3 deletions integration-tests/lts/select.test.ts
Expand Up @@ -1162,7 +1162,9 @@ SELECT __scope_0_defaultPerson {
name: h.name,
otherHeros: e.select(e.Hero, (h2) => ({
name: true,
names: e.op(h.name, "++", h2.name),
name_one: h.name,
name_two: h2.name,
names_match: e.op(h.name, "=", h2.name),
order_by: h2.name,
})),
order_by: h.name,
Expand All @@ -1176,7 +1178,9 @@ SELECT __scope_0_defaultPerson {
name: h.name,
otherHeros: heros.map((h2) => ({
name: h2.name,
names: h.name + h2.name,
name_one: h.name,
name_two: h2.name,
names_match: h.name === h2.name,
})),
}));

Expand Down Expand Up @@ -1377,9 +1381,11 @@ SELECT __scope_0_defaultPerson {

const result = await query.run(client);

type Result = typeof result;

tc.assert<
tc.IsExact<
typeof result,
Result,
{ xy: { a: string | null; b: number | null } | null }[]
>
>(true);
Expand Down
2 changes: 1 addition & 1 deletion integration-tests/nightly/package.json
Expand Up @@ -16,7 +16,7 @@
"jest": "^29.5.0",
"superjson": "^1.12.4",
"ts-jest": "^29.1.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"dependencies": {}
}
2 changes: 1 addition & 1 deletion integration-tests/stable/package.json
Expand Up @@ -16,7 +16,7 @@
"jest": "^29.5.0",
"superjson": "^1.12.4",
"ts-jest": "^29.1.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"dependencies": {}
}
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -15,7 +15,7 @@
"tslint": "^6.1.3",
"tslint-config-prettier": "^1.18.0",
"tslint-plugin-prettier": "^2.3.0",
"typescript": "^5.2.2"
"typescript": "^5.4.2"
},
"scripts": {
"lint": "tslint 'packages/*/src/**/*.ts'",
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-core/package.json
Expand Up @@ -37,7 +37,7 @@
"edgedb": "^1.4.0",
"jest": "29.5.0",
"ts-jest": "29.1.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"peerDependencies": {
"edgedb": "^1.3.6"
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-express/package.json
Expand Up @@ -31,7 +31,7 @@
"@types/node": "^20.8.4",
"edgedb": "^1.3.6",
"express": "^4.18.2",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"peerDependencies": {
"cookie-parser": "^1.4.6",
Expand Down
8 changes: 4 additions & 4 deletions packages/auth-nextjs/package.json
Expand Up @@ -27,13 +27,13 @@
"@types/react": "^18.2.42",
"edgedb": "^1.3.6",
"next": "13.5.6",
"typescript": "^5.2.2",
"react": "^18.2.0"
"react": "^18.2.0",
"typescript": "^5.4.3"
},
"peerDependencies": {
"edgedb": "^1.3.6",
"react": "^18.2.0",
"next": ">=13.5.6 <15.0.0"
"next": ">=13.5.6 <15.0.0",
"react": "^18.2.0"
},
"dependencies": {
"@edgedb/auth-core": "0.2.0-beta.1"
Expand Down
2 changes: 1 addition & 1 deletion packages/auth-remix/package.json
Expand Up @@ -21,7 +21,7 @@
"devDependencies": {
"@types/node": "^20.8.4",
"edgedb": "^1.4.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"peerDependencies": {
"edgedb": "^1.3.6"
Expand Down
4 changes: 2 additions & 2 deletions packages/auth-sveltekit/package.json
Expand Up @@ -19,11 +19,11 @@
"build": "tsc --project tsconfig.json"
},
"devDependencies": {
"@sveltejs/kit": "^2.0.0",
"@types/node": "^20.8.4",
"edgedb": "^1.3.6",
"typescript": "^5.2.2",
"svelte": "^4.2.7",
"@sveltejs/kit": "^2.0.0",
"typescript": "^5.4.3",
"vite": "^5.0.3"
},
"peerDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/create/package.json
Expand Up @@ -23,7 +23,7 @@
"@types/debug": "^4.1.12",
"@types/node": "^20.10.4",
"tsx": "^4.6.2",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"dependencies": {
"@clack/prompts": "^0.7.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/driver/package.json
Expand Up @@ -34,7 +34,7 @@
"jest-environment-jsdom": "^29.5.0",
"ts-jest": "29.1.0",
"tsx": "^3.12.7",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"scripts": {
"typecheck": "tsc --project tsconfig.json --noEmit",
Expand Down
2 changes: 1 addition & 1 deletion packages/generate/package.json
Expand Up @@ -31,7 +31,7 @@
"jest": "^29.5.0",
"superjson": "^1.12.4",
"ts-jest": "^29.1.0",
"typescript": "^5.2.2"
"typescript": "^5.4.3"
},
"dependencies": {},
"scripts": {
Expand Down
11 changes: 6 additions & 5 deletions packages/generate/src/syntax/literal.ts
Expand Up @@ -27,16 +27,17 @@ export type $expr_Literal<Type extends BaseType = BaseType> = Expression<{
__value__: any;
}>;

export function literal<T extends BaseType>(
type: T,
value: BaseTypeToTsType<T>
): $expr_Literal<T> {
export function literal<
T extends BaseType,
TsType extends BaseTypeToTsType<T> = BaseTypeToTsType<T>,
ExprType extends $expr_Literal<T> = $expr_Literal<T>
>(type: T, value: TsType): ExprType {
return $expressionify({
__element__: type,
__cardinality__: Cardinality.One,
__kind__: ExpressionKind.Literal,
__value__: value,
}) as any;
}) as ExprType;
}

export const $nameMapping = new Map<string, string>([
Expand Down
4 changes: 2 additions & 2 deletions packages/generate/src/syntax/path.ts
Expand Up @@ -77,9 +77,9 @@ export type $pathify<
// Parent extends PathParent | null = null
> = Root extends ObjectTypeSet
? ObjectTypeSet extends Root
? {} // Root is literally ObjectTypeSet
? unknown // Root is literally ObjectTypeSet
: pathifyPointers<Root> & pathifyShape<Root> & $linkPropify<Root>
: {}; // pathify does nothing on non-object types
: unknown; // pathify does nothing on non-object types

export type pathifyPointers<
Root extends ObjectTypeSet
Expand Down