Skip to content

Commit

Permalink
Loosen type of e.shape's returned scope (#1045)
Browse files Browse the repository at this point in the history
Type intersection creates an expression with a fixed `__shape__`
expression. This was being glossed over before because the parameter
type was `unknown`, but once we switched it to match the scopified
object expression, it became too strict for use with intersections.
  • Loading branch information
scotttrinh authored Jun 21, 2024
1 parent 936f952 commit 252b0ab
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 14 deletions.
16 changes: 5 additions & 11 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,18 @@ jobs:
run: |
yarn run format
- name: ESLint (ignore failures for now)
run: |
yarn eslint || echo "ESLint still failing... Fine for now!"
- name: Build
run: |
yarn workspace edgedb build
yarn workspace @edgedb/generate build
yarn workspace @edgedb/auth-core build
yarn workspace @edgedb/ai build
- name: Typecheck
run: |
yarn workspaces run typecheck
# - name: Compile for Deno
# run: |
# yarn build:deno
# Only typecheck the following since nothing depends on these packages
yarn workspace @edgedb/auth-remix run typecheck
yarn workspace @edgedb/auth-nextjs run typecheck
yarn workspace @edgedb/auth-express run typecheck
yarn workspace @edgedb/auth-sveltekit run typecheck
- name: Install EdgeDB
uses: edgedb/setup-edgedb@6763b6de72782d9c2e5ecc1095986a1c707da68f
Expand Down
25 changes: 25 additions & 0 deletions integration-tests/lts/select.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,12 @@ SELECT __scope_0_defaultPerson {
name: true,
id: true,
}));
const heroShape = e.shape(e.Hero, () => ({
villains: true,
}));
const villainShape = e.shape(e.Villain, () => ({
nemesis: true,
}));
const profileShape = e.shape(e.Profile, () => ({
slug: true,
}));
Expand Down Expand Up @@ -1413,6 +1419,25 @@ SELECT __scope_0_defaultPerson {
assert.ok(result.title);
assert.ok(result.rating);
assert.ok(result.characters);

const cast = e.select(query, () => ({ characters: true }));
const freeObjWithShape = e.select({
heros: e.select(cast.characters.is(e.Hero), (h) => {
return heroShape(h);
}),
villains: e.select(cast.characters.is(e.Villain), villainShape),
});
type FreeObjWithShape = $infer<typeof freeObjWithShape>;
tc.assert<
tc.IsExact<
FreeObjWithShape,
{
heros: { villains: { id: string }[] }[];
villains: { nemesis: { id: string } | null }[];
}
>
>(true);
assert.ok(freeObjWithShape);
});

test("filter_single id", async () => {
Expand Down
12 changes: 10 additions & 2 deletions packages/generate/src/syntax/select.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import type {
ExclusiveTuple,
orLiteralValue,
EnumType,
assert_single,
} from "./typesystem";

import {
Expand Down Expand Up @@ -855,11 +856,18 @@ function $shape<
? Cardinality.One
: Expr[k];
}>,
ElementOfAnyShape extends Omit<Element, "__shape__"> & { __shape__: any },
>(
_expr: Expr,
shape: (scope: Scope) => Readonly<Shape>,
): (scope: Scope) => Readonly<Shape> {
return shape;
): (
scope: Omit<Scope, "__element__" | "assert_single"> & {
__element__: ElementOfAnyShape;
assert_single(): assert_single<ElementOfAnyShape, Cardinality.AtMostOne>;
},
) => Readonly<Shape>;
function $shape(_a: unknown, b: (...args: any) => any) {
return b;
}
export { $shape as shape };

Expand Down
3 changes: 2 additions & 1 deletion packages/generate/src/syntax/typesystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,8 @@ export type ExpressionMethods<Set extends TypeSet> = {
ObjectType<
T["__element__"]["__name__"],
T["__element__"]["__pointers__"],
{ id: true }
{ id: true },
T["__element__"]["__exclusives__"]
>
>;
assert_single(): assert_single<
Expand Down

0 comments on commit 252b0ab

Please sign in to comment.