UNPKG

@shencom/utils-tree

Version:
204 lines (200 loc) 7.85 kB
/** 展开对象类型 */ type Unfurl<T> = T extends Record<string, unknown> ? { [K in keyof T]: T[K] } : T; /** 递归移除 `readonly` */ type DeepMutable<T> = keyof T extends never ? T : { -readonly [P in keyof T]: DeepMutable<T[P]> }; type Dictionary<T = any> = Record<string, T>; interface TreeNodeOptions { children?: string; id?: string; pid?: string; } interface TreeToArrayOptions { children?: string; keepChildren?: boolean; } type Flatten<T> = T extends any[] ? T[number] : T; type AnyToArray<T> = T extends any[] ? T : T[]; type TreeType = Dictionary[] | Dictionary; /** * 树形数据平铺开转数组 * * @template T * @param {T} tree - 数据 * @param {TreeToArrayOptions} [options] - 配置属性 * @param {string} [options.children='children'] - 子节点映射字段 * @param {boolean} [options.keepChildren=false] - 是否保留完整子节点数据 * @example * ``` * TreeToArray(tree); * TreeToArray(tree, { children: 'child'}); * TreeToArray(tree, { children: 'child', keepChildren: true }); * ``` * @return {*} {AnyToArray<T>} */ declare function TreeToArray<T>(tree: T, options?: TreeToArrayOptions): AnyToArray<T>; /** * 查找树形数据中的某个节点 * * @template T * @param {T} tree - 数据 * @param {string} id - 节点 id * @param {Omit<TreeNodeOptions, 'pid'>} [maps] - 配置属性 * @param {string} [maps.id='id'] - 节点 id 映射字段 * @param {string} [maps.children='children'] - 子节点映射字段 * @example * ``` * TreeFindNode(tree, '1'); * TreeFindNode(tree, '1', { id: 'id1', children: 'child'}); * ``` * @return {*} {(Flatten<T> | null)} */ declare function TreeFindNode<T>(tree: T, id: string, maps?: Omit<TreeNodeOptions, 'pid'>): Flatten<T> | null; /** * 查找树形数据中的某个节点的所有父节点,返回数据中包含自身 * * @template T * @param {TreeType} tree - 数据 * @param {string} id - 节点 id * @param {TreeNodeOptions} [maps] - 配置属性 * @param {string} [maps.id='id'] - 节点 id 映射字段 * @param {string} [maps.children='children'] - 子节点映射字段 * @param {string} [maps.pid='pid'] - 父节点 id 映射字段 * @param {boolean} [keepChildren=false] - 是否保留完整子节点数据 * @example * ``` * TreeFindParentNodes(tree, '1'); * TreeFindParentNodes(tree, '1', { id: 'id', children: 'child', pid: 'pid'}); * TreeFindParentNodes(tree, '1', { id: 'id', children: 'child', pid: 'pid' }, true); * ``` * @return {*} {T[]} */ declare function TreeFindParentNodes<T>(tree: T, id: string, maps?: TreeNodeOptions, keepChildren?: boolean): AnyToArray<T>; /** * 查找树形数据中的某个节点的所有父节点id * * @param {TreeType} tree - 数据 * @param {string} id - 节点 id * @param {TreeNodeOptions} [maps] - 配置属性 * @param {string} [maps.id='id'] - 节点 id 映射字段 * @param {string} [maps.children='children'] - 子节点映射字段 * @param {string} [maps.pid='pid'] - 父节点 id 映射字段 * @example * ``` * TreeFindParentIds(tree, '1'); * TreeFindParentIds(tree, '1', { id: 'id', children: 'child', pid: 'pid'}); * ``` * @return {*} {string[]} */ declare function TreeFindParentIds(tree: TreeType, id: string, maps?: TreeNodeOptions): string[]; interface ParentByKeyProps extends TreeNodeOptions { key: string; value: number | string; } /** * 通过树形数据中的某个 key 的值,查找所有的父级节点,返回数据中包含自身 * * @template T * @param {T} tree - 数据 * @param {ParentByKeyProps} [props] - 配置属性 * @param {string} [props.key] - 要查找的 key * @param {string | number} [props.value] - 要查找的 key 的值 * @param {string} [props.id='id'] - 节点 id 映射字段 * @param {string} [props.pid='pid'] - 父节点 id 映射字段 * @param {string} [props.children='children'] - 子节点映射字段 * @param {boolean} [keepChildren='false'] - 是否保留完整子节点数据 * @example * ``` * TreeFindParentByKey(tree, { key: 'name', value: '1' }); * TreeFindParentByKey(tree, { key: 'name', value: '1', id: 'id', pid: 'pid', children: 'child' }); * TreeFindParentByKey(tree, { key: 'name', value: '1', id: 'id', pid: 'pid', children: 'child' }, true); * ``` * @return {*} {T[]} */ declare function TreeFindParentByKey<T>(tree: T, props: ParentByKeyProps, keepChildren?: boolean): AnyToArray<T>; interface TreeCallbackfn<T> { (node: T): (T & {}) | Record<string, any>; } /** * 处理树形结构每一项的数据 * * @template T * @param {T} tree - 数据 * @param {TreeCallbackfn<Flatten<T>>} handler - 处理函数 * @param {Pick<TreeNodeOptions, 'children'>} [maps] - 配置属性 * @param {string} [maps.children='children'] - 子节点映射字段 * @example * ``` * TreeMap(tree, (node) => ({ ...node, title: node.name })); * TreeMap(tree, (node) => ({ ...node, title: node.name }), { children: 'child'}); * ``` * @return {*} {AnyToArray<T>} */ declare function TreeMap<T>(tree: T, handler: TreeCallbackfn<Flatten<T>>, maps?: Pick<TreeNodeOptions, 'children'>): T; /** * 遍历树形结构每一项的数据 * * @template T * @param {T} tree - 数据 * @param {(node: T) => void} handler - 处理函数 * @param {Pick<TreeNodeOptions, 'children'>} [maps] - 配置属性 * @param {string} [maps.children='children'] - 子节点映射字段 * @example * ``` * TreeForEach(tree, (node) => { ... }); * TreeForEach(tree, (node) => { ... }, { children: 'child'}); * ``` */ declare function TreeForEach<T>(tree: T, handler: (node: T) => void, maps?: Pick<TreeNodeOptions, 'children'>): void; type Pop<T extends any[]> = T extends [...infer P, any] ? P : []; type MapToValue<MM extends Dictionary, TT extends any[], O = []> = TT['length'] extends 0 ? O : MapToValue<MM, Pop<TT>, { [K in keyof MM as MM[K]]: TT[number][K] extends any[] ? MapToValue<MM, TT[number][K], TT[number][K][0]> extends never ? never : [MapToValue<MM, TT[number][K], TT[number][K][0]>] : TT[number][K]; }>; /** * 对树形结构中每一项的进行映射 * * @template T * @param {T} tree - 数据 * @param {Record<string, string>} maps - 映射关系 * @param {string} [childKey='children'] - 子节点字段 * @example * ``` * TreeMapOption(tree, { title: 'name' }); * TreeMapOption(tree, { title: 'name' }, 'child'); * ``` * @return {*} {AnyToArray<T>} */ declare const TreeMapOption: <T extends TreeType, M extends Dictionary<(string & {}) | keyof Flatten<T>>, C extends string>(tree: T, maps: M, childKey?: C | undefined) => Unfurl<DeepMutable<MapToValue<M, AnyToArray<T>, []>>>; /** * 过滤树形结构中的每一项的数据 * * @template T * @param {T} tree - 数据 * @param {(node: T) => void} condition - 判断函数 * @param {Pick<TreeNodeOptions, 'children'>} [maps] - 配置属性 * @param {string} [maps.children='children'] - 子节点映射字段 * @example * ``` * TreeFilter(tree, (node) => node.active); * TreeFilter(tree, (node) => node.active, { children: 'child'}); * ``` * @return {*} {T} */ declare function TreeFilter<T>(tree: T, condition: (node: Flatten<T>) => boolean, maps?: Pick<TreeNodeOptions, 'children'>): T | null; /** * 将子节点列表为空数组处理成 null * * @template T * @param {T} tree - 数据 * @param {Pick<TreeNodeOptions, 'children'>} [maps] - 配置属性 * @param {string} [maps.children='children'] - 子节点映射字段 * @example * ``` * TreeFilterChildEmpty(tree); * TreeFilterChildEmpty(tree, { children: 'child'}); * ``` * @return {*} {T} */ declare function TreeFilterChildEmpty<T>(tree: T, maps?: Pick<TreeNodeOptions, 'children'>): T; export { TreeFilter, TreeFilterChildEmpty, TreeFindNode, TreeFindParentByKey, TreeFindParentIds, TreeFindParentNodes, TreeForEach, TreeMap, TreeMapOption, TreeToArray };