0
interface SubscriptionParams {
  selectedProduct?: SubscriptionSelectedProduct;
}

interface SubscriptionSelectedProduct {
  productId?: string;
  pricingId?: string;
  childProduct?: SubscriptionSelectedProduct;
}

function getChildIdRecursively(product: SubscriptionSelectedProduct, ids: string[]) {
  if (product) {
    ids.push(product.productId!);
    product.childProduct && getChildIdRecursively(product.childProduct, ids);
  }
}

function subscriptionProductsIds(subscription: SubscriptionParams): string[] {
  let ids: string[] = [subscription.selectedProduct?.productId!];
  if (subscription.selectedProduct?.childProduct) {
    getChildIdRecursively(subscription.selectedProduct?.childProduct, ids);
  }

  return ids;
}

How to make this recursion without mutation, now I am mutating ids array. I want to follow functional programming principles

Emilis
  • 140
  • 3
  • 17
  • 1
    see [this Q&A](https://stackoverflow.com/a/70051788/633183) for a pure functional approach – Mulan Nov 26 '21 at 19:22

2 Answers2

2

I think you could resolve this by leveraging tree traversals IMHO.

const collectIds = (node) => {
  const { id, children = [] } = node;
  
  // const children = [product.childProduct] in your specific case
  const ids = children.flatMap(collectIds);
  
  return [id, ...ids];
};


const product = {
  id: 'L1',
  children: [
    { id: 'L1.1' },
    { 
      id: 'L1.2', 
      children: [
        { id: 'L1.2.1', },
        { id: 'L1.2.2', },
        { id: 'L1.2.3', },
        { id: 'L1.2.4', },
        { id: 'L1.2.5', },
      ],
    },
  ],
};

console.log(
  collectIds(product),
);
Hitmands
  • 12,577
  • 3
  • 30
  • 62
1

I'd avoid creating a lot of unnecessary intermediate arrays, but to each their own. Making this "immutable" is as easy as returning a new array from the getChildIdRecursively. Also since you are basically duplicating the logic in subscriptionProductsIds you can remove that.

function getChildIdRecursively(product: SubscriptionSelectedProduct) {
  if (product) {
    let ids: string[] = [product.productId!];
    if (product.childProduct) {
      ids = ids.concat(getChildIdRecursively(product.childProduct));
    }
    return ids;
  }
  return [];
}

function subscriptionProductsIds(subscription: SubscriptionParams): string[] {
  return getChildIdRecursively(subscription.selectedProduct)
}
Felix Kling
  • 756,363
  • 169
  • 1,062
  • 1,111