dotansimha / dotansimha/graphql-code-generator
Incorrectly generates TypeScript type `{}` for empty object
- Dominant language
- TypeScript
- Stars
- 11.3k
- Forks
- 1.4k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 23
Description
### Which packages are impacted by your issue?
@graphql-codegen/typescript, @graphql-codegen/typescript-operations
### Describe the bug
Codegen creates the TypeScript type `{}` to represent an empty object, but that is incorrect because in TypeScript that means any types other than `null` and `undefined`.
The correct type to represent an empty object in TypeScript is `{ [key: PropertyKey]: never }` (my favourite way) or `Record`.
Deno lint's recommended rule set will actually put a lint error on `{}`, via the rule `ban-types`:
https://docs.deno.com/lint/rules/ban-types/
### Your Example Website or App
Nah
### Steps to Reproduce the Bug or Issue
An example of where empty objects can happen in GraphQL operations is:
```graphql
query Foo {
node(id: "") {
... on User {
__typename
}
}
}
```
Which will result in something like this:
```ts
export type FooQuery = {
readonly node:
| {
readonly __typename: "User";
}
| {}
| null;
};
```
Because in theory, you could use a node ID for something that's not a `User`, and end up with an empty object in the query data.
### Expected behavior
Here is a more correct type:
```ts
export type FooQuery = {
readonly node:
| {
readonly __typename: "User";
}
| { [key: PropertyKey]: never }
| null;
};
```
### Screenshots or Videos
_No response_
### Platform
- OS: macOS
- Deno: 2.4.2
- @graphql-codegen/cli: 5.0.7
- @graphql-codegen/near-operation-file-preset: 3.1.0
- @graphql-codegen/typescript: 4.1.6
- @graphql-codegen/typescript-operations: 4.6.1
- graphql: 16.11.0
### Codegen Config File
In `graphql.config.json`:
```json
{
"documents": "**/*.{graphql,mjs}",
"schema": "./schema.graphql",
"extensions": {
"codegen": {
"config": {
"avoidOptionals": true,
"defaultScalarType": "unknown",
"disableDescriptions": true,
"enumsAsTypes": true,
"immutableTypes": true,
"namingConvention": "keep",
"printFieldsOnNewLines": true,
"scalars": {
"Color": "string",
"DateTime": "string",
"Decimal": "string",
"HTML": "string",
"ISO8601DateTime": "string",
"JSON": "string",
"URL": "string",
"UnsignedInt64": "string"
},
"useTypeImports": true
},
"hooks": {
"afterOneFileWrite": ["deno fmt"]
},
"generates": {
"public/types/schema.mts": {
"plugins": ["typescript"],
"config": {
"onlyOperationTypes": true
}
},
"public/": {
"preset": "near-operation-file",
"presetConfig": {
"extension": ".types.mts",
"baseTypesPath": "types/schema.mts.mts"
},
"plugins": ["typescript-operations"],
"config": {
"skipTypename": true
}
}
}
}
}
}
```
### Additional context
A temporary workaround in the codegen config:
```json
{
"hooks": {
"afterOneFileWrite": [
"sed -i '' 's/{}/{ [key: PropertyKey]: never }/g'"
]
}
}
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.