dotansimha / dotansimha/graphql-code-generator

Incorrectly generates TypeScript type `{}` for empty object

Open
#10,385 10 comments 0 reactions 1 assignee Claimed by @eddeee888 View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.