[{"data":1,"prerenderedAt":2350},["ShallowReactive",2],{"navigation_docs":3,"-guide-type-builders":149,"-guide-type-builders-surround":2345},[4,27,81,103,144],{"title":5,"icon":6,"redirect":7,"path":8,"stem":9,"children":10,"page":26},"Introduction","i-lucide-rocket","\u002Fintroduction\u002Fabout-ts-runtypes","\u002Fintroduction","01.introduction",[11,14,18,22],{"title":12,"path":7,"stem":13},"About RunTypes","01.introduction\u002F01.about-ts-runtypes",{"title":15,"path":16,"stem":17},"Built on typescript-go","\u002Fintroduction\u002Fbuilt-on-typescript-go","01.introduction\u002F02.built-on-typescript-go",{"title":19,"path":20,"stem":21},"Quick Start","\u002Fintroduction\u002Fquick-start","01.introduction\u002F03.quick-start",{"title":23,"path":24,"stem":25},"Configuration","\u002Fintroduction\u002Fconfiguration","01.introduction\u002F04.configuration",false,{"title":28,"icon":29,"redirect":30,"path":31,"stem":32,"children":33,"page":26},"Guide","i-lucide-book-open","\u002Fguide\u002Ftype-builders","\u002Fguide","02.guide",[34,37,41,45,49,53,57,61,65,69,73,77],{"title":35,"path":30,"stem":36},"Types vs Type Builders","02.guide\u002F01.type-builders",{"title":38,"path":39,"stem":40},"Type Formats","\u002Fguide\u002Ftype-formats","02.guide\u002F02.type-formats",{"title":42,"path":43,"stem":44},"Validation","\u002Fguide\u002Fvalidation","02.guide\u002F03.validation",{"title":46,"path":47,"stem":48},"Reflection","\u002Fguide\u002Freflection","02.guide\u002F04.reflection",{"title":50,"path":51,"stem":52},"JSON Serialization","\u002Fguide\u002Fjson-serialization","02.guide\u002F05.json-serialization",{"title":54,"path":55,"stem":56},"Binary Serialization","\u002Fguide\u002Fbinary-serialization","02.guide\u002F06.binary-serialization",{"title":58,"path":59,"stem":60},"Data Mocking","\u002Fguide\u002Fmocking","02.guide\u002F07.mocking",{"title":62,"path":63,"stem":64},"Compiler Markers","\u002Fguide\u002Fcompiler-markers","02.guide\u002F08.compiler-markers",{"title":66,"path":67,"stem":68},"Pure Functions","\u002Fguide\u002Fpure-functions","02.guide\u002F09.pure-functions",{"title":70,"path":71,"stem":72},"Linting","\u002Fguide\u002Flinting","02.guide\u002F10.linting",{"title":74,"path":75,"stem":76},"Source Conversion","\u002Fguide\u002Fsource-conversion","02.guide\u002F13.source-conversion",{"title":78,"path":79,"stem":80},"Generating JSON Schema","\u002Fguide\u002Fjson-schema-generation","02.guide\u002F14.json-schema-generation",{"title":82,"icon":83,"redirect":84,"path":85,"stem":86,"children":87,"page":26},"AI Integration","i-lucide-sparkles","\u002Fai-integration\u002Fworkflow-and-commands","\u002Fai-integration","03.ai-integration",[88,91,95,99],{"title":89,"path":84,"stem":90},"AI Workflow","03.ai-integration\u002F01.workflow-and-commands",{"title":92,"path":93,"stem":94},"FriendlyText","\u002Fai-integration\u002Ffriendly-type","03.ai-integration\u002F02.friendly-type",{"title":96,"path":97,"stem":98},"MockData","\u002Fai-integration\u002Fmock-data","03.ai-integration\u002F03.mock-data",{"title":100,"path":101,"stem":102},"Translations (i18n)","\u002Fai-integration\u002Fi18n","03.ai-integration\u002F04.i18n",{"title":104,"icon":105,"redirect":106,"path":107,"stem":108,"children":109,"page":26},"Benchmarks","i-lucide-gauge","\u002Fbenchmarks\u002Fvalidation","\u002Fbenchmarks","07.benchmarks",[110,112,116,120,124,128,132,136,140],{"title":42,"path":106,"stem":111},"07.benchmarks\u002F01.validation",{"title":113,"path":114,"stem":115},"Validation Formats","\u002Fbenchmarks\u002Fvalidation-formats","07.benchmarks\u002F02.validation-formats",{"title":117,"path":118,"stem":119},"Validation Errors","\u002Fbenchmarks\u002Fgetvalidationerrors","07.benchmarks\u002F03.getvalidationerrors",{"title":121,"path":122,"stem":123},"Validation Error Formats","\u002Fbenchmarks\u002Fgetvalidationerrors-formats","07.benchmarks\u002F04.getvalidationerrors-formats",{"title":125,"path":126,"stem":127},"Serialization","\u002Fbenchmarks\u002Fserialization","07.benchmarks\u002F05.serialization",{"title":129,"path":130,"stem":131},"Serialization Formats","\u002Fbenchmarks\u002Fserialization-formats","07.benchmarks\u002F06.serialization-formats",{"title":133,"path":134,"stem":135},"Compile Time","\u002Fbenchmarks\u002Fcompiletime","07.benchmarks\u002F07.compiletime",{"title":137,"path":138,"stem":139},"Correctness","\u002Fbenchmarks\u002Fcorrectness","07.benchmarks\u002F08.correctness",{"title":141,"path":142,"stem":143},"Strict validation","\u002Fbenchmarks\u002Fstrict","07.benchmarks\u002F09.strict",{"title":145,"path":146,"stem":147,"icon":148},"Diagnostics","\u002Fdiagnostics","08.diagnostics","i-lucide-triangle-alert",{"id":150,"title":35,"body":151,"description":2339,"extension":2340,"links":2341,"meta":2342,"navigation":303,"path":30,"seo":2343,"stem":36,"__hash__":2344},"docs\u002F02.guide\u002F01.type-builders.md",{"type":152,"value":153},"minimark",[154,159,172,561,564,571,578,877,883,886,890,893,1272,1275,1279,1289,2032,2053,2056,2060,2063,2218,2228,2329,2335],[155,156,158],"h2",{"id":157},"side-by-side","Side by side",[160,161,162,163,167,168,171],"p",{},"Same shape, two spellings. ",[164,165,166],"code",{},"isProductA"," and ",[164,169,170],{},"isProductB"," are identical validators under the hood.",[173,174,177,335],"div",{"className":175},[176],"rt-define-cols",[178,179,180],"code-group",{},[181,182,188],"pre",{"className":183,"code":184,"filename":185,"language":186,"meta":187,"style":187},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Option A: a plain TypeScript type. Fastest path, nothing extra to write.\ntype Product = {\n  id: number;\n  name: string;\n  tags: string[];\n  status: 'draft' | 'live';\n};\n\nconst isProductA = createValidateFn\u003CProduct>();\n","Type Definition","ts","",[164,189,190,199,217,233,246,262,292,298,305],{"__ignoreMap":187},[191,192,195],"span",{"class":193,"line":194},"line",1,[191,196,198],{"class":197},"sHwdD","\u002F\u002F Option A: a plain TypeScript type. Fastest path, nothing extra to write.\n",[191,200,202,206,210,214],{"class":193,"line":201},2,[191,203,205],{"class":204},"spNyl","type",[191,207,209],{"class":208},"sBMFI"," Product",[191,211,213],{"class":212},"sMK4o"," =",[191,215,216],{"class":212}," {\n",[191,218,220,224,227,230],{"class":193,"line":219},3,[191,221,223],{"class":222},"swJcz","  id",[191,225,226],{"class":212},":",[191,228,229],{"class":208}," number",[191,231,232],{"class":212},";\n",[191,234,236,239,241,244],{"class":193,"line":235},4,[191,237,238],{"class":222},"  name",[191,240,226],{"class":212},[191,242,243],{"class":208}," string",[191,245,232],{"class":212},[191,247,249,252,254,256,260],{"class":193,"line":248},5,[191,250,251],{"class":222},"  tags",[191,253,226],{"class":212},[191,255,243],{"class":208},[191,257,259],{"class":258},"sTEyZ","[]",[191,261,232],{"class":212},[191,263,265,268,270,273,277,280,283,285,288,290],{"class":193,"line":264},6,[191,266,267],{"class":222},"  status",[191,269,226],{"class":212},[191,271,272],{"class":212}," '",[191,274,276],{"class":275},"sfazB","draft",[191,278,279],{"class":212},"'",[191,281,282],{"class":212}," |",[191,284,272],{"class":212},[191,286,287],{"class":275},"live",[191,289,279],{"class":212},[191,291,232],{"class":212},[191,293,295],{"class":193,"line":294},7,[191,296,297],{"class":212},"};\n",[191,299,301],{"class":193,"line":300},8,[191,302,304],{"emptyLinePlaceholder":303},true,"\n",[191,306,308,311,314,317,321,324,327,330,333],{"class":193,"line":307},9,[191,309,310],{"class":204},"const",[191,312,313],{"class":258}," isProductA ",[191,315,316],{"class":212},"=",[191,318,320],{"class":319},"s2Zo4"," createValidateFn",[191,322,323],{"class":212},"\u003C",[191,325,326],{"class":208},"Product",[191,328,329],{"class":212},">",[191,331,332],{"class":258},"()",[191,334,232],{"class":212},[178,336,337],{},[181,338,341],{"className":183,"code":339,"filename":340,"language":186,"meta":187,"style":187},"\u002F\u002F Option B: the RT.* builders, if you like the Zod \u002F TypeBox feel.\nconst productRunType = RT.object({\n  id: TF.number(),\n  name: TF.string(),\n  tags: RT.array(TF.string()),\n  status: RT.union([RT.literal('draft'), RT.literal('live')]),\n});\n\n\u002F\u002F Recover the TypeScript type, then generate from the type. Used this way\n\u002F\u002F the schema itself adds nothing to your bundle.\ntype ProductFromRunType = InferType\u003Ctypeof productRunType>;\n\nconst isProductB = createValidateFn\u003CProductFromRunType>();\n","Type Builder",[164,342,343,348,372,391,408,433,487,496,500,505,511,533,538],{"__ignoreMap":187},[191,344,345],{"class":193,"line":194},[191,346,347],{"class":197},"\u002F\u002F Option B: the RT.* builders, if you like the Zod \u002F TypeBox feel.\n",[191,349,350,352,355,357,360,363,366,369],{"class":193,"line":201},[191,351,310],{"class":204},[191,353,354],{"class":258}," productRunType ",[191,356,316],{"class":212},[191,358,359],{"class":258}," RT",[191,361,362],{"class":212},".",[191,364,365],{"class":319},"object",[191,367,368],{"class":258},"(",[191,370,371],{"class":212},"{\n",[191,373,374,376,378,381,383,386,388],{"class":193,"line":219},[191,375,223],{"class":222},[191,377,226],{"class":212},[191,379,380],{"class":258}," TF",[191,382,362],{"class":212},[191,384,385],{"class":319},"number",[191,387,332],{"class":258},[191,389,390],{"class":212},",\n",[191,392,393,395,397,399,401,404,406],{"class":193,"line":235},[191,394,238],{"class":222},[191,396,226],{"class":212},[191,398,380],{"class":258},[191,400,362],{"class":212},[191,402,403],{"class":319},"string",[191,405,332],{"class":258},[191,407,390],{"class":212},[191,409,410,412,414,416,418,421,424,426,428,431],{"class":193,"line":248},[191,411,251],{"class":222},[191,413,226],{"class":212},[191,415,359],{"class":258},[191,417,362],{"class":212},[191,419,420],{"class":319},"array",[191,422,423],{"class":258},"(TF",[191,425,362],{"class":212},[191,427,403],{"class":319},[191,429,430],{"class":258},"())",[191,432,390],{"class":212},[191,434,435,437,439,441,443,446,449,451,454,456,458,460,462,465,468,470,472,474,476,478,480,482,485],{"class":193,"line":264},[191,436,267],{"class":222},[191,438,226],{"class":212},[191,440,359],{"class":258},[191,442,362],{"class":212},[191,444,445],{"class":319},"union",[191,447,448],{"class":258},"([RT",[191,450,362],{"class":212},[191,452,453],{"class":319},"literal",[191,455,368],{"class":258},[191,457,279],{"class":212},[191,459,276],{"class":275},[191,461,279],{"class":212},[191,463,464],{"class":258},")",[191,466,467],{"class":212},",",[191,469,359],{"class":258},[191,471,362],{"class":212},[191,473,453],{"class":319},[191,475,368],{"class":258},[191,477,279],{"class":212},[191,479,287],{"class":275},[191,481,279],{"class":212},[191,483,484],{"class":258},")])",[191,486,390],{"class":212},[191,488,489,492,494],{"class":193,"line":294},[191,490,491],{"class":212},"}",[191,493,464],{"class":258},[191,495,232],{"class":212},[191,497,498],{"class":193,"line":300},[191,499,304],{"emptyLinePlaceholder":303},[191,501,502],{"class":193,"line":307},[191,503,504],{"class":197},"\u002F\u002F Recover the TypeScript type, then generate from the type. Used this way\n",[191,506,508],{"class":193,"line":507},10,[191,509,510],{"class":197},"\u002F\u002F the schema itself adds nothing to your bundle.\n",[191,512,514,516,519,521,524,527,530],{"class":193,"line":513},11,[191,515,205],{"class":204},[191,517,518],{"class":208}," ProductFromRunType",[191,520,213],{"class":212},[191,522,523],{"class":208}," InferType",[191,525,526],{"class":212},"\u003Ctypeof",[191,528,529],{"class":258}," productRunType",[191,531,532],{"class":212},">;\n",[191,534,536],{"class":193,"line":535},12,[191,537,304],{"emptyLinePlaceholder":303},[191,539,541,543,546,548,550,552,555,557,559],{"class":193,"line":540},13,[191,542,310],{"class":204},[191,544,545],{"class":258}," isProductB ",[191,547,316],{"class":212},[191,549,320],{"class":319},[191,551,323],{"class":212},[191,553,554],{"class":208},"ProductFromRunType",[191,556,329],{"class":212},[191,558,332],{"class":258},[191,560,232],{"class":212},[160,562,563],{},"The pure type is the fast path. There's nothing to write but the type you already have. A builder returns a run-type, a real value you can store in a variable, pass to a function, or build up piece by piece.",[155,565,567,568],{"id":566},"get-the-type-back-with-infertype","Get the type back with ",[164,569,570],{},"InferType",[160,572,573,574,577],{},"A run-type is a value, but sometimes you want the TypeScript type it stands for. ",[164,575,576],{},"InferType\u003Ctypeof runType>"," hands it back:",[181,579,581],{"className":183,"code":580,"language":186,"meta":187,"style":187},"import * as TF from '@ts-runtypes\u002Fcore\u002Fformats';\nimport {type InferType} from '@ts-runtypes\u002Fcore';\nimport * as RT from '@ts-runtypes\u002Fcore\u002Fbuilders';\n\n\u002F\u002F Build a run-type as a value you can pass around, store, or compose.\nconst address = RT.object({\n  street: TF.string(),\n  city: TF.string(),\n  zip: TF.string(),\n});\n\n\u002F\u002F InferType\u003Ctypeof runType> hands you the TypeScript type back.\ntype Address = InferType\u003Ctypeof address>;\n\n\u002F\u002F Now `Address` is a normal type. Use it anywhere.\nconst home: Address = {street: '1 Infinite Loop', city: 'Cupertino', zip: '95014'};\n\nexport {address, home};\nexport type {Address};\n",[164,582,583,610,635,657,661,666,685,702,719,736,744,748,753,771,776,782,840,845,862],{"__ignoreMap":187},[191,584,585,589,592,595,598,601,603,606,608],{"class":193,"line":194},[191,586,588],{"class":587},"s7zQu","import",[191,590,591],{"class":212}," *",[191,593,594],{"class":587}," as",[191,596,597],{"class":258}," TF ",[191,599,600],{"class":587},"from",[191,602,272],{"class":212},[191,604,605],{"class":275},"@ts-runtypes\u002Fcore\u002Fformats",[191,607,279],{"class":212},[191,609,232],{"class":212},[191,611,612,614,617,619,621,623,626,628,631,633],{"class":193,"line":201},[191,613,588],{"class":587},[191,615,616],{"class":212}," {",[191,618,205],{"class":587},[191,620,523],{"class":258},[191,622,491],{"class":212},[191,624,625],{"class":587}," from",[191,627,272],{"class":212},[191,629,630],{"class":275},"@ts-runtypes\u002Fcore",[191,632,279],{"class":212},[191,634,232],{"class":212},[191,636,637,639,641,643,646,648,650,653,655],{"class":193,"line":219},[191,638,588],{"class":587},[191,640,591],{"class":212},[191,642,594],{"class":587},[191,644,645],{"class":258}," RT ",[191,647,600],{"class":587},[191,649,272],{"class":212},[191,651,652],{"class":275},"@ts-runtypes\u002Fcore\u002Fbuilders",[191,654,279],{"class":212},[191,656,232],{"class":212},[191,658,659],{"class":193,"line":235},[191,660,304],{"emptyLinePlaceholder":303},[191,662,663],{"class":193,"line":248},[191,664,665],{"class":197},"\u002F\u002F Build a run-type as a value you can pass around, store, or compose.\n",[191,667,668,670,673,675,677,679,681,683],{"class":193,"line":264},[191,669,310],{"class":204},[191,671,672],{"class":258}," address ",[191,674,316],{"class":212},[191,676,359],{"class":258},[191,678,362],{"class":212},[191,680,365],{"class":319},[191,682,368],{"class":258},[191,684,371],{"class":212},[191,686,687,690,692,694,696,698,700],{"class":193,"line":294},[191,688,689],{"class":222},"  street",[191,691,226],{"class":212},[191,693,380],{"class":258},[191,695,362],{"class":212},[191,697,403],{"class":319},[191,699,332],{"class":258},[191,701,390],{"class":212},[191,703,704,707,709,711,713,715,717],{"class":193,"line":300},[191,705,706],{"class":222},"  city",[191,708,226],{"class":212},[191,710,380],{"class":258},[191,712,362],{"class":212},[191,714,403],{"class":319},[191,716,332],{"class":258},[191,718,390],{"class":212},[191,720,721,724,726,728,730,732,734],{"class":193,"line":307},[191,722,723],{"class":222},"  zip",[191,725,226],{"class":212},[191,727,380],{"class":258},[191,729,362],{"class":212},[191,731,403],{"class":319},[191,733,332],{"class":258},[191,735,390],{"class":212},[191,737,738,740,742],{"class":193,"line":507},[191,739,491],{"class":212},[191,741,464],{"class":258},[191,743,232],{"class":212},[191,745,746],{"class":193,"line":513},[191,747,304],{"emptyLinePlaceholder":303},[191,749,750],{"class":193,"line":535},[191,751,752],{"class":197},"\u002F\u002F InferType\u003Ctypeof runType> hands you the TypeScript type back.\n",[191,754,755,757,760,762,764,766,769],{"class":193,"line":540},[191,756,205],{"class":204},[191,758,759],{"class":208}," Address",[191,761,213],{"class":212},[191,763,523],{"class":208},[191,765,526],{"class":212},[191,767,768],{"class":258}," address",[191,770,532],{"class":212},[191,772,774],{"class":193,"line":773},14,[191,775,304],{"emptyLinePlaceholder":303},[191,777,779],{"class":193,"line":778},15,[191,780,781],{"class":197},"\u002F\u002F Now `Address` is a normal type. Use it anywhere.\n",[191,783,785,787,790,792,794,796,798,801,803,805,808,810,812,815,817,819,822,824,826,829,831,833,836,838],{"class":193,"line":784},16,[191,786,310],{"class":204},[191,788,789],{"class":258}," home",[191,791,226],{"class":212},[191,793,759],{"class":208},[191,795,213],{"class":212},[191,797,616],{"class":212},[191,799,800],{"class":222},"street",[191,802,226],{"class":212},[191,804,272],{"class":212},[191,806,807],{"class":275},"1 Infinite Loop",[191,809,279],{"class":212},[191,811,467],{"class":212},[191,813,814],{"class":222}," city",[191,816,226],{"class":212},[191,818,272],{"class":212},[191,820,821],{"class":275},"Cupertino",[191,823,279],{"class":212},[191,825,467],{"class":212},[191,827,828],{"class":222}," zip",[191,830,226],{"class":212},[191,832,272],{"class":212},[191,834,835],{"class":275},"95014",[191,837,279],{"class":212},[191,839,297],{"class":212},[191,841,843],{"class":193,"line":842},17,[191,844,304],{"emptyLinePlaceholder":303},[191,846,848,851,853,856,858,860],{"class":193,"line":847},18,[191,849,850],{"class":587},"export",[191,852,616],{"class":212},[191,854,855],{"class":258},"address",[191,857,467],{"class":212},[191,859,789],{"class":258},[191,861,297],{"class":212},[191,863,865,867,870,872,875],{"class":193,"line":864},19,[191,866,850],{"class":587},[191,868,869],{"class":587}," type",[191,871,616],{"class":212},[191,873,874],{"class":258},"Address",[191,876,297],{"class":212},[160,878,879,880,882],{},"So you never write a shape twice. Start from a type and reflect it, or start from a run-type and ",[164,881,570],{}," your way to the type. Either direction gives you one source of truth.",[160,884,885],{},"This pattern also keeps your bundle small. A schema you only take the type of ships no runtime description at all: the build sees that the value is never used and generates just the functions you asked for. The moment you use the schema value itself (pass it to a create function, read its properties, or export it) the build keeps its runtime description too. So when other files only need the shape, export the type rather than the schema.",[155,887,889],{"id":888},"mix-them-freely","Mix them freely",[160,891,892],{},"They're the same thing, so you can use both in the same file: a plain type here, a builder there, even nesting one kind of thinking inside the other.",[181,894,896],{"className":183,"code":895,"language":186,"meta":187,"style":187},"import * as TF from '@ts-runtypes\u002Fcore\u002Fformats';\nimport {createValidateFn} from '@ts-runtypes\u002Fcore';\nimport * as RT from '@ts-runtypes\u002Fcore\u002Fbuilders';\n\n\u002F\u002F Mix both in one file: a pure type nested inside a run-type and back again.\ntype Money = {amount: number; currency: 'USD' | 'EUR'};\n\n\u002F\u002F A run-type that references the plain type via RT.* leaves.\nconst invoice = RT.object({\n  id: TF.string(),\n  lines: RT.array(\n    RT.object({\n      sku: TF.string(),\n      total: RT.object({amount: TF.number(), currency: RT.union([RT.literal('USD'), RT.literal('EUR')])}),\n    })\n  ),\n});\n\nconst isMoney = createValidateFn\u003CMoney>();\nconst isInvoice = createValidateFn(invoice);\n\nexport {isMoney, isInvoice};\n",[164,897,898,918,939,959,963,968,1012,1016,1021,1040,1056,1072,1085,1102,1184,1192,1199,1207,1211,1233,1250,1255],{"__ignoreMap":187},[191,899,900,902,904,906,908,910,912,914,916],{"class":193,"line":194},[191,901,588],{"class":587},[191,903,591],{"class":212},[191,905,594],{"class":587},[191,907,597],{"class":258},[191,909,600],{"class":587},[191,911,272],{"class":212},[191,913,605],{"class":275},[191,915,279],{"class":212},[191,917,232],{"class":212},[191,919,920,922,924,927,929,931,933,935,937],{"class":193,"line":201},[191,921,588],{"class":587},[191,923,616],{"class":212},[191,925,926],{"class":258},"createValidateFn",[191,928,491],{"class":212},[191,930,625],{"class":587},[191,932,272],{"class":212},[191,934,630],{"class":275},[191,936,279],{"class":212},[191,938,232],{"class":212},[191,940,941,943,945,947,949,951,953,955,957],{"class":193,"line":219},[191,942,588],{"class":587},[191,944,591],{"class":212},[191,946,594],{"class":587},[191,948,645],{"class":258},[191,950,600],{"class":587},[191,952,272],{"class":212},[191,954,652],{"class":275},[191,956,279],{"class":212},[191,958,232],{"class":212},[191,960,961],{"class":193,"line":235},[191,962,304],{"emptyLinePlaceholder":303},[191,964,965],{"class":193,"line":248},[191,966,967],{"class":197},"\u002F\u002F Mix both in one file: a pure type nested inside a run-type and back again.\n",[191,969,970,972,975,977,979,982,984,986,989,992,994,996,999,1001,1003,1005,1008,1010],{"class":193,"line":264},[191,971,205],{"class":204},[191,973,974],{"class":208}," Money",[191,976,213],{"class":212},[191,978,616],{"class":212},[191,980,981],{"class":222},"amount",[191,983,226],{"class":212},[191,985,229],{"class":208},[191,987,988],{"class":212},";",[191,990,991],{"class":222}," currency",[191,993,226],{"class":212},[191,995,272],{"class":212},[191,997,998],{"class":275},"USD",[191,1000,279],{"class":212},[191,1002,282],{"class":212},[191,1004,272],{"class":212},[191,1006,1007],{"class":275},"EUR",[191,1009,279],{"class":212},[191,1011,297],{"class":212},[191,1013,1014],{"class":193,"line":294},[191,1015,304],{"emptyLinePlaceholder":303},[191,1017,1018],{"class":193,"line":300},[191,1019,1020],{"class":197},"\u002F\u002F A run-type that references the plain type via RT.* leaves.\n",[191,1022,1023,1025,1028,1030,1032,1034,1036,1038],{"class":193,"line":307},[191,1024,310],{"class":204},[191,1026,1027],{"class":258}," invoice ",[191,1029,316],{"class":212},[191,1031,359],{"class":258},[191,1033,362],{"class":212},[191,1035,365],{"class":319},[191,1037,368],{"class":258},[191,1039,371],{"class":212},[191,1041,1042,1044,1046,1048,1050,1052,1054],{"class":193,"line":507},[191,1043,223],{"class":222},[191,1045,226],{"class":212},[191,1047,380],{"class":258},[191,1049,362],{"class":212},[191,1051,403],{"class":319},[191,1053,332],{"class":258},[191,1055,390],{"class":212},[191,1057,1058,1061,1063,1065,1067,1069],{"class":193,"line":513},[191,1059,1060],{"class":222},"  lines",[191,1062,226],{"class":212},[191,1064,359],{"class":258},[191,1066,362],{"class":212},[191,1068,420],{"class":319},[191,1070,1071],{"class":258},"(\n",[191,1073,1074,1077,1079,1081,1083],{"class":193,"line":535},[191,1075,1076],{"class":258},"    RT",[191,1078,362],{"class":212},[191,1080,365],{"class":319},[191,1082,368],{"class":258},[191,1084,371],{"class":212},[191,1086,1087,1090,1092,1094,1096,1098,1100],{"class":193,"line":540},[191,1088,1089],{"class":222},"      sku",[191,1091,226],{"class":212},[191,1093,380],{"class":258},[191,1095,362],{"class":212},[191,1097,403],{"class":319},[191,1099,332],{"class":258},[191,1101,390],{"class":212},[191,1103,1104,1107,1109,1111,1113,1115,1117,1120,1122,1124,1126,1128,1130,1132,1134,1136,1138,1140,1142,1144,1146,1148,1150,1152,1154,1156,1158,1160,1162,1164,1166,1168,1170,1172,1174,1176,1178,1180,1182],{"class":193,"line":773},[191,1105,1106],{"class":222},"      total",[191,1108,226],{"class":212},[191,1110,359],{"class":258},[191,1112,362],{"class":212},[191,1114,365],{"class":319},[191,1116,368],{"class":258},[191,1118,1119],{"class":212},"{",[191,1121,981],{"class":222},[191,1123,226],{"class":212},[191,1125,380],{"class":258},[191,1127,362],{"class":212},[191,1129,385],{"class":319},[191,1131,332],{"class":258},[191,1133,467],{"class":212},[191,1135,991],{"class":222},[191,1137,226],{"class":212},[191,1139,359],{"class":258},[191,1141,362],{"class":212},[191,1143,445],{"class":319},[191,1145,448],{"class":258},[191,1147,362],{"class":212},[191,1149,453],{"class":319},[191,1151,368],{"class":258},[191,1153,279],{"class":212},[191,1155,998],{"class":275},[191,1157,279],{"class":212},[191,1159,464],{"class":258},[191,1161,467],{"class":212},[191,1163,359],{"class":258},[191,1165,362],{"class":212},[191,1167,453],{"class":319},[191,1169,368],{"class":258},[191,1171,279],{"class":212},[191,1173,1007],{"class":275},[191,1175,279],{"class":212},[191,1177,484],{"class":258},[191,1179,491],{"class":212},[191,1181,464],{"class":258},[191,1183,390],{"class":212},[191,1185,1186,1189],{"class":193,"line":778},[191,1187,1188],{"class":212},"    }",[191,1190,1191],{"class":258},")\n",[191,1193,1194,1197],{"class":193,"line":784},[191,1195,1196],{"class":258},"  )",[191,1198,390],{"class":212},[191,1200,1201,1203,1205],{"class":193,"line":842},[191,1202,491],{"class":212},[191,1204,464],{"class":258},[191,1206,232],{"class":212},[191,1208,1209],{"class":193,"line":847},[191,1210,304],{"emptyLinePlaceholder":303},[191,1212,1213,1215,1218,1220,1222,1224,1227,1229,1231],{"class":193,"line":864},[191,1214,310],{"class":204},[191,1216,1217],{"class":258}," isMoney ",[191,1219,316],{"class":212},[191,1221,320],{"class":319},[191,1223,323],{"class":212},[191,1225,1226],{"class":208},"Money",[191,1228,329],{"class":212},[191,1230,332],{"class":258},[191,1232,232],{"class":212},[191,1234,1236,1238,1241,1243,1245,1248],{"class":193,"line":1235},20,[191,1237,310],{"class":204},[191,1239,1240],{"class":258}," isInvoice ",[191,1242,316],{"class":212},[191,1244,320],{"class":319},[191,1246,1247],{"class":258},"(invoice)",[191,1249,232],{"class":212},[191,1251,1253],{"class":193,"line":1252},21,[191,1254,304],{"emptyLinePlaceholder":303},[191,1256,1258,1260,1262,1265,1267,1270],{"class":193,"line":1257},22,[191,1259,850],{"class":587},[191,1261,616],{"class":212},[191,1263,1264],{"class":258},"isMoney",[191,1266,467],{"class":212},[191,1268,1269],{"class":258}," isInvoice",[191,1271,297],{"class":212},[160,1273,1274],{},"Either way you end up at the same validator, the same JSON codec, the same mock. Pick whichever reads better to you.",[155,1276,1278],{"id":1277},"labeled-tuples-and-named-parameters","Labeled tuples and named parameters",[160,1280,1281,1282,1285,1286,226],{},"TypeScript lets a tuple name its slots (",[164,1283,1284],{},"[x: number, y: number]",") and those names are part of the type. To author them with builders, wrap each element in ",[164,1287,1288],{},"RT.slot(name, runType)",[181,1290,1292],{"className":183,"code":1291,"language":186,"meta":187,"style":187},"import * as TF from '@ts-runtypes\u002Fcore\u002Fformats';\nimport {createValidateFn, type InferType} from '@ts-runtypes\u002Fcore';\nimport * as RT from '@ts-runtypes\u002Fcore\u002Fbuilders';\n\n\u002F\u002F Wrap each element in RT.slot to name it. The result is the same type as the\n\u002F\u002F labeled tuple written by hand, so both spellings share one validator.\nconst pointRunType = RT.tuple({required: [RT.slot('x', TF.number()), RT.slot('y', TF.number())]});\ntype Point = InferType\u003Ctypeof pointRunType>; \u002F\u002F [x: number, y: number]\n\nconst isPoint = createValidateFn(pointRunType);\nconst samePoint = createValidateFn\u003C[x: number, y: number]>(); \u002F\u002F same cached validator\n\n\u002F\u002F Optional and rest elements take slots too. Each group is named, and you only\n\u002F\u002F write the groups you need. The rest slot carries its own name.\nconst rowRunType = RT.tuple({\n  required: [RT.slot('id', TF.number())],\n  optional: [RT.slot('note', TF.string())],\n  rest: RT.slot('tags', TF.string()),\n});\ntype Row = InferType\u003Ctypeof rowRunType>; \u002F\u002F [id: number, note?: string, ...tags: string[]]\n\n\u002F\u002F A tuple with a rest element but no optional elements just leaves out the\n\u002F\u002F optional group.\nconst logRunType = RT.tuple({required: [RT.slot('level', TF.string())], rest: RT.slot('lines', TF.string())});\ntype Log = InferType\u003Ctypeof logRunType>; \u002F\u002F [level: string, ...lines: string[]]\n\n\u002F\u002F RT.func names its parameters the same way, under the params group, and ret\n\u002F\u002F names the return type.\nconst handlerRunType = RT.func({params: [RT.slot('event', TF.string()), RT.slot('retries', TF.number())], ret: RT.boolean()});\ntype Handler = InferType\u003Ctypeof handlerRunType>; \u002F\u002F (event: string, retries: number) => boolean\n\nexport {isPoint, samePoint, rowRunType, logRunType, handlerRunType};\nexport type {Point, Row, Log, Handler};\n",[164,1293,1294,1314,1340,1360,1364,1369,1374,1460,1482,1486,1502,1545,1549,1554,1559,1578,1612,1646,1680,1688,1709,1713,1718,1724,1811,1833,1838,1844,1850,1950,1972,1977,2006],{"__ignoreMap":187},[191,1295,1296,1298,1300,1302,1304,1306,1308,1310,1312],{"class":193,"line":194},[191,1297,588],{"class":587},[191,1299,591],{"class":212},[191,1301,594],{"class":587},[191,1303,597],{"class":258},[191,1305,600],{"class":587},[191,1307,272],{"class":212},[191,1309,605],{"class":275},[191,1311,279],{"class":212},[191,1313,232],{"class":212},[191,1315,1316,1318,1320,1322,1324,1326,1328,1330,1332,1334,1336,1338],{"class":193,"line":201},[191,1317,588],{"class":587},[191,1319,616],{"class":212},[191,1321,926],{"class":258},[191,1323,467],{"class":212},[191,1325,869],{"class":587},[191,1327,523],{"class":258},[191,1329,491],{"class":212},[191,1331,625],{"class":587},[191,1333,272],{"class":212},[191,1335,630],{"class":275},[191,1337,279],{"class":212},[191,1339,232],{"class":212},[191,1341,1342,1344,1346,1348,1350,1352,1354,1356,1358],{"class":193,"line":219},[191,1343,588],{"class":587},[191,1345,591],{"class":212},[191,1347,594],{"class":587},[191,1349,645],{"class":258},[191,1351,600],{"class":587},[191,1353,272],{"class":212},[191,1355,652],{"class":275},[191,1357,279],{"class":212},[191,1359,232],{"class":212},[191,1361,1362],{"class":193,"line":235},[191,1363,304],{"emptyLinePlaceholder":303},[191,1365,1366],{"class":193,"line":248},[191,1367,1368],{"class":197},"\u002F\u002F Wrap each element in RT.slot to name it. The result is the same type as the\n",[191,1370,1371],{"class":193,"line":264},[191,1372,1373],{"class":197},"\u002F\u002F labeled tuple written by hand, so both spellings share one validator.\n",[191,1375,1376,1378,1381,1383,1385,1387,1390,1392,1394,1397,1399,1402,1404,1407,1409,1411,1414,1416,1418,1420,1422,1424,1426,1428,1430,1432,1434,1436,1438,1441,1443,1445,1447,1449,1451,1454,1456,1458],{"class":193,"line":294},[191,1377,310],{"class":204},[191,1379,1380],{"class":258}," pointRunType ",[191,1382,316],{"class":212},[191,1384,359],{"class":258},[191,1386,362],{"class":212},[191,1388,1389],{"class":319},"tuple",[191,1391,368],{"class":258},[191,1393,1119],{"class":212},[191,1395,1396],{"class":222},"required",[191,1398,226],{"class":212},[191,1400,1401],{"class":258}," [RT",[191,1403,362],{"class":212},[191,1405,1406],{"class":319},"slot",[191,1408,368],{"class":258},[191,1410,279],{"class":212},[191,1412,1413],{"class":275},"x",[191,1415,279],{"class":212},[191,1417,467],{"class":212},[191,1419,380],{"class":258},[191,1421,362],{"class":212},[191,1423,385],{"class":319},[191,1425,430],{"class":258},[191,1427,467],{"class":212},[191,1429,359],{"class":258},[191,1431,362],{"class":212},[191,1433,1406],{"class":319},[191,1435,368],{"class":258},[191,1437,279],{"class":212},[191,1439,1440],{"class":275},"y",[191,1442,279],{"class":212},[191,1444,467],{"class":212},[191,1446,380],{"class":258},[191,1448,362],{"class":212},[191,1450,385],{"class":319},[191,1452,1453],{"class":258},"())]",[191,1455,491],{"class":212},[191,1457,464],{"class":258},[191,1459,232],{"class":212},[191,1461,1462,1464,1467,1469,1471,1473,1476,1479],{"class":193,"line":300},[191,1463,205],{"class":204},[191,1465,1466],{"class":208}," Point",[191,1468,213],{"class":212},[191,1470,523],{"class":208},[191,1472,526],{"class":212},[191,1474,1475],{"class":258}," pointRunType",[191,1477,1478],{"class":212},">;",[191,1480,1481],{"class":197}," \u002F\u002F [x: number, y: number]\n",[191,1483,1484],{"class":193,"line":307},[191,1485,304],{"emptyLinePlaceholder":303},[191,1487,1488,1490,1493,1495,1497,1500],{"class":193,"line":507},[191,1489,310],{"class":204},[191,1491,1492],{"class":258}," isPoint ",[191,1494,316],{"class":212},[191,1496,320],{"class":319},[191,1498,1499],{"class":258},"(pointRunType)",[191,1501,232],{"class":212},[191,1503,1504,1506,1509,1511,1513,1515,1518,1520,1522,1524,1526,1529,1531,1533,1536,1538,1540,1542],{"class":193,"line":513},[191,1505,310],{"class":204},[191,1507,1508],{"class":258}," samePoint ",[191,1510,316],{"class":212},[191,1512,320],{"class":319},[191,1514,323],{"class":212},[191,1516,1517],{"class":258},"[",[191,1519,1413],{"class":208},[191,1521,226],{"class":212},[191,1523,229],{"class":208},[191,1525,467],{"class":212},[191,1527,1528],{"class":208}," y",[191,1530,226],{"class":212},[191,1532,229],{"class":208},[191,1534,1535],{"class":258},"]",[191,1537,329],{"class":212},[191,1539,332],{"class":258},[191,1541,988],{"class":212},[191,1543,1544],{"class":197}," \u002F\u002F same cached validator\n",[191,1546,1547],{"class":193,"line":535},[191,1548,304],{"emptyLinePlaceholder":303},[191,1550,1551],{"class":193,"line":540},[191,1552,1553],{"class":197},"\u002F\u002F Optional and rest elements take slots too. Each group is named, and you only\n",[191,1555,1556],{"class":193,"line":773},[191,1557,1558],{"class":197},"\u002F\u002F write the groups you need. The rest slot carries its own name.\n",[191,1560,1561,1563,1566,1568,1570,1572,1574,1576],{"class":193,"line":778},[191,1562,310],{"class":204},[191,1564,1565],{"class":258}," rowRunType ",[191,1567,316],{"class":212},[191,1569,359],{"class":258},[191,1571,362],{"class":212},[191,1573,1389],{"class":319},[191,1575,368],{"class":258},[191,1577,371],{"class":212},[191,1579,1580,1583,1585,1587,1589,1591,1593,1595,1598,1600,1602,1604,1606,1608,1610],{"class":193,"line":784},[191,1581,1582],{"class":222},"  required",[191,1584,226],{"class":212},[191,1586,1401],{"class":258},[191,1588,362],{"class":212},[191,1590,1406],{"class":319},[191,1592,368],{"class":258},[191,1594,279],{"class":212},[191,1596,1597],{"class":275},"id",[191,1599,279],{"class":212},[191,1601,467],{"class":212},[191,1603,380],{"class":258},[191,1605,362],{"class":212},[191,1607,385],{"class":319},[191,1609,1453],{"class":258},[191,1611,390],{"class":212},[191,1613,1614,1617,1619,1621,1623,1625,1627,1629,1632,1634,1636,1638,1640,1642,1644],{"class":193,"line":842},[191,1615,1616],{"class":222},"  optional",[191,1618,226],{"class":212},[191,1620,1401],{"class":258},[191,1622,362],{"class":212},[191,1624,1406],{"class":319},[191,1626,368],{"class":258},[191,1628,279],{"class":212},[191,1630,1631],{"class":275},"note",[191,1633,279],{"class":212},[191,1635,467],{"class":212},[191,1637,380],{"class":258},[191,1639,362],{"class":212},[191,1641,403],{"class":319},[191,1643,1453],{"class":258},[191,1645,390],{"class":212},[191,1647,1648,1651,1653,1655,1657,1659,1661,1663,1666,1668,1670,1672,1674,1676,1678],{"class":193,"line":847},[191,1649,1650],{"class":222},"  rest",[191,1652,226],{"class":212},[191,1654,359],{"class":258},[191,1656,362],{"class":212},[191,1658,1406],{"class":319},[191,1660,368],{"class":258},[191,1662,279],{"class":212},[191,1664,1665],{"class":275},"tags",[191,1667,279],{"class":212},[191,1669,467],{"class":212},[191,1671,380],{"class":258},[191,1673,362],{"class":212},[191,1675,403],{"class":319},[191,1677,430],{"class":258},[191,1679,390],{"class":212},[191,1681,1682,1684,1686],{"class":193,"line":864},[191,1683,491],{"class":212},[191,1685,464],{"class":258},[191,1687,232],{"class":212},[191,1689,1690,1692,1695,1697,1699,1701,1704,1706],{"class":193,"line":1235},[191,1691,205],{"class":204},[191,1693,1694],{"class":208}," Row",[191,1696,213],{"class":212},[191,1698,523],{"class":208},[191,1700,526],{"class":212},[191,1702,1703],{"class":258}," rowRunType",[191,1705,1478],{"class":212},[191,1707,1708],{"class":197}," \u002F\u002F [id: number, note?: string, ...tags: string[]]\n",[191,1710,1711],{"class":193,"line":1252},[191,1712,304],{"emptyLinePlaceholder":303},[191,1714,1715],{"class":193,"line":1257},[191,1716,1717],{"class":197},"\u002F\u002F A tuple with a rest element but no optional elements just leaves out the\n",[191,1719,1721],{"class":193,"line":1720},23,[191,1722,1723],{"class":197},"\u002F\u002F optional group.\n",[191,1725,1727,1729,1732,1734,1736,1738,1740,1742,1744,1746,1748,1750,1752,1754,1756,1758,1761,1763,1765,1767,1769,1771,1773,1775,1778,1780,1782,1784,1786,1788,1790,1793,1795,1797,1799,1801,1803,1805,1807,1809],{"class":193,"line":1726},24,[191,1728,310],{"class":204},[191,1730,1731],{"class":258}," logRunType ",[191,1733,316],{"class":212},[191,1735,359],{"class":258},[191,1737,362],{"class":212},[191,1739,1389],{"class":319},[191,1741,368],{"class":258},[191,1743,1119],{"class":212},[191,1745,1396],{"class":222},[191,1747,226],{"class":212},[191,1749,1401],{"class":258},[191,1751,362],{"class":212},[191,1753,1406],{"class":319},[191,1755,368],{"class":258},[191,1757,279],{"class":212},[191,1759,1760],{"class":275},"level",[191,1762,279],{"class":212},[191,1764,467],{"class":212},[191,1766,380],{"class":258},[191,1768,362],{"class":212},[191,1770,403],{"class":319},[191,1772,1453],{"class":258},[191,1774,467],{"class":212},[191,1776,1777],{"class":222}," rest",[191,1779,226],{"class":212},[191,1781,359],{"class":258},[191,1783,362],{"class":212},[191,1785,1406],{"class":319},[191,1787,368],{"class":258},[191,1789,279],{"class":212},[191,1791,1792],{"class":275},"lines",[191,1794,279],{"class":212},[191,1796,467],{"class":212},[191,1798,380],{"class":258},[191,1800,362],{"class":212},[191,1802,403],{"class":319},[191,1804,430],{"class":258},[191,1806,491],{"class":212},[191,1808,464],{"class":258},[191,1810,232],{"class":212},[191,1812,1814,1816,1819,1821,1823,1825,1828,1830],{"class":193,"line":1813},25,[191,1815,205],{"class":204},[191,1817,1818],{"class":208}," Log",[191,1820,213],{"class":212},[191,1822,523],{"class":208},[191,1824,526],{"class":212},[191,1826,1827],{"class":258}," logRunType",[191,1829,1478],{"class":212},[191,1831,1832],{"class":197}," \u002F\u002F [level: string, ...lines: string[]]\n",[191,1834,1836],{"class":193,"line":1835},26,[191,1837,304],{"emptyLinePlaceholder":303},[191,1839,1841],{"class":193,"line":1840},27,[191,1842,1843],{"class":197},"\u002F\u002F RT.func names its parameters the same way, under the params group, and ret\n",[191,1845,1847],{"class":193,"line":1846},28,[191,1848,1849],{"class":197},"\u002F\u002F names the return type.\n",[191,1851,1853,1855,1858,1860,1862,1864,1867,1869,1871,1874,1876,1878,1880,1882,1884,1886,1889,1891,1893,1895,1897,1899,1901,1903,1905,1907,1909,1911,1913,1916,1918,1920,1922,1924,1926,1928,1930,1933,1935,1937,1939,1942,1944,1946,1948],{"class":193,"line":1852},29,[191,1854,310],{"class":204},[191,1856,1857],{"class":258}," handlerRunType ",[191,1859,316],{"class":212},[191,1861,359],{"class":258},[191,1863,362],{"class":212},[191,1865,1866],{"class":319},"func",[191,1868,368],{"class":258},[191,1870,1119],{"class":212},[191,1872,1873],{"class":222},"params",[191,1875,226],{"class":212},[191,1877,1401],{"class":258},[191,1879,362],{"class":212},[191,1881,1406],{"class":319},[191,1883,368],{"class":258},[191,1885,279],{"class":212},[191,1887,1888],{"class":275},"event",[191,1890,279],{"class":212},[191,1892,467],{"class":212},[191,1894,380],{"class":258},[191,1896,362],{"class":212},[191,1898,403],{"class":319},[191,1900,430],{"class":258},[191,1902,467],{"class":212},[191,1904,359],{"class":258},[191,1906,362],{"class":212},[191,1908,1406],{"class":319},[191,1910,368],{"class":258},[191,1912,279],{"class":212},[191,1914,1915],{"class":275},"retries",[191,1917,279],{"class":212},[191,1919,467],{"class":212},[191,1921,380],{"class":258},[191,1923,362],{"class":212},[191,1925,385],{"class":319},[191,1927,1453],{"class":258},[191,1929,467],{"class":212},[191,1931,1932],{"class":222}," ret",[191,1934,226],{"class":212},[191,1936,359],{"class":258},[191,1938,362],{"class":212},[191,1940,1941],{"class":319},"boolean",[191,1943,332],{"class":258},[191,1945,491],{"class":212},[191,1947,464],{"class":258},[191,1949,232],{"class":212},[191,1951,1953,1955,1958,1960,1962,1964,1967,1969],{"class":193,"line":1952},30,[191,1954,205],{"class":204},[191,1956,1957],{"class":208}," Handler",[191,1959,213],{"class":212},[191,1961,523],{"class":208},[191,1963,526],{"class":212},[191,1965,1966],{"class":258}," handlerRunType",[191,1968,1478],{"class":212},[191,1970,1971],{"class":197}," \u002F\u002F (event: string, retries: number) => boolean\n",[191,1973,1975],{"class":193,"line":1974},31,[191,1976,304],{"emptyLinePlaceholder":303},[191,1978,1980,1982,1984,1987,1989,1992,1994,1996,1998,2000,2002,2004],{"class":193,"line":1979},32,[191,1981,850],{"class":587},[191,1983,616],{"class":212},[191,1985,1986],{"class":258},"isPoint",[191,1988,467],{"class":212},[191,1990,1991],{"class":258}," samePoint",[191,1993,467],{"class":212},[191,1995,1703],{"class":258},[191,1997,467],{"class":212},[191,1999,1827],{"class":258},[191,2001,467],{"class":212},[191,2003,1966],{"class":258},[191,2005,297],{"class":212},[191,2007,2009,2011,2013,2015,2018,2020,2022,2024,2026,2028,2030],{"class":193,"line":2008},33,[191,2010,850],{"class":587},[191,2012,869],{"class":587},[191,2014,616],{"class":212},[191,2016,2017],{"class":258},"Point",[191,2019,467],{"class":212},[191,2021,1694],{"class":258},[191,2023,467],{"class":212},[191,2025,1818],{"class":258},[191,2027,467],{"class":212},[191,2029,1957],{"class":258},[191,2031,297],{"class":212},[160,2033,2034,2035,2037,2038,2041,2042,2045,2046,2048,2049,2052],{},"A tuple names its three groups of elements, and you write only the groups you need: ",[164,2036,1396],{}," for the elements that always appear, ",[164,2039,2040],{},"optional"," for the trailing ones that may be left out, and ",[164,2043,2044],{},"rest"," for a single element type that repeats. A function names its ",[164,2047,1873],{}," and its ",[164,2050,2051],{},"ret",". Naming the groups is what keeps a definition unambiguous, since a bare list of elements gives no hint about which of them are optional.",[160,2054,2055],{},"A labeled tuple built this way is the same type as its hand-written twin, so validators, ids and mocks all land on the same cache entry. Plain run-types without slots keep meaning unlabeled tuples and unnamed parameters. Slots go all in or not at all (TypeScript's own rule for tuple labels), and each group is a list, so the order you write is the order the tuple keeps.",[155,2057,2059],{"id":2058},"reuse-shared-fields","Reuse shared fields",[160,2061,2062],{},"Run-types are plain values, so you can keep a set of shared fields in one place and spread it into each builder that needs them. The merge happens at build time, so every run-type still reflects its full, exact type (the same one you would get by writing every field out).",[181,2064,2066],{"className":183,"code":2065,"language":186,"meta":187,"style":187},"import {object, number, string, boolean} from '@ts-runtypes\u002Fcore';\n\nconst base = {id: number(), createdAt: number()};\n\nconst User = object({...base, name: string()});      \u002F\u002F {id, createdAt, name}\nconst Post = object({...base, published: boolean()}); \u002F\u002F {id, createdAt, published}\n",[164,2067,2068,2101,2105,2137,2141,2181],{"__ignoreMap":187},[191,2069,2070,2072,2074,2076,2078,2080,2082,2084,2086,2089,2091,2093,2095,2097,2099],{"class":193,"line":194},[191,2071,588],{"class":587},[191,2073,616],{"class":212},[191,2075,365],{"class":258},[191,2077,467],{"class":212},[191,2079,229],{"class":258},[191,2081,467],{"class":212},[191,2083,243],{"class":258},[191,2085,467],{"class":212},[191,2087,2088],{"class":258}," boolean",[191,2090,491],{"class":212},[191,2092,625],{"class":587},[191,2094,272],{"class":212},[191,2096,630],{"class":275},[191,2098,279],{"class":212},[191,2100,232],{"class":212},[191,2102,2103],{"class":193,"line":201},[191,2104,304],{"emptyLinePlaceholder":303},[191,2106,2107,2109,2112,2114,2116,2118,2120,2122,2124,2126,2129,2131,2133,2135],{"class":193,"line":219},[191,2108,310],{"class":204},[191,2110,2111],{"class":258}," base ",[191,2113,316],{"class":212},[191,2115,616],{"class":212},[191,2117,1597],{"class":222},[191,2119,226],{"class":212},[191,2121,229],{"class":319},[191,2123,332],{"class":258},[191,2125,467],{"class":212},[191,2127,2128],{"class":222}," createdAt",[191,2130,226],{"class":212},[191,2132,229],{"class":319},[191,2134,332],{"class":258},[191,2136,297],{"class":212},[191,2138,2139],{"class":193,"line":235},[191,2140,304],{"emptyLinePlaceholder":303},[191,2142,2143,2145,2148,2150,2153,2155,2158,2161,2163,2166,2168,2170,2172,2174,2176,2178],{"class":193,"line":248},[191,2144,310],{"class":204},[191,2146,2147],{"class":258}," User ",[191,2149,316],{"class":212},[191,2151,2152],{"class":319}," object",[191,2154,368],{"class":258},[191,2156,2157],{"class":212},"{...",[191,2159,2160],{"class":258},"base",[191,2162,467],{"class":212},[191,2164,2165],{"class":222}," name",[191,2167,226],{"class":212},[191,2169,243],{"class":319},[191,2171,332],{"class":258},[191,2173,491],{"class":212},[191,2175,464],{"class":258},[191,2177,988],{"class":212},[191,2179,2180],{"class":197},"      \u002F\u002F {id, createdAt, name}\n",[191,2182,2183,2185,2188,2190,2192,2194,2196,2198,2200,2203,2205,2207,2209,2211,2213,2215],{"class":193,"line":264},[191,2184,310],{"class":204},[191,2186,2187],{"class":258}," Post ",[191,2189,316],{"class":212},[191,2191,2152],{"class":319},[191,2193,368],{"class":258},[191,2195,2157],{"class":212},[191,2197,2160],{"class":258},[191,2199,467],{"class":212},[191,2201,2202],{"class":222}," published",[191,2204,226],{"class":212},[191,2206,2088],{"class":319},[191,2208,332],{"class":258},[191,2210,491],{"class":212},[191,2212,464],{"class":258},[191,2214,988],{"class":212},[191,2216,2217],{"class":197}," \u002F\u002F {id, createdAt, published}\n",[160,2219,2220,2221,2223,2224,2227],{},"The same works for shared option presets. A ",[164,2222,926],{}," or ",[164,2225,2226],{},"createJsonEncoderFn"," call can spread a preset and override individual keys inline (a key written after the spread wins).",[181,2229,2231],{"className":183,"code":2230,"language":186,"meta":187,"style":187},"import {createJsonEncoderFn} from '@ts-runtypes\u002Fcore';\n\nconst preset = {strategy: 'mutate'} as const;\n\nconst encodePost = createJsonEncoderFn\u003CPost>(undefined, {...preset});\n",[164,2232,2233,2253,2257,2289,2293],{"__ignoreMap":187},[191,2234,2235,2237,2239,2241,2243,2245,2247,2249,2251],{"class":193,"line":194},[191,2236,588],{"class":587},[191,2238,616],{"class":212},[191,2240,2226],{"class":258},[191,2242,491],{"class":212},[191,2244,625],{"class":587},[191,2246,272],{"class":212},[191,2248,630],{"class":275},[191,2250,279],{"class":212},[191,2252,232],{"class":212},[191,2254,2255],{"class":193,"line":201},[191,2256,304],{"emptyLinePlaceholder":303},[191,2258,2259,2261,2264,2266,2268,2271,2273,2275,2278,2280,2282,2284,2287],{"class":193,"line":219},[191,2260,310],{"class":204},[191,2262,2263],{"class":258}," preset ",[191,2265,316],{"class":212},[191,2267,616],{"class":212},[191,2269,2270],{"class":222},"strategy",[191,2272,226],{"class":212},[191,2274,272],{"class":212},[191,2276,2277],{"class":275},"mutate",[191,2279,279],{"class":212},[191,2281,491],{"class":212},[191,2283,594],{"class":587},[191,2285,2286],{"class":204}," const",[191,2288,232],{"class":212},[191,2290,2291],{"class":193,"line":235},[191,2292,304],{"emptyLinePlaceholder":303},[191,2294,2295,2297,2300,2302,2305,2307,2310,2312,2314,2317,2320,2323,2325,2327],{"class":193,"line":248},[191,2296,310],{"class":204},[191,2298,2299],{"class":258}," encodePost ",[191,2301,316],{"class":212},[191,2303,2304],{"class":319}," createJsonEncoderFn",[191,2306,323],{"class":212},[191,2308,2309],{"class":208},"Post",[191,2311,329],{"class":212},[191,2313,368],{"class":258},[191,2315,2316],{"class":212},"undefined,",[191,2318,2319],{"class":212}," {...",[191,2321,2322],{"class":258},"preset",[191,2324,491],{"class":212},[191,2326,464],{"class":258},[191,2328,232],{"class":212},[160,2330,2331,2332,2334],{},"The fragment you spread has to be a ",[164,2333,310],{}," (or written inline), and it can live in another module and be imported. A value produced at runtime, like the result of a function call, cannot be read at build time, so spreading one is reported as an error.",[2336,2337,2338],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}","Describe a shape as a TypeScript type or with builders; both compile to the same thing.","md",null,{"toc":26},{"title":35,"description":2339},"X2SwaSDaRspiU3r9T5UJsnKbcXC7sIOP8aLkpSfY19I",[2346,2348],{"title":23,"path":24,"stem":25,"description":2347,"children":-1},"Configure the compiler from your tsconfig, with build tools overriding per build.",{"title":38,"path":39,"stem":40,"description":2349,"children":-1},"Bake constraints like email, UUID, int32 or positive straight into your types or builders.",1787523489065]