Convert Maybe<string>[]' to 'string[]
Asked Answered
B

3

6

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

Banting answered 7/4, 2021 at 15:47 Comment(0)
P
6

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[]);
Philanthropist answered 7/4, 2021 at 16:4 Comment(2)
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.Counterforce
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.Philanthropist
H
1

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

Herminiahermione answered 16/11, 2022 at 15:31 Comment(0)
S
1

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)
Striker answered 28/3, 2023 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.