All files / src/utils deepMerge.ts

100% Statements 14/14
89.47% Branches 17/19
100% Functions 1/1
100% Lines 13/13

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                  7x   6x   6x   9x 1x     8x 8x 8x   8x               1x 7x 7x         6x    
/**
 * シンプルなディープマージユーティリティ。
 * 2026 Best Practice: 外部ライブラリへの依存を避け、必要な機能のみを軽量に実装。
 * プロトタイプ汚染対策済みの安全な実装。
 */
export function deepMerge<T extends object>(
  target: T,
  source: Partial<T> | undefined,
): T {
  if (!source) return target;
 
  const output = { ...target } as Record<string, unknown>;
 
  for (const key in source) {
    // 2026 Best Practice: プロトタイプ汚染(__proto__, constructor, prototype)の防止
    if (key === "__proto__" || key === "constructor" || key === "prototype") {
      continue;
    }
 
    Eif (Object.prototype.hasOwnProperty.call(source, key)) {
      const sourceValue = (source as Record<string, unknown>)[key];
      const targetValue = (target as Record<string, unknown>)[key];
 
      if (
        sourceValue &&
        typeof sourceValue === "object" &&
        !Array.isArray(sourceValue) &&
        targetValue &&
        typeof targetValue === "object" &&
        !Array.isArray(targetValue)
      ) {
        output[key] = deepMerge(targetValue as object, sourceValue as object);
      } else if (EsourceValue !== undefined) {
        output[key] = sourceValue;
      }
    }
  }
 
  return output as T;
}