Skip to content

Commit a0d9ea2

Browse files
authored
Replace Key type param with SourceAtKey on Field type (#26)
1 parent a8df678 commit a0d9ea2

File tree

6 files changed

+257
-142
lines changed

6 files changed

+257
-142
lines changed

.changeset/afraid-colts-jam.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
"@graphql-ts/extend": major
3+
"@graphql-ts/schema": major
4+
---
5+
6+
The `Key` type parameter on `Field` has been replaced with a new type parameter (`SourceAtKey`) and represents essentially `Source[Key]` instead of `Key`. For example, a field like this can be written:
7+
8+
```ts
9+
const field = g.field({
10+
type: g.String,
11+
});
12+
```
13+
14+
and `field` will be usable like this:
15+
16+
```ts
17+
const Something = g.object<{
18+
name: string
19+
}>({
20+
name: "Something"
21+
fields: {
22+
name: field,
23+
// @ts-expect-error
24+
other: field
25+
},
26+
});
27+
```
28+
29+
The field is usable at `name` since the source type has an object with a `name` property that's a `string` but using it at `other` will result in a type error since the source type doesn't have a `other` property.
30+
31+
Previously, using `g.field` outside a `g.object`/`g.fields` call would require specifying a resolver and fields written within `g.fields` would be bound to be used at a specific key rather than the new behaviour of any key with the right type.
32+
33+
This also reduces the need for `g.fields`. For example, the example given in the previous JSDoc for `g.fields`:
34+
35+
```ts
36+
const nodeFields = g.fields<{ id: string }>()({
37+
id: g.field({ type: g.ID }),
38+
});
39+
const Node = g.interface<{ id: string }>()({
40+
name: "Node",
41+
fields: nodeFields,
42+
});
43+
const Person = g.object<{
44+
__typename: "Person";
45+
id: string;
46+
name: string;
47+
}>()({
48+
name: "Person",
49+
interfaces: [Node],
50+
fields: {
51+
...nodeFields,
52+
name: g.field({ type: g.String }),
53+
},
54+
});
55+
```
56+
57+
Now the `g.fields` call is unnecessary and writing `nodeFields` will no longer error at the `g.field` call and will instead work as expected.
58+
59+
```ts
60+
const nodeFields = {
61+
id: g.field({ type: g.ID }),
62+
};
63+
```
64+
65+
There is still some use to `g.fields` for when you want to define a number of shared fields with resolvers and specify the source type just once in the `g.fields` call rathe than in every resolver.
66+
67+
This change is unlikely to break existing code except where you explicitly use the `Field` type or explicitly pass type parameters to `g.field` (the latter of which you likely shouldn't do) but since it changes the meaning of a type parameter of `Field`, it's regarded as a breaking change.

packages/extend/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ function flattenExtensions(
377377
* type would immediately be thrown away, it would be pretty much pointless.
378378
*/
379379
type FieldsOnAnything = {
380-
[key: string]: Field<unknown, any, OutputType<any>, string, any>;
380+
[key: string]: Field<unknown, any, OutputType<any>, unknown, any>;
381381
};
382382

383383
/**

0 commit comments

Comments
 (0)