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
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),
);
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)
}