Home > Mobile >  How can I use pick with optional types in nested typescript
How can I use pick with optional types in nested typescript

Time:05-20

I want write typescript

  dynamicContent?: {
    data?: {
      attributes?: {
        baccarat?: { title?: string | null; content?: string | null } | null;
        baccaratOnline?: { title?: string | null; content?: string | null } | null;
        casino?: { title?: string | null; content?: string | null } | null;
        casinoOnline?: { title?: string | null; content?: string | null } | null;
        games?: Array<{
          gameUrl?: string | null;
          media: {
            data?: {
              attributes?: {
                url: string;
                alternativeText?: string | null;
                width?: number | null;
                height?: number | null;
              } | null;
            } | null;
          };
        } | null> | null;
      } | null;
    } | null;
  } | null;
};

I want to use type games here is what I try

  Pick<NonNullable<GetDynamicContentQuery["dynamicContent"]["data"]["attributes"]>, 'games'>

it seems like nullable only dynamicContent field am not sure how to nullable all

CodePudding user response:

You seem to not understand the difference between optional and nullable, hence the difference between undefined and null.

In TypeScript, when you define an optional property, it effectively makes it the type of the property or undefined:

interface MyInterface {
    myField?: number;
}

Will be the effectively the same as:

interface MyInterface {
    myField: number | undefined;
}

Now, let's talk about null and undefined. In JavaScript (on top of which TypeScript is built), undefined means that something just doesn't exists. It is used when a property of an object doesn't exists:

const obj = { prop1: 'Prop 1', prop2: 'Prop 2', prop3: 123 };
console.log(obj.prop1); // 'Prop 1'
console.log(obj.prop2); // 'Prop 2'
console.log(obj.prop3); // 123
console.log(obj.prop4); // undefined

On the other hand, we have null. null is an actual value in JavaScript, just like any number, string, object or function. It is used to identify that the property / variable, holding the value itself exists, but the value is nothing.

Allowing an optional property to be null in TypeScript will cause you issues down the line, so it is recommended that you don't do that, instead, just make the properties optional.

Still, this has already been explained, and much better than I did: https://stackoverflow.com/a/57249968/10566045

CodePudding user response:

What @TopchetoEU answered is correct and you should probably define the interface GetDynamicContentQuery differently. But if you for some reason can not change the definition, here is a solution to access games anyway:

type DeeplyRemoveNullAndOptional<T> = { 
  [K in keyof T]-?: Exclude<T[K], null | undefined> extends Record<any, any> 
    ? DeeplyRemoveNullAndOptional<Exclude<T[K], null>> 
    : NonNullable<T[K]> 
}

type GamesType = DeeplyRemoveNullAndOptional<
  GetDynamicContentQuery
>["dynamicContent"]["data"]["attributes"]["games"]

I was confused why you even needed Pick. You can just access games directly.

Playground

  • Related