[{"data":1,"prerenderedAt":1563},["ShallowReactive",2],{"\u002Fresources\u002Fdeepmerge-typed":3,"navigation":1452},{"id":4,"title":5,"body":6,"description":1439,"extension":1440,"meta":1441,"navigation":1445,"path":1448,"seo":1449,"stem":1450,"__hash__":1451},"content\u002Fresources\u002Fdeepmerge-typed.md","deepmerge-typed — Type-Safe Deep Merge for TypeScript",{"type":7,"value":8,"toc":1437},"minimark",[9,54,993,1203,1378,1406,1417,1433],[10,11,14,36,42,49],"block",{":centered":12,"heading-tag":13},"true","h1",[15,16,17,21,33],"t-typography",{},[18,19,20],"p",{},"Nearly every project we ship has the same small function buried somewhere in it: take a defaults object, take whatever the caller actually passed, and hand back one settled configuration. It looks like a solved problem. In TypeScript it is not. The merge libraries we tried all returned a type that was subtly wrong, and a wrong type means the compiler quietly stops catching the mistakes you actually make.",[18,22,23,24,28,29,32],{},"So we wrote our own and published it. ",[25,26,27],"code",{},"deepMerge(defaults, overrides)"," gives you back the exact type of ",[25,30,31],{},"defaults",": every field still required, every union still narrowed the way you declared it. Overrides are checked against that type at every depth, so a key that does not exist, or a string where a number belongs, is a compile error instead of a setting that never applies.",[18,34,35],{},"No dependencies, 1.03 kB gzipped, ESM and CommonJS, MIT.",[37,38],"package-install",{"command":39,"github":40,"npm":41},"npm install deepmerge-typed","https:\u002F\u002Fgithub.com\u002FfirstwebagencyDev\u002Fdeepmerge-typed","https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fdeepmerge-typed",[43,44,46],"template",{"v-slot:title":45},"",[18,47,48],{},"Open source · MIT",[43,50,51],{"v-slot:subtitle":45},[18,52,53],{},"deepmerge-typed: a deep merge that keeps your TypeScript types exact",[10,55,56],{":centered":12},[15,57,58,63,66,425,462,468,540,551,588,593,596,681,701,705,798,808,819,822,826,829,885,977],{},[59,60,62],"h2",{"id":61},"one-example-start-to-finish","One Example, Start to Finish",[18,64,65],{},"Here's an HTTP client with five options and a caller who cares about two of them.",[67,68,72],"pre",{"className":69,"code":70,"language":71,"meta":45,"style":45},"language-ts shiki shiki-themes catppuccin-mocha","import { deepMerge } from 'deepmerge-typed';\n\ninterface ClientOptions {\n    mode: 'compact' | 'full';\n    retries: number;\n    headers: { accept: string; encoding: string };\n    hosts: string[];\n    onRetry: () => void;\n}\n\nconst defaults: ClientOptions = {\n    mode: 'compact',\n    retries: 3,\n    headers: { accept: 'application\u002Fjson', encoding: 'gzip' },\n    hosts: ['localhost'],\n    onRetry: () => undefined\n};\n\nconst options = deepMerge(defaults, {\n    mode: 'full',\n    headers: { accept: 'text\u002Fhtml' }\n});\n","ts",[25,73,74,104,111,124,156,169,201,216,236,242,247,266,279,292,321,339,353,359,364,384,396,415],{"__ignoreMap":45},[75,76,79,83,87,91,94,97,101],"span",{"class":77,"line":78},"line",1,[75,80,82],{"class":81},"sTa83","import",[75,84,86],{"class":85},"sqv1J"," {",[75,88,90],{"class":89},"sYma7"," deepMerge ",[75,92,93],{"class":85},"}",[75,95,96],{"class":81}," from",[75,98,100],{"class":99},"sX9bP"," 'deepmerge-typed'",[75,102,103],{"class":85},";\n",[75,105,107],{"class":77,"line":106},2,[75,108,110],{"emptyLinePlaceholder":109},true,"\n",[75,112,114,117,121],{"class":77,"line":113},3,[75,115,116],{"class":81},"interface",[75,118,120],{"class":119},"shU6S"," ClientOptions",[75,122,123],{"class":85}," {\n",[75,125,127,130,134,137,141,144,147,149,152,154],{"class":77,"line":126},4,[75,128,129],{"class":89},"    mode",[75,131,133],{"class":132},"sMC71",":",[75,135,136],{"class":99}," '",[75,138,140],{"class":139},"soaYw","compact",[75,142,143],{"class":99},"'",[75,145,146],{"class":132}," |",[75,148,136],{"class":99},[75,150,151],{"class":139},"full",[75,153,143],{"class":99},[75,155,103],{"class":85},[75,157,159,162,164,167],{"class":77,"line":158},5,[75,160,161],{"class":89},"    retries",[75,163,133],{"class":132},[75,165,166],{"class":81}," number",[75,168,103],{"class":85},[75,170,172,175,177,179,183,185,188,191,194,196,198],{"class":77,"line":171},6,[75,173,174],{"class":89},"    headers",[75,176,133],{"class":132},[75,178,86],{"class":85},[75,180,182],{"class":181},"scVMC"," accept",[75,184,133],{"class":132},[75,186,187],{"class":81}," string",[75,189,190],{"class":85},";",[75,192,193],{"class":181}," encoding",[75,195,133],{"class":132},[75,197,187],{"class":81},[75,199,200],{"class":85}," };\n",[75,202,204,207,209,211,214],{"class":77,"line":203},7,[75,205,206],{"class":89},"    hosts",[75,208,133],{"class":132},[75,210,187],{"class":81},[75,212,213],{"class":119},"[]",[75,215,103],{"class":85},[75,217,219,223,225,228,231,234],{"class":77,"line":218},8,[75,220,222],{"class":221},"sO0CG","    onRetry",[75,224,133],{"class":132},[75,226,227],{"class":85}," ()",[75,229,230],{"class":132}," =>",[75,232,233],{"class":81}," void",[75,235,103],{"class":85},[75,237,239],{"class":77,"line":238},9,[75,240,241],{"class":85},"}\n",[75,243,245],{"class":77,"line":244},10,[75,246,110],{"emptyLinePlaceholder":109},[75,248,250,253,256,258,261,264],{"class":77,"line":249},11,[75,251,252],{"class":81},"const",[75,254,255],{"class":89}," defaults",[75,257,133],{"class":132},[75,259,260],{"class":119}," ClientOptions ",[75,262,263],{"class":132},"=",[75,265,123],{"class":85},[75,267,269,271,273,276],{"class":77,"line":268},12,[75,270,129],{"class":89},[75,272,133],{"class":132},[75,274,275],{"class":99}," 'compact'",[75,277,278],{"class":85},",\n",[75,280,282,284,286,290],{"class":77,"line":281},13,[75,283,161],{"class":89},[75,285,133],{"class":132},[75,287,289],{"class":288},"sulG4"," 3",[75,291,278],{"class":85},[75,293,295,297,299,301,303,305,308,311,313,315,318],{"class":77,"line":294},14,[75,296,174],{"class":89},[75,298,133],{"class":132},[75,300,86],{"class":85},[75,302,182],{"class":89},[75,304,133],{"class":132},[75,306,307],{"class":99}," 'application\u002Fjson'",[75,309,310],{"class":85},",",[75,312,193],{"class":89},[75,314,133],{"class":132},[75,316,317],{"class":99}," 'gzip'",[75,319,320],{"class":85}," },\n",[75,322,324,326,328,331,334,337],{"class":77,"line":323},15,[75,325,206],{"class":89},[75,327,133],{"class":132},[75,329,330],{"class":89}," [",[75,332,333],{"class":99},"'localhost'",[75,335,336],{"class":89},"]",[75,338,278],{"class":85},[75,340,342,344,346,348,350],{"class":77,"line":341},16,[75,343,222],{"class":221},[75,345,133],{"class":132},[75,347,227],{"class":85},[75,349,230],{"class":132},[75,351,352],{"class":81}," undefined\n",[75,354,356],{"class":77,"line":355},17,[75,357,358],{"class":85},"};\n",[75,360,362],{"class":77,"line":361},18,[75,363,110],{"emptyLinePlaceholder":109},[75,365,367,369,372,374,377,380,382],{"class":77,"line":366},19,[75,368,252],{"class":81},[75,370,371],{"class":89}," options ",[75,373,263],{"class":132},[75,375,376],{"class":221}," deepMerge",[75,378,379],{"class":89},"(defaults",[75,381,310],{"class":85},[75,383,123],{"class":85},[75,385,387,389,391,394],{"class":77,"line":386},20,[75,388,129],{"class":89},[75,390,133],{"class":132},[75,392,393],{"class":99}," 'full'",[75,395,278],{"class":85},[75,397,399,401,403,405,407,409,412],{"class":77,"line":398},21,[75,400,174],{"class":89},[75,402,133],{"class":132},[75,404,86],{"class":85},[75,406,182],{"class":89},[75,408,133],{"class":132},[75,410,411],{"class":99}," 'text\u002Fhtml'",[75,413,414],{"class":85}," }\n",[75,416,418,420,423],{"class":77,"line":417},22,[75,419,93],{"class":85},[75,421,422],{"class":89},")",[75,424,103],{"class":85},[18,426,427,430,431,434,435,438,439,442,443,438,446,449,450,453,454,457,458,461],{},[25,428,429],{},"options"," is a ",[25,432,433],{},"ClientOptions",". Not a partial of one, not a union of two shapes. ",[25,436,437],{},"retries"," is still ",[25,440,441],{},"3",", ",[25,444,445],{},"headers.encoding",[25,447,448],{},"'gzip'"," even though the override only mentioned ",[25,451,452],{},"accept",", and ",[25,455,456],{},"mode"," is still the two-literal union you declared rather than a widened ",[25,459,460],{},"string",".",[18,463,464,467],{},[25,465,466],{},"deepMerge"," takes any number of overrides, not just one, and applies them left to right, so later ones win:",[67,469,471],{"className":69,"code":470,"language":71,"meta":45,"style":45},"deepMerge({ a: 1, b: 2, c: 3 }, { b: 20 }, { c: 30 });\n",[25,472,473],{"__ignoreMap":45},[75,474,475,477,480,483,486,488,491,493,496,498,501,503,506,508,510,513,515,517,519,522,524,526,528,530,533,536,538],{"class":77,"line":78},[75,476,466],{"class":221},[75,478,479],{"class":89},"(",[75,481,482],{"class":85},"{",[75,484,485],{"class":89}," a",[75,487,133],{"class":132},[75,489,490],{"class":288}," 1",[75,492,310],{"class":85},[75,494,495],{"class":89}," b",[75,497,133],{"class":132},[75,499,500],{"class":288}," 2",[75,502,310],{"class":85},[75,504,505],{"class":89}," c",[75,507,133],{"class":132},[75,509,289],{"class":288},[75,511,512],{"class":85}," },",[75,514,86],{"class":85},[75,516,495],{"class":89},[75,518,133],{"class":132},[75,520,521],{"class":288}," 20",[75,523,512],{"class":85},[75,525,86],{"class":85},[75,527,505],{"class":89},[75,529,133],{"class":132},[75,531,532],{"class":288}," 30",[75,534,535],{"class":85}," }",[75,537,422],{"class":89},[75,539,103],{"class":85},[18,541,542,543,546,547,550],{},"gives ",[25,544,545],{},"{ a: 1, b: 20, c: 30 }",". An override that is ",[25,548,549],{},"undefined"," is skipped entirely, which removes a guard you have written a hundred times:",[67,552,554],{"className":69,"code":553,"language":71,"meta":45,"style":45},"const options = deepMerge(defaults, condition ? overrides : undefined);\n",[25,555,556],{"__ignoreMap":45},[75,557,558,560,562,564,566,568,570,573,576,579,581,584,586],{"class":77,"line":78},[75,559,252],{"class":81},[75,561,371],{"class":89},[75,563,263],{"class":132},[75,565,376],{"class":221},[75,567,379],{"class":89},[75,569,310],{"class":85},[75,571,572],{"class":89}," condition ",[75,574,575],{"class":132},"?",[75,577,578],{"class":89}," overrides ",[75,580,133],{"class":132},[75,582,583],{"class":81}," undefined",[75,585,422],{"class":89},[75,587,103],{"class":85},[589,590,592],"h3",{"id":591},"wrong-overrides-do-not-compile","Wrong Overrides Do Not Compile",[18,594,595],{},"Each of these three lines is an error before you ever run it:",[67,597,599],{"className":69,"code":598,"language":71,"meta":45,"style":45},"deepMerge(defaults, { verbose: true });\ndeepMerge(defaults, { mode: 'brief' });\ndeepMerge(defaults, { headers: { accept: 7 } });\n",[25,600,601,625,649],{"__ignoreMap":45},[75,602,603,605,607,609,611,614,616,619,621,623],{"class":77,"line":78},[75,604,466],{"class":221},[75,606,379],{"class":89},[75,608,310],{"class":85},[75,610,86],{"class":85},[75,612,613],{"class":89}," verbose",[75,615,133],{"class":132},[75,617,618],{"class":288}," true",[75,620,535],{"class":85},[75,622,422],{"class":89},[75,624,103],{"class":85},[75,626,627,629,631,633,635,638,640,643,645,647],{"class":77,"line":106},[75,628,466],{"class":221},[75,630,379],{"class":89},[75,632,310],{"class":85},[75,634,86],{"class":85},[75,636,637],{"class":89}," mode",[75,639,133],{"class":132},[75,641,642],{"class":99}," 'brief'",[75,644,535],{"class":85},[75,646,422],{"class":89},[75,648,103],{"class":85},[75,650,651,653,655,657,659,662,664,666,668,670,673,675,677,679],{"class":77,"line":113},[75,652,466],{"class":221},[75,654,379],{"class":89},[75,656,310],{"class":85},[75,658,86],{"class":85},[75,660,661],{"class":89}," headers",[75,663,133],{"class":132},[75,665,86],{"class":85},[75,667,182],{"class":89},[75,669,133],{"class":132},[75,671,672],{"class":288}," 7",[75,674,535],{"class":85},[75,676,535],{"class":85},[75,678,422],{"class":89},[75,680,103],{"class":85},[18,682,683,685,686,689,690,693,694,696,697,700],{},[25,684,433],{}," has no ",[25,687,688],{},"verbose",". ",[25,691,692],{},"'brief'"," is not one of the two literals ",[25,695,456],{}," allows. And ",[25,698,699],{},"headers.accept"," is a string, two levels down. Hand any of those to a typical deep merge and it will happily build you an object carrying a setting that never applies, which is the kind of bug you find by re-reading the code rather than by running it.",[59,702,704],{"id":703},"what-gets-merged-and-what-gets-replaced","What Gets Merged and What Gets Replaced",[706,707,708,721],"table",{},[709,710,711],"thead",{},[712,713,714,718],"tr",{},[715,716,717],"th",{},"Value",[715,719,720],{},"What happens",[722,723,724,733,741,749,772,779,789],"tbody",{},[712,725,726,730],{},[727,728,729],"td",{},"Plain object on both sides",[727,731,732],{},"Merged key by key, as deep as the objects go",[712,734,735,738],{},[727,736,737],{},"Plain object on one side only",[727,739,740],{},"Replaces the other side",[712,742,743,746],{},[727,744,745],{},"Array",[727,747,748],{},"Replaces, and is copied",[712,750,751,769],{},[727,752,753,442,756,442,759,442,762,442,765,768],{},[25,754,755],{},"Date",[25,757,758],{},"RegExp",[25,760,761],{},"Map",[25,763,764],{},"Set",[25,766,767],{},"Promise",", typed array",[727,770,771],{},"Replaces, kept by reference",[712,773,774,777],{},[727,775,776],{},"Class instance, function",[727,778,771],{},[712,780,781,786],{},[727,782,783],{},[25,784,785],{},"null",[727,787,788],{},"Replaces",[712,790,791,795],{},[727,792,793],{},[25,794,549],{},[727,796,797],{},"No override at all, so the default stays",[18,799,800,801,804,805,807],{},"The last row is a default rather than a law: ",[25,802,803],{},"createDeepMerge({ skipUndefined: false })"," builds a merge where an explicit ",[25,806,549],{}," comes through as a value of its own.",[18,809,810,811,814,815,818],{},"A plain object here means an object literal, a ",[25,812,813],{},"JSON.parse"," result, or an ",[25,816,817],{},"Object.create(null)"," object, including one built in another realm such as an iframe or a worker. Everything else is treated as a value rather than a branch, and values replace instead of merging.",[18,820,821],{},"Key order follows the defaults first, then any key only the overrides had. Symbol keys are carried over and merged like string keys.",[59,823,825],{"id":824},"arrays","Arrays",[18,827,828],{},"Arrays replace by default, because for a list of hosts or a list of plugins that is what you want nine times out of ten. For the tenth time, build a merge function with different rules:",[67,830,832],{"className":69,"code":831,"language":71,"meta":45,"style":45},"import { createDeepMerge } from 'deepmerge-typed';\n\nconst mergeConfig = createDeepMerge({ arrays: 'concat' });\n",[25,833,834,851,855],{"__ignoreMap":45},[75,835,836,838,840,843,845,847,849],{"class":77,"line":78},[75,837,82],{"class":81},[75,839,86],{"class":85},[75,841,842],{"class":89}," createDeepMerge ",[75,844,93],{"class":85},[75,846,96],{"class":81},[75,848,100],{"class":99},[75,850,103],{"class":85},[75,852,853],{"class":77,"line":106},[75,854,110],{"emptyLinePlaceholder":109},[75,856,857,859,862,864,867,869,871,874,876,879,881,883],{"class":77,"line":113},[75,858,252],{"class":81},[75,860,861],{"class":89}," mergeConfig ",[75,863,263],{"class":132},[75,865,866],{"class":221}," createDeepMerge",[75,868,479],{"class":89},[75,870,482],{"class":85},[75,872,873],{"class":89}," arrays",[75,875,133],{"class":132},[75,877,878],{"class":99}," 'concat'",[75,880,535],{"class":85},[75,882,422],{"class":89},[75,884,103],{"class":85},[706,886,887,911],{},[709,888,889],{},[712,890,891,894,903],{},[715,892,893],{},"Mode",[715,895,896,899,900],{},[25,897,898],{},"[1, 2, 3]"," with ",[25,901,902],{},"[9]",[715,904,905,899,908],{},[25,906,907],{},"[1, 2]",[25,909,910],{},"[2, 3]",[722,912,913,929,946,961],{},[712,914,915,921,925],{},[727,916,917,920],{},[25,918,919],{},"'replace'"," (default)",[727,922,923],{},[25,924,902],{},[727,926,927],{},[25,928,910],{},[712,930,931,936,941],{},[727,932,933],{},[25,934,935],{},"'concat'",[727,937,938],{},[25,939,940],{},"[1, 2, 3, 9]",[727,942,943],{},[25,944,945],{},"[1, 2, 2, 3]",[712,947,948,953,957],{},[727,949,950],{},[25,951,952],{},"'unique'",[727,954,955],{},[25,956,940],{},[727,958,959],{},[25,960,898],{},[712,962,963,968,973],{},[727,964,965],{},[25,966,967],{},"'byIndex'",[727,969,970],{},[25,971,972],{},"[9, 2, 3]",[727,974,975],{},[25,976,910],{},[18,978,979,980,982,983,985,986,988,989,992],{},"You can also pass a function of your own. ",[25,981,952],{}," drops repeats by identity, the way a ",[25,984,764],{}," does, so it dedupes primitives and shared references but not two objects that merely look alike. ",[25,987,967],{}," merges the items sitting at the same index, the way ",[25,990,991],{},"lodash.merge"," does, and it is the only mode where an override item may be partial. In every other mode the item lands in the result whole, so the types ask for a whole item.",[10,994,996,1182,1198],{"bg-fill":995},"light",[15,997,1000],{"className":998},[999],"max-w-full",[706,1001,1002,1019],{},[709,1003,1004],{},[712,1005,1006,1008,1011,1014,1017],{},[715,1007],{},[715,1009,1010],{},"deepmerge-typed",[715,1012,1013],{},"deepmerge-ts",[715,1015,1016],{},"deepmerge",[715,1018,991],{},[722,1020,1021,1041,1054,1070,1083,1096,1115,1134,1148,1168],{},[712,1022,1023,1026,1029,1032,1035],{},[727,1024,1025],{},"Result typed as the defaults",[727,1027,1028],{},"Yes",[727,1030,1031],{},"No",[727,1033,1034],{},"Only if you annotate it yourself",[727,1036,1037,1038],{},"With ",[25,1039,1040],{},"@types\u002Flodash.merge",[712,1042,1043,1046,1048,1050,1052],{},[727,1044,1045],{},"Overrides checked at every depth",[727,1047,1028],{},[727,1049,1031],{},[727,1051,1031],{},[727,1053,1031],{},[712,1055,1056,1059,1062,1065,1067],{},[727,1057,1058],{},"Arrays by default",[727,1060,1061],{},"Replace",[727,1063,1064],{},"Concatenate",[727,1066,1064],{},[727,1068,1069],{},"Merge by index",[712,1071,1072,1075,1077,1079,1081],{},[727,1073,1074],{},"Result shares no subtree with the input",[727,1076,1028],{},[727,1078,1031],{},[727,1080,1028],{},[727,1082,1028],{},[712,1084,1085,1088,1090,1092,1094],{},[727,1086,1087],{},"Branches the overrides never mention are copied",[727,1089,1028],{},[727,1091,1031],{},[727,1093,1028],{},[727,1095,1028],{},[712,1097,1098,1107,1109,1111,1113],{},[727,1099,1100,1101,1104,1105],{},"Drops a ",[25,1102,1103],{},"__proto__"," key coming from ",[25,1106,813],{},[727,1108,1028],{},[727,1110,1031],{},[727,1112,1028],{},[727,1114,1028],{},[712,1116,1117,1120,1123,1125,1131],{},[727,1118,1119],{},"A cycle in the input",[727,1121,1122],{},"Points at the result",[727,1124,1122],{},[727,1126,1127,1128],{},"Throws a ",[25,1129,1130],{},"RangeError",[727,1132,1133],{},"Points at the input, not the result",[712,1135,1136,1139,1141,1143,1145],{},[727,1137,1138],{},"Mutates its arguments",[727,1140,1031],{},[727,1142,1031],{},[727,1144,1031],{},[727,1146,1147],{},"Yes, the first one",[712,1149,1150,1157,1160,1163,1166],{},[727,1151,1152,1154,1155],{},[25,1153,761],{}," and ",[25,1156,764],{},[727,1158,1159],{},"Replaced by reference",[727,1161,1162],{},"Merged",[727,1164,1165],{},"Replaced",[727,1167,1165],{},[712,1169,1170,1173,1176,1178,1180],{},[727,1171,1172],{},"Dependencies",[727,1174,1175],{},"0",[727,1177,1175],{},[727,1179,1175],{},[727,1181,1175],{},[15,1183,1184,1190],{},[18,1185,1186,1187,461],{},"Measured against deepmerge-ts 8.0.2, deepmerge 4.3.1, and lodash.merge 4.6.2. None of the four pollute ",[25,1188,1189],{},"Object.prototype",[18,1191,1192,1193,1154,1195,1197],{},"Replacing ",[25,1194,761],{},[25,1196,764],{}," rather than merging them is a decision, not an oversight. There is no one obvious answer for what merging two maps should do with a key both of them hold, and guessing silently is worse than replacing predictably. Merge them yourself, or through your own strategy, when your case has an obvious answer.",[43,1199,1200],{"v-slot:title":45},[18,1201,1202],{},"How It Compares to Other Deep Merges",[10,1204,1205],{":centered":12},[15,1206,1207,1211,1215,1237,1241,1244,1248,1251,1255,1268,1280,1289,1293,1304,1368,1371],{},[59,1208,1210],{"id":1209},"safety","Safety",[589,1212,1214],{"id":1213},"prototype-pollution-never-gets-through","Prototype Pollution Never Gets Through",[18,1216,1217,1218,1220,1221,1223,1224,1227,1228,1230,1231,1233,1234,1236],{},"A ",[25,1219,1103],{}," key is dropped from either side at any depth, so nothing you merge can reach ",[25,1222,1189],{},". Keys that merely look dangerous stay ordinary keys: merge ",[25,1225,1226],{},"{ toString: 'label' }"," and you get ",[25,1229,1226],{}," back. ",[25,1232,1103],{}," is the only key on ",[25,1235,1189],{}," carrying a setter, which is why it is the only one treated specially, and a test in the repository asserts exactly that.",[589,1238,1240],{"id":1239},"nothing-is-shared-with-the-input","Nothing Is Shared With the Input",[18,1242,1243],{},"Every plain object and array in the result is new, whichever side it came from, including branches the overrides never mentioned. Writing to the result cannot reach back into your defaults, and two results merged from the same defaults cannot disturb each other.",[589,1245,1247],{"id":1246},"cycles-come-out-as-cycles","Cycles Come Out as Cycles",[18,1249,1250],{},"A value that points at itself, or at anything already being merged, comes out pointing at the matching part of the result. Not at a stale copy, and not into a stack overflow.",[59,1252,1254],{"id":1253},"what-else-is-in-the-package","What Else Is in the Package",[18,1256,1257,1260,1261,1263,1264,1267],{},[25,1258,1259],{},"deepClone"," is the copier the merge is built on, exported on its own. It copies plain objects and arrays as deep as they go, keeps everything else by reference, preserves cycles, array holes, and array subclasses, and drops ",[25,1262,1103],{},". Unlike ",[25,1265,1266],{},"structuredClone"," it keeps functions, class instances, and maps by reference instead of throwing or duplicating them, which is the right trade-off for configuration and the wrong one for sending data to a worker.",[18,1269,1270,1273,1274,1276,1277,1279],{},[25,1271,1272],{},"isPlainObject"," is the predicate the merge uses. It says yes to object literals, ",[25,1275,813],{}," results, ",[25,1278,817],{}," objects, and literals from another realm; no to arrays, dates, maps, regular expressions, class instances, functions, and primitives.",[18,1281,1282,1285,1286,1288],{},[25,1283,1284],{},"DeepPartial\u003CT>"," is worth importing even if you never merge anything. A hand-rolled deep partial usually wanders into arrays and makes their items optional, or maps over the methods of a ",[25,1287,755],{},". This one stops at arrays, tuples, functions, classes, and built-ins.",[59,1290,1292],{"id":1291},"size-and-requirements","Size and Requirements",[18,1294,1295,1296,1299,1300,1303],{},"Each entry point stands on its own and ",[25,1297,1298],{},"sideEffects"," is ",[25,1301,1302],{},"false",", so a bundler keeps only what you import.",[706,1305,1306,1319],{},[709,1307,1308],{},[712,1309,1310,1313,1316],{},[715,1311,1312],{},"You import",[715,1314,1315],{},"Raw",[715,1317,1318],{},"Gzipped",[722,1320,1321,1333,1345,1357],{},[712,1322,1323,1327,1330],{},[727,1324,1325],{},[25,1326,466],{},[727,1328,1329],{},"3.60 kB",[727,1331,1332],{},"1.03 kB",[712,1334,1335,1339,1342],{},[727,1336,1337],{},[25,1338,1259],{},[727,1340,1341],{},"1.72 kB",[727,1343,1344],{},"0.65 kB",[712,1346,1347,1351,1354],{},[727,1348,1349],{},[25,1350,1272],{},[727,1352,1353],{},"0.30 kB",[727,1355,1356],{},"0.19 kB",[712,1358,1359,1362,1365],{},[727,1360,1361],{},"Everything",[727,1363,1364],{},"5.36 kB",[727,1366,1367],{},"1.45 kB",[18,1369,1370],{},"What ships is the build and its paperwork: eight files, no sources, no tests, no sourcemaps.",[18,1372,1373,1374,1377],{},"It runs on Node 18 or newer and in any modern browser. Every push installs the packed tarball on Node 18, 20, 22, and 24 and imports it from both ESM and CommonJS, so that range is measured rather than assumed. The types need TypeScript 5.4 or newer because they lean on ",[25,1375,1376],{},"NoInfer","; without TypeScript the package still works, it just has less to say.",[10,1379,1380],{":centered":12},[15,1381,1382,1386,1389,1397],{},[59,1383,1385],{"id":1384},"why-a-web-agency-publishes-an-npm-package","Why a Web Agency Publishes an npm Package",[18,1387,1388],{},"Most of what we write is client work, and nobody outside the project ever reads it. This one was worth breaking the habit for: the problem wasn't ours specifically, and the fix was small enough to give away.",[18,1390,1391,1392,461],{},"It's also a fair sample of how we work. Merging a configuration object is exactly the sort of unglamorous detail that decides whether a codebase is still pleasant two years later. If yours has stopped being pleasant, whether it's an inherited project, a prototype that accidentally shipped, or a build nobody wants to touch, that's ",[1393,1394,1396],"a",{"href":1395},"\u002Fsolutions\u002Fvibecoding-rescue","a good part of what we do",[18,1398,1399,1400,1405],{},"Issues and pull requests are welcome on ",[1393,1401,1404],{"href":40,"rel":1402},[1403],"nofollow","GitHub",". If you use it and something is missing, tell us.",[10,1407,1408,1412],{":centered":12},[1409,1410],"faq",{":items":1411},"[{\"label\":\"Is deepmerge-typed free to use in commercial projects?\",\"content\":\"Yes. It is published under the MIT license, so you can use it in commercial and closed-source work without asking or paying. Nothing beyond keeping the license file is required.\"},{\"label\":\"How is it different from deepmerge or lodash.merge?\",\"content\":\"Two things above all: the result keeps the exact type of the defaults you passed in rather than a widened or partial one, and every override is type-checked against those defaults at every depth. It also replaces arrays by default, never mutates its arguments, and copies every branch of the result so nothing is shared with the input.\"},{\"label\":\"Does it work in plain JavaScript?\",\"content\":\"Yes. The package ships both ESM and CommonJS builds and runs on Node 18 or newer and in any modern browser. TypeScript 5.4 or newer is only needed for the type checking, which is admittedly the main reason to choose it.\"},{\"label\":\"Is it safe against prototype pollution?\",\"content\":\"Yes. __proto__ is stripped from both sides at any depth, so nothing you merge can reach Object.prototype. Keys that merely share a name with something on the prototype, such as toString or constructor, are kept as ordinary data.\"},{\"label\":\"Can it concatenate arrays instead of replacing them?\",\"content\":\"Yes. createDeepMerge builds a merge function with different array rules: concat, unique, byIndex, or a function of your own. Replace is the default because it is the behavior that surprises people least.\"},{\"label\":\"How big is it?\",\"content\":\"Around 1 kB gzipped if you import only deepMerge, and 1.45 kB for everything the package exports. It has zero dependencies and is tree-shakeable, so your bundler keeps only the parts you actually use.\"},{\"label\":\"Where do I report a bug or request a feature?\",\"content\":\"Open an issue on the GitHub repository. We maintain the package ourselves, so it reaches the people who wrote it. Pull requests are welcome too.\"}]",[43,1413,1414],{"v-slot:title":45},[18,1415,1416],{},"Questions About deepmerge-typed",[10,1418,1420,1423,1428],{"bg-fill":1419,":contained":12},"dark",[1421,1422],"contact-form",{},[43,1424,1425],{"v-slot:title":45},[18,1426,1427],{},"Work With Us",[43,1429,1430],{"v-slot:subtitle":45},[18,1431,1432],{},"Have a TypeScript codebase that needs this kind of attention?",[1434,1435,1436],"style",{},"html pre.shiki code .sTa83, html code.shiki .sTa83{--shiki-default:#CBA6F7}html pre.shiki code .sqv1J, html code.shiki .sqv1J{--shiki-default:#9399B2}html pre.shiki code .sYma7, html code.shiki .sYma7{--shiki-default:#CDD6F4}html pre.shiki code .sX9bP, html code.shiki .sX9bP{--shiki-default:#A6E3A1}html pre.shiki code .shU6S, html code.shiki .shU6S{--shiki-default:#F9E2AF;--shiki-default-font-style:italic}html pre.shiki code .sMC71, html code.shiki .sMC71{--shiki-default:#94E2D5}html pre.shiki code .soaYw, html code.shiki .soaYw{--shiki-default:#A6E3A1;--shiki-default-font-style:italic}html pre.shiki code .scVMC, html code.shiki .scVMC{--shiki-default:#CDD6F4;--shiki-default-font-style:italic}html pre.shiki code .sO0CG, html code.shiki .sO0CG{--shiki-default:#89B4FA;--shiki-default-font-style:italic}html pre.shiki code .sulG4, html code.shiki .sulG4{--shiki-default:#FAB387}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":45,"searchDepth":106,"depth":106,"links":1438},[],"A zero-dependency deep merge for TypeScript that returns the type of your defaults and type-checks every override, at every depth. Free, MIT licensed, 1 kB gzipped.","md",{"ogImage":1442},{"props":1443},{"title":1010,"description":1444},"Type-safe deep merge for TypeScript • Zero dependencies",{"title":1010,"order":113,"icon":1446,"description":1447},"mdi:language-typescript","Our open-source type-safe deep merge for TypeScript","\u002Fresources\u002Fdeepmerge-typed",{"title":5,"description":1439},"resources\u002Fdeepmerge-typed","eOMIFbC6M5vCKEV5K5tW_XzM6PCJ6-QAK_PhQQ34ED0",[1453,1457,1510,1531,1559],{"title":1454,"path":1455,"stem":1456,"to":1455},"About Us","\u002Fabout","about",{"title":1458,"path":1459,"stem":1460,"children":1461,"type":1509,"to":1459},"Resources","\u002Fresources","resources",[1462,1463,1469,1475,1498,1504],{"title":1010,"path":1448,"stem":1450,"order":113,"icon":1446,"description":1447,"to":1448},{"title":1464,"path":1465,"stem":1466,"order":158,"icon":1467,"description":1468,"to":1465},"DIY vs Agency","\u002Fresources\u002Fdiy-vs-agency","resources\u002Fdiy-vs-agency","heroicons:scale","When a website builder is enough — and when it isn’t",{"title":1470,"path":1471,"stem":1472,"order":78,"icon":1473,"description":1474,"to":1471},"Favicon Generator","\u002Fresources\u002Ffavicon","resources\u002Ffavicon","heroicons:photo","Free online favicon generator for all sizes and formats",{"title":1476,"path":1477,"stem":1478,"children":1479,"order":106,"icon":1496,"description":1497,"to":1477},"Tailwind Templates","\u002Fresources\u002Ftailwind","resources\u002Ftailwind",[1480,1484,1488,1492],{"title":1481,"path":1482,"stem":1483,"to":1482},"Feature Cards Grid","\u002Fresources\u002Ftailwind\u002Fcards","resources\u002Ftailwind\u002Fcards",{"title":1485,"path":1486,"stem":1487,"to":1486},"Contact Form","\u002Fresources\u002Ftailwind\u002Fform","resources\u002Ftailwind\u002Fform",{"title":1489,"path":1490,"stem":1491,"to":1490},"Hero Sections","\u002Fresources\u002Ftailwind\u002Fhero","resources\u002Ftailwind\u002Fhero",{"title":1493,"path":1494,"stem":1495,"to":1494},"Responsive Navbar","\u002Fresources\u002Ftailwind\u002Fnavbar","resources\u002Ftailwind\u002Fnavbar","teenyicons:tailwind-solid","Free Tailwind CSS components and templates",{"title":1499,"path":1500,"stem":1501,"order":126,"icon":1502,"description":1503,"to":1500},"Website Cost Guide","\u002Fresources\u002Fwebsite-cost","resources\u002Fwebsite-cost","heroicons:currency-dollar","What a small business website really costs in 2026",{"title":1505,"path":1506,"stem":1507,"order":171,"icon":1473,"description":1508,"to":1506},"WYSIWYG Editor","\u002Fresources\u002Fwysiwyg","resources\u002Fwysiwyg","Powerful visual editor coming soon","megamenu",{"title":1511,"path":1512,"stem":1513,"children":1514,"order":78,"to":1512},"Showcases","\u002Fshowcases","showcases",[1515,1519,1523,1527],{"title":1516,"path":1517,"stem":1518,"to":1517},"OCAutoAid","\u002Fshowcases\u002Focautoaid","showcases\u002F1.ocautoaid",{"title":1520,"path":1521,"stem":1522,"to":1521},"Aladdin","\u002Fshowcases\u002Faladdin","showcases\u002F2.aladdin",{"title":1524,"path":1525,"stem":1526,"to":1525},"P&J Cleaners","\u002Fshowcases\u002Fpj-cleaners","showcases\u002F3.pj-cleaners",{"title":1528,"path":1529,"stem":1530,"to":1529},"Laelia Wellness","\u002Fshowcases\u002Flaelia","showcases\u002F4.laelia",{"title":1532,"path":1533,"stem":1534,"children":1535,"order":78,"type":1509,"to":1533},"Solutions","\u002Fsolutions","solutions",[1536,1542,1548,1553],{"title":1537,"path":1538,"stem":1539,"icon":1540,"description":1541,"to":1538},"Automotive Websites","\u002Fsolutions\u002Fautomotive","solutions\u002Fautomotive","material-symbols:car-repair-sharp","Professional websites for automotive businesses that drive results",{"title":1543,"path":1544,"stem":1545,"icon":1546,"description":1547,"to":1544},"Shopify Store Development","\u002Fsolutions\u002Fshopify-store","solutions\u002Fshopify-store","mdi:shopify","Professional Shopify store setup and custom development",{"title":1549,"path":1395,"stem":1550,"icon":1551,"description":1552,"to":1395},"Vibecoding Project Recovery","solutions\u002Fvibecoding-rescue","icon-park-solid:tools","Professional rescue and refinement of AI-generated code projects",{"title":1554,"path":1555,"stem":1556,"icon":1557,"description":1558,"to":1555},"WebFlow Templates","\u002Fsolutions\u002Fwebflow","solutions\u002Fwebflow","icon-park-solid:page-template","Professional Webflow development and custom template solutions",{"title":1560,"path":1561,"stem":1562,"order":106,"to":1561},"Contact","\u002Fcontact-us","contact-us",1787779229120]