@appium/docutils
Version:
Documentation generation utilities for Appium and related projects
48 lines (43 loc) • 1.58 kB
text/typescript
import {util as supportUtil} from '@appium/support';
/**
* Converts a tuple to an object; use for extracting parameter types from a function signature
*/
export type TupleToObject<T extends readonly any[], M extends Record<Exclude<keyof T, keyof any[]>, PropertyKey>> = {
[K in Exclude<keyof T, keyof any[]> as M[K]]: T[K];
};
/**
* Type guard to narrow an array to a string array
* @param value any value
* @returns `true` if the array is `string[]`
*/
export const isStringArray = (value: any): value is string[] =>
Array.isArray(value) && value.every((item) => typeof item === 'string');
/**
* Performs a deep "defaults" merge into a clone of `target`.
* Only undefined properties in `target` are filled from `defaults`.
* @param target Destination object
* @param defaults Default values object
* @returns Merged clone
*/
export function mergeDefaultsDeep<T extends Record<string, any>>(target: T, defaults: T): T {
const out = structuredClone(target);
const stack: Array<{dest: Record<string, any>; src: Record<string, any>}> = [{dest: out, src: defaults}];
while (stack.length) {
const next = stack.pop();
if (!next) {
continue;
}
const {dest, src} = next;
for (const [key, srcVal] of Object.entries(src)) {
const destVal = dest[key];
if (destVal === undefined) {
dest[key] = structuredClone(srcVal);
continue;
}
if (supportUtil.isPlainObject(destVal) && supportUtil.isPlainObject(srcVal)) {
stack.push({dest: destVal, src: srcVal});
}
}
}
return out as T;
}