mirror of
https://github.com/appium/appium.git
synced 2026-10-18 21:51:37 +08:00
48 lines
1.5 KiB
TypeScript
48 lines
1.5 KiB
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;
|
|
}
|