How to make type from nested part of another type?

I’m creating website that uses code generation for type safety around GraphQl queries. Some components in my app get part of object as prop. The type looks as follows:

type ActiveOrderQuery = {
    __typename?: "Query" | undefined;
    activeOrder?: {
        __typename?: "Order" | undefined;
        id: string;
        subTotalWithTax: number;
        subTotal: number;
        currencyCode: CurrencyCode;
        lines: Array<{
            __typename?: 'OrderLine';
            id: string;
            quantity: number;
            linePrice: number;
            linePriceWithTax: number;
            unitPrice: number;
            unitPriceWithTax: number;
            productVariant: {
                __typename?: 'ProductVariant';
                name: string;
                featuredAsset?: {
                    __typename?: 'Asset';
                    preview: string;
                } | null;
            discounts: Array<{
                __typename?: 'Discount';
                type: AdjustmentType;
                description: string;
                amount: number;
                amountWithTax: number;
    } | null | undefined;

My components maps over ‘lines’ property so I’d like to dynamically create or access type definition for ActiveOrderQuery["activeOrder"]["lines"].
I’ve tried mapped types but those only allow me to go one level deep so I could do
type NestedType = ActiveOrderQuery["activeOrder"]
but not
type NestedType = ActiveOrderQuery["activeOrder"]["lines"]
Is there any solution to that problem? I’d like to avoid writing those types by hand as they can change due to code generation.

>Solution :

This took longer to figure out than I would like to admit haha.

The problem is that activeOrder can be either an object, null or undefined, of course the keys of null and undefined are never so you can’t extract them.

To get the keys out, first get rid of null|undefined using the Exclude utility.

type NestedA = Exclude<ActiveOrderQuery["activeOrder"], null|undefined>;
type NestedB = NestedA["lines"];

type Nested = Exclude<ActiveOrderQuery["activeOrder"], null|undefined>["lines"];

Leave a Reply