4

I am using graphql with generated types and struggling with how to convert them to the type I need to pass it to my data service calls.

@graphql-codegen has given me an args type of

export type QueryOrdersArgs = {
  ids: Array<Maybe<Scalars['ID']>>;
};

(I don't really understand why its generated as a Maybe type, as the graphql schema enforces that I only query with a parameter of an array of ids (strings))

In my resolver, I need to call into a service which takes an array of strings. Everything works as expected (with @ts-ignore) but now I need to fix up my types.

const { orderIds } = args;
const result = getOrder(orderIds);

I have a codesandbox with just the types here https://codesandbox.io/s/typescript-playground-export-forked-3fpx9?file=/index.ts

export type Maybe<T> = T | null;
export type Scalars = {
  ID: string;
  String: string;
  Boolean: boolean;
  Int: number;
  Float: number;
  _FieldSet: any;
};

let ids: Array<Maybe<Scalars["ID"]>>;

export const getOrders = (orderIds: Array<string>) => {
  orderIds.map((x) => console.log(x));
};

getOrders(ids);

I currently get the error - "TS2345: Argument of type 'Maybe[]' is not assignable to parameter of type 'string[]'."

Any help greatly appreciated

tmc
  • 404
  • 1
  • 7
  • 20

3 Answers3

2

If you're confident that it shouldn't be a Maybe type, you can cast it:

type Maybe<T> = T | null;
const maybeArray: Maybe<string>[] = [];
let stringArray: string[] = maybeArray as string[];

or in your case

getOrders(ids as string[]);
Slava Knyazev
  • 5,377
  • 1
  • 22
  • 43
  • 1
    Your problem here is your type is now wrong. It is possible some of the string values in this array are null per the Maybe type. You would want to first filter out null before casting to string[], or you can run into null pointers later in your code. – user1015434 Sep 15 '21 at 15:18
  • Correct — but OP says that the graphql generated types are wrong. Casting signals that, rather than implying that the type is correct, and just needs to be dealt with. In all other cases, filtering is the right way to go. – Slava Knyazev Sep 15 '21 at 19:33
0

To remove Maybe, you need to filter non nullable items

const nonNullable = <T>(value: T): value is NonNullable<T> =>
  value !== null && value !== undefined

getOrders(ids.filter(nonNullable));

But if you want to remove the Maybe from your schema, you need to an exclamation mark ! in the graphql schema to be a required field

Harrison
  • 195
  • 1
  • 2
  • 9
0

This is a method that I use to convert the list safely.

export const RemoveMaybeAsList = <T>(items: Maybe<T>[]): T[] => items.filter((x) => !!x) as T[];

It does of course reduce performance as it requires a O(N) scan through the list.

Usage:

const ensuredValues = RemoveMaybeAsList(maybeValues)
Jack
  • 2,891
  • 11
  • 48
  • 65