Currently, I am exploring the integration of GraphQL with Angular. So far, I have been able to scaffold the schema successfully using the @graphql-codegen
package. The services generated are functional in querying the database.
However, I've noticed that the query results are structured unexpectedly, at least from my perspective. Although everything is strongly-typed, it seems like the intellisense is providing me with strongly-typed anonymous objects
(similar to those in C#).
Let's take a look at this particular GraphQL Query:
query Animals {
animals {
id
name
latinName
created
changed
changedBy
}
}
When executed against the database, the result returned is in JSON format as follows:
{
"data": {
"animals": [
{
"id": 1,
"name": "Rehwild",
"latinName": "Capreolus capreolus",
"created": "2023-04-01T19:29:45.513Z",
"changed": "2023-04-01T19:29:45.513Z",
"changedBy": ""
},
{
"id": 2,
"name": "Dammwild",
"latinName": "Dama dama",
"created": "2023-04-01T19:29:45.513Z",
"changed": "2023-04-01T19:29:45.513Z",
"changedBy": ""
}
]
}
}
With the code generation process, my expectation was to receive an array of type Animal[]
directly under the data property of the response, something akin to the following interface:
export interface Animal {
id: number;
name: string;
latinName: string;
created: string;
changed: string;
changedBy: string;
}
However, in the TypeScript code generated, there exists a type declaration for Animal
which includes additional properties not explicitly requested in the above GraphQL query:
/** A specific animal that can be searched for and saved. */
export type Animal = {
__typename?: 'Animal';
changed: Scalars['DateTime'];
changedBy: Scalars['String'];
created: Scalars['DateTime'];
id: Scalars['Int'];
latinName?: Maybe<Scalars['String']>;
name: Scalars['String'];
timesDied: Array<Death>;
timesRescued: Array<Rescue>;
};
Consequently, when attempting to load the data in the constructor of my component:
constructor(private animals: AnimalsGQL) {
this.animals$ = this.animals.watch().valueChanges.pipe(map(result => result.data.animals));
}
I'm observing a return type different from what I expected, instead of receiving Animal[]
.
https://i.sstatic.net/TDVLT.png
This discrepancy in type description poses challenges in various parts of my code. I would ideally prefer direct referencing to the relevant type rather than referring to an anonymous type
. Does anyone know why this behavior is occurring? Details of my setup and the codegen configuration are provided below.
Any assistance on this matter would be highly appreciated.
package.json:
{
"name": "tests",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test",
"codegen": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 graphql-codegen --config codegen.ts"
},
"private": true,
...
}
codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';
const config: CodegenConfig = {
overwrite: true,
schema: "https://localhost:7029/graphql",
documents: "src/**/*.graphql",
generates: {
"src/graphql/generated/graphql.ts": {
plugins: ['typescript', 'typescript-operations', 'typescript-apollo-angular'],
config: {
addExplicitOverride: true
}
},
"./graphql.schema.json": {
plugins: ["introspection"]
}
}
};
export default config;