export const isString = (value: unknown): value is string => typeof value === 'string'; export const isPlainObject = (value: unknown): value is object => typeof value === 'object' && value !== null && !Array.isArray(value); export function flattenTree( root: T, children: (node: T) => Iterable, predicate: (node: T) => boolean = (): boolean => true ): Set { const results = new Set(); const visited = new Set(); const toProcess = [root]; while (toProcess.length) { const node = toProcess.shift()!; if (visited.has(node)) { continue; } visited.add(node); if (predicate(node)) { results.add(node); } toProcess.push(...children(node)); } return results; } export function* concatIterables(...iterables: Iterable[]): Iterable { for (const iterable of iterables) { for (const item of iterable) { yield item; } } }