All files / src/components/utils mergeProps.ts

95.23% Statements 20/21
82.6% Branches 19/23
100% Functions 3/3
95% Lines 19/20

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67                                  194x   194x 346x 346x 97x   249x 2091x 2091x   2091x             82x 2009x           2009x         97x   1912x         194x       82x 2x 4x 4x          
interface Props {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    [key: string]: any;
}
 
type PropsArgs = Props | undefined | null;
 
type TupleTypes<T> = {[P in keyof T]: T[P]} extends {[key: number]: infer V}
    ? NullToObject<V>
    : never;
type NullToObject<T> = T extends null | undefined ? {} : T;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void
    ? I
    : never;
 
export function mergeProps<T extends PropsArgs[]>(...args: T): UnionToIntersection<TupleTypes<T>> {
    const result: Props = {...args[0]};
 
    for (let i = 1; i < args.length; i++) {
        const props = args[i];
        if (!props) {
            continue;
        }
        for (const key of Object.keys(props)) {
            const left = result[key];
            const right = props[key];
 
            if (
                typeof left === 'function' &&
                typeof right === 'function' &&
                key.startsWith('on') &&
                key.charCodeAt(2) >= /* A */ 65 &&
                key.charCodeAt(2) <= /* Z */ 90
            ) {
                result[key] = chain(left, right);
            I} else if (
                key === 'className' &&
                typeof left === 'string' &&
                typeof right === 'string'
            ) {
                result[key] = left + ' ' + right;
            } else if (
                key === 'controlProps' &&
                typeof left === 'object' &&
                typeof right === 'object'
            ) {
                result[key] = mergeProps(left, right);
            } else {
                result[key] = right === undefined ? left : right;
            }
        }
    }
 
    return result as UnionToIntersection<TupleTypes<T>>;
}
 
function chain(...fns: unknown[]) {
    return (...args: unknown[]) => {
        for (const fn of fns) {
            Eif (typeof fn === 'function') {
                fn(...args);
            }
        }
    };
}