From c8b720f17c52d41ea557c10624a3a436af57bd72 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 17 Jan 2024 14:10:35 +0000 Subject: [PATCH 1/3] Test for unmasking empty objects --- src/__tests__/api.test-d.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/__tests__/api.test-d.ts b/src/__tests__/api.test-d.ts index 0e420a1d..35c148f2 100644 --- a/src/__tests__/api.test-d.ts +++ b/src/__tests__/api.test-d.ts @@ -38,6 +38,19 @@ describe('mirrorFragmentTypeRec', () => { }); describe('readFragment', () => { + it('should not unmask empty objects', () => { + type fragment = parseDocument<` + fragment Fields on Todo { + id + } + `>; + + type document = getDocumentNode; + // @ts-expect-error + const result = readFragment({} as document, {}); + expectTypeOf().toBeNever(); + }); + it('unmasks regular fragments', () => { type fragment = parseDocument<` fragment Fields on Todo { From 5d89abbb0d32d91678463bb24a6ca3319cd898e5 Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 17 Jan 2024 14:11:05 +0000 Subject: [PATCH 2/3] Make fragmentRefs a required property --- src/__tests__/selection.test-d.ts | 4 ++-- src/api.ts | 7 ++++++- src/namespace.ts | 4 ++-- website/src/content/docs/get-started/writing-graphql.mdx | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/__tests__/selection.test-d.ts b/src/__tests__/selection.test-d.ts index 56e7c8ac..58af4a07 100644 --- a/src/__tests__/selection.test-d.ts +++ b/src/__tests__/selection.test-d.ts @@ -219,7 +219,7 @@ test('infers fragment spreads for fragment refs', () => { type actual = getDocumentType; type expected = { - [$tada.fragmentRefs]?: { + [$tada.fragmentRefs]: { Fields: extraFragments['Fields'][$tada.fragmentId]; }; }; @@ -235,7 +235,7 @@ test('marks undefined fragments with special fragment ref error', () => { type actual = getDocumentType; type expected = { - [$tada.fragmentRefs]?: { + [$tada.fragmentRefs]: { Fields: 'Undefined Fragment'; }; }; diff --git a/src/api.ts b/src/api.ts index acd48923..7b09eee0 100644 --- a/src/api.ts +++ b/src/api.ts @@ -349,7 +349,12 @@ type fragmentOfTypeRec = function readFragment< const Document extends DocumentDefDecorationLike & DocumentDecoration, const Fragment extends fragmentOfTypeRec, ->(_document: Document, fragment: Fragment): mirrorFragmentTypeRec> { +>( + _document: Document, + fragment: Fragment +): fragmentOfTypeRec extends Fragment + ? never + : mirrorFragmentTypeRec> { return fragment as any; } diff --git a/src/namespace.ts b/src/namespace.ts index 7d4af31e..43b0770f 100644 --- a/src/namespace.ts +++ b/src/namespace.ts @@ -63,13 +63,13 @@ type getFragmentsOfDocumentsRec = Documents extends readonly [ : {}; type makeFragmentRef = obj<{ - [$tada.fragmentRefs]?: { + [$tada.fragmentRefs]: { [Name in Definition['name']['value']]: Definition[$tada.fragmentId]; }; }>; type makeUndefinedFragmentRef = { - [$tada.fragmentRefs]?: { + [$tada.fragmentRefs]: { [Name in FragmentName]: 'Undefined Fragment'; }; }; diff --git a/website/src/content/docs/get-started/writing-graphql.mdx b/website/src/content/docs/get-started/writing-graphql.mdx index d6a8ca0b..5cf00d51 100644 --- a/website/src/content/docs/get-started/writing-graphql.mdx +++ b/website/src/content/docs/get-started/writing-graphql.mdx @@ -197,7 +197,7 @@ const result: ResultOf = { todos: [ { id: 'ExampleID', - [$tada.fragmentRefs]?: { + [$tada.fragmentRefs]: { TodoItem: unique symbol; }; }, From a03789792da707a40c19c5f3a33b6f8c2d88bbeb Mon Sep 17 00:00:00 2001 From: Phil Pluckthun Date: Wed, 17 Jan 2024 14:12:15 +0000 Subject: [PATCH 3/3] Add changeset --- .changeset/rude-bulldogs-kneel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/rude-bulldogs-kneel.md diff --git a/.changeset/rude-bulldogs-kneel.md b/.changeset/rude-bulldogs-kneel.md new file mode 100644 index 00000000..951466b1 --- /dev/null +++ b/.changeset/rude-bulldogs-kneel.md @@ -0,0 +1,5 @@ +--- +'gql.tada': patch +--- + +Make `$tada.fragmentRefs` property required. Previously, this was optional (to mirror what GCG’s client-preset does). However, this can lead to invalid checks in `readFragment`, as it would be able to match types that don’t actually match the fragment refs.