Enhance your coding experience with Angular Apollo Codegen providing intelligent suggestions for anonymous objects

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;

Answer №1

Anonymous types do not exist in TypeScript. Frequently, interfaces are mentioned by name in tooltips, while types can be displayed directly in tooltips, but this is not always the case. At times, TypeScript handles it differently.

Ultimately, the content of a tooltip does not impact how TypeScript functions. Whether the type is inlined or referenced by name, TypeScript will treat it identically and it will not affect anything else.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Extracting live TV channels from an m3u file by differentiating them from VOD content

Currently, I am developing an IPTV player app and have successfully parsed the m3u file. My current challenge is separating live TV channels from Video on Demand (VOD). I am unsure of where exactly the transition happens in the playlists. Below are the ke ...

Using event.target to pass HTML form data to FormData is causing an error stating that the Argument of type 'EventTarget' cannot be assigned to a parameter of type 'HTMLFormElement'

Looking to extract data from a form and store it in FormData: const handleSubmit = (e: FormEvent<HTMLFormElement>) => { e.preventDefault(); const formData = new FormData(e.target as HTMLFormElement); const value = formData.get(' ...

Refine the observable data

Trying to filter a list of items from my Firebase database based on location.liked === true has been a challenge for me. I've attempted using the traditional filter array method but have not had success. Can anyone suggest an alternative method to acc ...

Organize items within an array based on dual properties rather than a single one

Here is an array of objects that I would like to group based on certain keys (JSON format): [ { "name": "john", "lastName": "doe", "gender": "male" }, { "name": &qu ...

A more efficient method for refreshing Discord Message Embeds using a MessageComponentInteraction collector to streamline updates

Currently, I am working on developing a horse race command for my discord bot using TypeScript. The code is functioning properly; however, there is an issue with updating an embed that displays the race and the participants. To ensure the update works co ...

Unexpected behavior: ng2-dragula modelDrop event leading to undefined array

Struggling to figure out the issue with this code. As shown in this GIF, when dragging a div from one container to another, the object disappears and the array becomes undefined. https://i.stack.imgur.com/TELyc.gif Here is the code snippet: Main View.ht ...

Responding to ipcMain events within Spectron

I created an electron application that initiates a launcher window (in a renderer process) first, which then starts multiple background services. Once these background services are successfully started, it sends the message "services-running" on its ipcRen ...

Initiating Angular APP_INITIALIZERThe Angular APP_INITIALIZER

I am a newcomer to Angular and currently utilizing Angular6 for development purposes. I have a specific query regarding my app. Before the app initializes, I need to invoke three services that provide configurations required by the app. Let's refer to ...

What is the process of playing blob videos (avi, mov) in Angular14?

I've been struggling with this issue for quite some time without knowing how to resolve it. After some research, I came across a similar question: how to play blob video in angular. However, the problem is that the demo provided in the answer does no ...

Unable to retrieve multiple values from a sinon stub

I am trying to stub a method using sinon in my Typescript code with Bluebird promises. However, I'm running into an issue where only the first value I set for the stub is being returned, even though I want it to return a different value on the second ...

Passing Selected Table Row Model Data to Backend in Angular 7

My goal is to send the selected data in a table row, which I select through a checkbox, to the server. However, I'm unsure about how to handle this via a service call. While I have the basic structure in place, I need assistance with sending the items ...

Getting into a dynamic named property inside another object in angular can be achieved by utilizing bracket notation

I encountered an issue in my Angular 8 project where I create an object from a JSON, but there is a dynamic property whose name is unknown until runtime. This causes problems when trying to access the value of that dynamic property within another object, l ...

Customize YouTube iframe styles in Angular 4+ with TypeScript

Has anyone been successful in overriding the style of an embedded YouTube iframe using Angular 4+ with TypeScript? I've attempted to override a CSS class of the embed iframe, but have not had any luck. Here is the URL to YouTube's stylesheet: ...

Encountering issues while trying to incorporate a trading chart library into an Angular 7 project

ERROR in src/assets/datafeeds/udf/src/udf-compatible-datafeed-base.ts(243,74): error TS2339: 'errmsg' Property Not Found The property 'errmsg' does not exist on the type 'UdfErrorResponse | UdfSearchSymbolsResponse'. The p ...

Creating a Union Type from a JavaScript Map in Typescript

I am struggling to create a union type based on the keys of a Map. Below is a simple example illustrating what I am attempting to achieve: const myMap = new Map ([ ['one', <IconOne/>], ['two', <IconTwo/>], ['three ...

Ways to troubleshoot issues with the ng bootstrap package

Having an issue debugging ng-bootstrap 4 in my Angular 7 project, I decided to follow the instructions provided on this link to clone ng-bootstrap and install dependencies using yarn. The process completed without any errors. However, when attempting to np ...

Ways to protect the URL link for attachments obtained from cloud services

I have created an Angular form that allows users to upload attachments. Once uploaded, the attachments are securely stored in an Azure Storage Account. Upon successful upload, a unique URL for the attachment is generated and returned. However, the curren ...

Tips for testing validation messages in Angular template-driven forms

I have created a simple Angular template-driven form with one required field. An error message is supposed to be shown if the field is not valid, such as when the component is initially loaded and the required field is empty. The code functions correctly i ...

"Unsubscribing in Angular via a button click: A step-by

I'm having trouble canceling a subscription for "device orientation" in Angular using (click) in HTML. I've tried multiple solutions but none seem to work. Does anyone have any ideas on how to fix this? TS // Watching the change in device compa ...

You must pass a string, Buffer, ArrayBuffer, or Array as the first argument when using Uint8Array.slice(). A number was received instead

Here is my implementation of the ByteArray class, which extends the Uint8Array class. export class ByteArray extends Uint8Array { ... private _encoded: string; ... constructor(_encoded: string) { super(Buffer.from(_encoded, " ...