It seems to me that the code for the 2nd item in items is never reached in the for loop.
How to fix this method?
class Item {
items: Item[] = [];
constructor(public id: string) {}
}
function getItembyIdRecursively(id: string, items: Item[]): Item | undefined {
for (const item of items) {
if (item.id === id) {
return item;
} else {
return getItembyIdRecursively(id, item.items);
}
}
return undefined;
}
const item1 = new Item("1");
const item2 = new Item("2");
item1.items.push(new Item("1.2"));
const items = [item1, item2];
const foundItem = getItembyIdRecursively("2", items);
console.log(foundItem.id);
You can find a repro sample here:
2
Answers
The problem is your
else
statement, you are returning the result in all cases, even if it isundefined
. Basically since the firstItem
has children, you return the result of search in its children, and since the id is not matched, you getundefined
.Which is the same as this.
generators
I think generators offer a natural way to express searching or traversal functions. We can see how the generator does not need an additional
if
check before continuing withyield*
. Another benefit is the consumer is always guaranteed a valueRun this example on typescript playground
generic find
Instead of embedding the generator within the
getItem
function, we can definefind
as a standalone function, independent of theItem
type –Now
find
is reusable anywhere we need this functionality, as ingetItem
–Run this example on typescript playground
convenience and control: $0.99
Generators give us all sorts of power and flexibility.
getItem
returns just the first result, which immediately terminates the generator and stops scanning other items. With a tiny change, we could writegetItems
that returns all results –Run this example on typescript playground