[{"data":1,"prerenderedAt":1379},["ShallowReactive",2],{"navigation_docs":3,"-guide-pure-functions":127,"-guide-pure-functions-surround":1374},[4,19,53,71,95],{"title":5,"icon":6,"redirect":7,"path":8,"stem":9,"children":10,"page":18},"Introduction","i-lucide-rocket","\u002Fintroduction\u002Fabout-ts-runtypes","\u002Fintroduction","1.introduction",[11,14],{"title":12,"path":7,"stem":13},"About RunTypes","1.introduction\u002F1.about-ts-runtypes",{"title":15,"path":16,"stem":17},"Quick Start","\u002Fintroduction\u002Fquick-start","1.introduction\u002F2.quick-start",false,{"title":20,"icon":21,"redirect":22,"path":23,"stem":24,"children":25,"page":18},"Guide","i-lucide-book-open","\u002Fguide\u002Ftypes-vs-schemas","\u002Fguide","2.guide",[26,29,33,37,41,45,49],{"title":27,"path":22,"stem":28},"Types vs Schemas","2.guide\u002F1.types-vs-schemas",{"title":30,"path":31,"stem":32},"Type Formats","\u002Fguide\u002Ftype-formats","2.guide\u002F2.type-formats",{"title":34,"path":35,"stem":36},"Serialization","\u002Fguide\u002Fserialization","2.guide\u002F3.serialization",{"title":38,"path":39,"stem":40},"Mock Data","\u002Fguide\u002Fmocking","2.guide\u002F4.mocking",{"title":42,"path":43,"stem":44},"Validation","\u002Fguide\u002Fvalidation","2.guide\u002F5.validation",{"title":46,"path":47,"stem":48},"Reflection","\u002Fguide\u002Fmarkers-and-reflection","2.guide\u002F6.markers-and-reflection",{"title":50,"path":51,"stem":52},"Pure Functions","\u002Fguide\u002Fpure-functions","2.guide\u002F7.pure-functions",{"title":54,"icon":55,"redirect":56,"path":57,"stem":58,"children":59,"page":18},"AI Integration","i-lucide-sparkles","\u002Fai-integration\u002Fworkflow-and-commands","\u002Fai-integration","3.ai-integration",[60,63,67],{"title":61,"path":56,"stem":62},"AI Workflow","3.ai-integration\u002F1.workflow-and-commands",{"title":64,"path":65,"stem":66},"FriendlyType","\u002Fai-integration\u002Ffriendly-type","3.ai-integration\u002F2.friendly-type",{"title":68,"path":69,"stem":70},"MockData","\u002Fai-integration\u002Fmock-data","3.ai-integration\u002F3.mock-data",{"title":72,"icon":73,"redirect":74,"path":75,"stem":76,"children":77,"page":18},"Test Suites","i-lucide-terminal","\u002Fsuites\u002Fvalidation","\u002Fsuites","6.suites",[78,80,83,87,91],{"title":42,"path":74,"stem":79},"6.suites\u002F1.validation",{"title":34,"path":81,"stem":82},"\u002Fsuites\u002Fserialization","6.suites\u002F2.serialization",{"title":84,"path":85,"stem":86},"Formats Validation","\u002Fsuites\u002Fformat-validation","6.suites\u002F3.format-validation",{"title":88,"path":89,"stem":90},"Formats Serialization","\u002Fsuites\u002Fformat-serialization","6.suites\u002F4.format-serialization",{"title":92,"path":93,"stem":94},"Fuzzing","\u002Fsuites\u002Ffuzzing","6.suites\u002F5.fuzzing",{"title":96,"icon":97,"redirect":98,"path":99,"stem":100,"children":101,"page":18},"Benchmarks","i-lucide-gauge","\u002Fbenchmarks\u002Fvalidation","\u002Fbenchmarks","7.benchmarks",[102,104,108,112,116,119,123],{"title":42,"path":98,"stem":103},"7.benchmarks\u002F1.validation",{"title":105,"path":106,"stem":107},"Validation Formats","\u002Fbenchmarks\u002Fvalidation-formats","7.benchmarks\u002F2.validation-formats",{"title":109,"path":110,"stem":111},"Validation Errors","\u002Fbenchmarks\u002Fgetvalidationerrors","7.benchmarks\u002F3.getvalidationerrors",{"title":113,"path":114,"stem":115},"Validation Error Formats","\u002Fbenchmarks\u002Fgetvalidationerrors-formats","7.benchmarks\u002F4.getvalidationerrors-formats",{"title":34,"path":117,"stem":118},"\u002Fbenchmarks\u002Fserialization","7.benchmarks\u002F5.serialization",{"title":120,"path":121,"stem":122},"Serialization Formats","\u002Fbenchmarks\u002Fserialization-formats","7.benchmarks\u002F6.serialization-formats",{"title":124,"path":125,"stem":126},"Compile Time","\u002Fbenchmarks\u002Fcompiletime","7.benchmarks\u002F7.compiletime",{"id":128,"title":50,"body":129,"description":1368,"extension":1369,"links":1370,"meta":1371,"navigation":243,"path":51,"seo":1372,"stem":52,"__hash__":1373},"docs\u002F2.guide\u002F7.pure-functions.md",{"type":130,"value":131},"minimark",[132,144,149,158,616,632,636,647,815,828,831,842,1064,1089,1093,1104,1223,1236,1239,1250,1364],[133,134,135,139,140,143],"tip",{},[136,137,138],"strong",{},"Pure functions"," are small, self-contained helpers that inline straight into the generated code, and the compiler ",[136,141,142],{},"validates that they're genuinely pure for you."," A helper that reaches outside itself fails the build with a diagnostic, so an unsafe one never ships. (The exact rules are spelled out below.)",[145,146,148],"h2",{"id":147},"registerformatpattern","registerFormatPattern",[150,151,152,153,157],"p",{},"Got a string shape you reuse, like a slug, a SKU, or an internal id? Register the regex once and reference it from any number of ",[154,155,156],"code",{},"TF.String"," types.",[159,160,165],"pre",{"className":161,"code":162,"language":163,"meta":164,"style":164},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import type * as TF from 'ts-runtypes\u002Fformats';\nimport {createValidate, registerFormatPattern} from 'ts-runtypes';\n\n\u002F\u002F Register a reusable string pattern once. `mockSamples` are required —\n\u002F\u002F they double as canonical values the mock generator draws from, and each\n\u002F\u002F is checked against the regex at registration (a bad sample throws loudly).\nconst slug = registerFormatPattern({\n  source: '^[a-z0-9]+(?:-[a-z0-9]+)*$',\n  mockSamples: ['my-post', 'hello-world-2'],\n  message: 'must be a kebab-case slug',\n});\n\n\u002F\u002F Reference it by `typeof` in a TF.String. Build-time validation + mocks\n\u002F\u002F both pick it up.\ntype Slug = TF.String\u003C{pattern: typeof slug}>;\n\ntype Post = {slug: Slug; title: string};\n\nconst isPost = createValidate\u003CPost>();\nisPost({slug: 'my-first-post', title: 'Hi'}); \u002F\u002F true\nisPost({slug: 'Not A Slug!', title: 'Hi'}); \u002F\u002F false\n\nexport {slug, isPost};\nexport type {Slug, Post};\n","ts","",[154,166,167,206,238,245,252,258,264,286,306,338,355,365,370,376,382,421,426,459,464,491,535,576,581,598],{"__ignoreMap":164},[168,169,172,176,179,183,186,190,193,196,200,203],"span",{"class":170,"line":171},"line",1,[168,173,175],{"class":174},"s7zQu","import",[168,177,178],{"class":174}," type",[168,180,182],{"class":181},"sMK4o"," *",[168,184,185],{"class":174}," as",[168,187,189],{"class":188},"sTEyZ"," TF ",[168,191,192],{"class":174},"from",[168,194,195],{"class":181}," '",[168,197,199],{"class":198},"sfazB","ts-runtypes\u002Fformats",[168,201,202],{"class":181},"'",[168,204,205],{"class":181},";\n",[168,207,209,211,214,217,220,223,226,229,231,234,236],{"class":170,"line":208},2,[168,210,175],{"class":174},[168,212,213],{"class":181}," {",[168,215,216],{"class":188},"createValidate",[168,218,219],{"class":181},",",[168,221,222],{"class":188}," registerFormatPattern",[168,224,225],{"class":181},"}",[168,227,228],{"class":174}," from",[168,230,195],{"class":181},[168,232,233],{"class":198},"ts-runtypes",[168,235,202],{"class":181},[168,237,205],{"class":181},[168,239,241],{"class":170,"line":240},3,[168,242,244],{"emptyLinePlaceholder":243},true,"\n",[168,246,248],{"class":170,"line":247},4,[168,249,251],{"class":250},"sHwdD","\u002F\u002F Register a reusable string pattern once. `mockSamples` are required —\n",[168,253,255],{"class":170,"line":254},5,[168,256,257],{"class":250},"\u002F\u002F they double as canonical values the mock generator draws from, and each\n",[168,259,261],{"class":170,"line":260},6,[168,262,263],{"class":250},"\u002F\u002F is checked against the regex at registration (a bad sample throws loudly).\n",[168,265,267,271,274,277,280,283],{"class":170,"line":266},7,[168,268,270],{"class":269},"spNyl","const",[168,272,273],{"class":188}," slug ",[168,275,276],{"class":181},"=",[168,278,222],{"class":279},"s2Zo4",[168,281,282],{"class":188},"(",[168,284,285],{"class":181},"{\n",[168,287,289,293,296,298,301,303],{"class":170,"line":288},8,[168,290,292],{"class":291},"swJcz","  source",[168,294,295],{"class":181},":",[168,297,195],{"class":181},[168,299,300],{"class":198},"^[a-z0-9]+(?:-[a-z0-9]+)*$",[168,302,202],{"class":181},[168,304,305],{"class":181},",\n",[168,307,309,312,314,317,319,322,324,326,328,331,333,336],{"class":170,"line":308},9,[168,310,311],{"class":291},"  mockSamples",[168,313,295],{"class":181},[168,315,316],{"class":188}," [",[168,318,202],{"class":181},[168,320,321],{"class":198},"my-post",[168,323,202],{"class":181},[168,325,219],{"class":181},[168,327,195],{"class":181},[168,329,330],{"class":198},"hello-world-2",[168,332,202],{"class":181},[168,334,335],{"class":188},"]",[168,337,305],{"class":181},[168,339,341,344,346,348,351,353],{"class":170,"line":340},10,[168,342,343],{"class":291},"  message",[168,345,295],{"class":181},[168,347,195],{"class":181},[168,349,350],{"class":198},"must be a kebab-case slug",[168,352,202],{"class":181},[168,354,305],{"class":181},[168,356,358,360,363],{"class":170,"line":357},11,[168,359,225],{"class":181},[168,361,362],{"class":188},")",[168,364,205],{"class":181},[168,366,368],{"class":170,"line":367},12,[168,369,244],{"emptyLinePlaceholder":243},[168,371,373],{"class":170,"line":372},13,[168,374,375],{"class":250},"\u002F\u002F Reference it by `typeof` in a TF.String. Build-time validation + mocks\n",[168,377,379],{"class":170,"line":378},14,[168,380,381],{"class":250},"\u002F\u002F both pick it up.\n",[168,383,385,388,392,395,398,401,404,407,410,412,415,418],{"class":170,"line":384},15,[168,386,387],{"class":269},"type",[168,389,391],{"class":390},"sBMFI"," Slug",[168,393,394],{"class":181}," =",[168,396,397],{"class":390}," TF",[168,399,400],{"class":181},".",[168,402,403],{"class":390},"String",[168,405,406],{"class":181},"\u003C{",[168,408,409],{"class":291},"pattern",[168,411,295],{"class":181},[168,413,414],{"class":181}," typeof",[168,416,417],{"class":188}," slug",[168,419,420],{"class":181},"}>;\n",[168,422,424],{"class":170,"line":423},16,[168,425,244],{"emptyLinePlaceholder":243},[168,427,429,431,434,436,438,441,443,445,448,451,453,456],{"class":170,"line":428},17,[168,430,387],{"class":269},[168,432,433],{"class":390}," Post",[168,435,394],{"class":181},[168,437,213],{"class":181},[168,439,440],{"class":291},"slug",[168,442,295],{"class":181},[168,444,391],{"class":390},[168,446,447],{"class":181},";",[168,449,450],{"class":291}," title",[168,452,295],{"class":181},[168,454,455],{"class":390}," string",[168,457,458],{"class":181},"};\n",[168,460,462],{"class":170,"line":461},18,[168,463,244],{"emptyLinePlaceholder":243},[168,465,467,469,472,474,477,480,483,486,489],{"class":170,"line":466},19,[168,468,270],{"class":269},[168,470,471],{"class":188}," isPost ",[168,473,276],{"class":181},[168,475,476],{"class":279}," createValidate",[168,478,479],{"class":181},"\u003C",[168,481,482],{"class":390},"Post",[168,484,485],{"class":181},">",[168,487,488],{"class":188},"()",[168,490,205],{"class":181},[168,492,494,497,499,502,504,506,508,511,513,515,517,519,521,524,526,528,530,532],{"class":170,"line":493},20,[168,495,496],{"class":279},"isPost",[168,498,282],{"class":188},[168,500,501],{"class":181},"{",[168,503,440],{"class":291},[168,505,295],{"class":181},[168,507,195],{"class":181},[168,509,510],{"class":198},"my-first-post",[168,512,202],{"class":181},[168,514,219],{"class":181},[168,516,450],{"class":291},[168,518,295],{"class":181},[168,520,195],{"class":181},[168,522,523],{"class":198},"Hi",[168,525,202],{"class":181},[168,527,225],{"class":181},[168,529,362],{"class":188},[168,531,447],{"class":181},[168,533,534],{"class":250}," \u002F\u002F true\n",[168,536,538,540,542,544,546,548,550,553,555,557,559,561,563,565,567,569,571,573],{"class":170,"line":537},21,[168,539,496],{"class":279},[168,541,282],{"class":188},[168,543,501],{"class":181},[168,545,440],{"class":291},[168,547,295],{"class":181},[168,549,195],{"class":181},[168,551,552],{"class":198},"Not A Slug!",[168,554,202],{"class":181},[168,556,219],{"class":181},[168,558,450],{"class":291},[168,560,295],{"class":181},[168,562,195],{"class":181},[168,564,523],{"class":198},[168,566,202],{"class":181},[168,568,225],{"class":181},[168,570,362],{"class":188},[168,572,447],{"class":181},[168,574,575],{"class":250}," \u002F\u002F false\n",[168,577,579],{"class":170,"line":578},22,[168,580,244],{"emptyLinePlaceholder":243},[168,582,584,587,589,591,593,596],{"class":170,"line":583},23,[168,585,586],{"class":174},"export",[168,588,213],{"class":181},[168,590,440],{"class":188},[168,592,219],{"class":181},[168,594,595],{"class":188}," isPost",[168,597,458],{"class":181},[168,599,601,603,605,607,610,612,614],{"class":170,"line":600},24,[168,602,586],{"class":174},[168,604,178],{"class":174},[168,606,213],{"class":181},[168,608,609],{"class":188},"Slug",[168,611,219],{"class":181},[168,613,433],{"class":188},[168,615,458],{"class":181},[150,617,618,621,622,626,627,631],{},[154,619,620],{},"mockSamples"," are required and do double duty: the ",[623,624,625],"a",{"href":39},"mock generator"," draws from them, and each one is checked against the regex ",[628,629,630],"em",{},"at registration",". A sample that doesn't match throws immediately, so a broken pattern fails loud and early.",[145,633,635],{"id":634},"registermockingfunction","registerMockingFunction",[150,637,638,639,642,643,646],{},"By default the mock generator invents something valid for each kind. Want mocked values to read a particular way? Register a mock fn for a ",[154,640,641],{},"RunTypeKind",": return a value to override, or ",[154,644,645],{},"undefined"," to fall back to the default.",[159,648,650],{"className":161,"code":649,"language":163,"meta":164,"style":164},"import {registerMockingFunction, RunTypeKind, type FormatAnnotation} from 'ts-runtypes';\n\n\u002F\u002F Want mock data to look a certain way for a kind? Register a mock fn for\n\u002F\u002F that ReflectionKind. Return `undefined` to fall back to the default mock.\n\u002F\u002F Here: make every mocked string format spit out a friendlier value.\nregisterMockingFunction(RunTypeKind.string, (annotation: FormatAnnotation) => {\n  if (annotation.name === 'email') return 'someone@example.com';\n  return undefined; \u002F\u002F defer to the built-in mock for everything else\n});\n\n\u002F\u002F From now on createMockType\u003CT>() uses this when it mocks a string format.\n\u002F\u002F (createMockType itself is covered in the Mocking guide.)\nexport {};\n",[154,651,652,684,688,693,698,703,736,775,786,794,798,803,808],{"__ignoreMap":164},[168,653,654,656,658,660,662,665,667,669,672,674,676,678,680,682],{"class":170,"line":171},[168,655,175],{"class":174},[168,657,213],{"class":181},[168,659,635],{"class":188},[168,661,219],{"class":181},[168,663,664],{"class":188}," RunTypeKind",[168,666,219],{"class":181},[168,668,178],{"class":174},[168,670,671],{"class":188}," FormatAnnotation",[168,673,225],{"class":181},[168,675,228],{"class":174},[168,677,195],{"class":181},[168,679,233],{"class":198},[168,681,202],{"class":181},[168,683,205],{"class":181},[168,685,686],{"class":170,"line":208},[168,687,244],{"emptyLinePlaceholder":243},[168,689,690],{"class":170,"line":240},[168,691,692],{"class":250},"\u002F\u002F Want mock data to look a certain way for a kind? Register a mock fn for\n",[168,694,695],{"class":170,"line":247},[168,696,697],{"class":250},"\u002F\u002F that ReflectionKind. Return `undefined` to fall back to the default mock.\n",[168,699,700],{"class":170,"line":254},[168,701,702],{"class":250},"\u002F\u002F Here: make every mocked string format spit out a friendlier value.\n",[168,704,705,707,710,712,715,717,720,724,726,728,730,733],{"class":170,"line":260},[168,706,635],{"class":279},[168,708,709],{"class":188},"(RunTypeKind",[168,711,400],{"class":181},[168,713,714],{"class":188},"string",[168,716,219],{"class":181},[168,718,719],{"class":181}," (",[168,721,723],{"class":722},"sHdIc","annotation",[168,725,295],{"class":181},[168,727,671],{"class":390},[168,729,362],{"class":181},[168,731,732],{"class":269}," =>",[168,734,735],{"class":181}," {\n",[168,737,738,741,743,745,747,750,753,755,758,760,763,766,768,771,773],{"class":170,"line":266},[168,739,740],{"class":174},"  if",[168,742,719],{"class":291},[168,744,723],{"class":188},[168,746,400],{"class":181},[168,748,749],{"class":188},"name",[168,751,752],{"class":181}," ===",[168,754,195],{"class":181},[168,756,757],{"class":198},"email",[168,759,202],{"class":181},[168,761,762],{"class":291},") ",[168,764,765],{"class":174},"return",[168,767,195],{"class":181},[168,769,770],{"class":198},"someone@example.com",[168,772,202],{"class":181},[168,774,205],{"class":181},[168,776,777,780,783],{"class":170,"line":288},[168,778,779],{"class":174},"  return",[168,781,782],{"class":181}," undefined;",[168,784,785],{"class":250}," \u002F\u002F defer to the built-in mock for everything else\n",[168,787,788,790,792],{"class":170,"line":308},[168,789,225],{"class":181},[168,791,362],{"class":188},[168,793,205],{"class":181},[168,795,796],{"class":170,"line":340},[168,797,244],{"emptyLinePlaceholder":243},[168,799,800],{"class":170,"line":357},[168,801,802],{"class":250},"\u002F\u002F From now on createMockType\u003CT>() uses this when it mocks a string format.\n",[168,804,805],{"class":170,"line":367},[168,806,807],{"class":250},"\u002F\u002F (createMockType itself is covered in the Mocking guide.)\n",[168,809,810,812],{"class":170,"line":372},[168,811,586],{"class":174},[168,813,814],{"class":181}," {};\n",[150,816,817,818,820,821,824,825,827],{},"You get the format annotation (its ",[154,819,749],{}," and ",[154,822,823],{},"params","), so you can branch: friendly emails for ",[154,826,757],{},", something else for the rest.",[145,829,138],{"id":830},"pure-functions",[150,832,833,834,837,838,841],{},"Register a pure helper with ",[154,835,836],{},"registerPureFnFactory(\"namespace::name\", factory)",". The single ",[154,839,840],{},"\"namespace::name\""," id keeps the helper easy to find, the factory returns the real function, and the build inlines it into the generated code.",[159,843,845],{"className":161,"code":844,"language":163,"meta":164,"style":164},"import {registerPureFnFactory} from 'ts-runtypes';\n\n\u002F\u002F Pure functions are tiny, self-contained helpers the build can inline into\n\u002F\u002F the generated (JIT) code. The factory returns the real function; it must\n\u002F\u002F be self-contained — no outer-scope captures, no `this`, no await\u002Fyield.\n\nexport const slugify = registerPureFnFactory('app::slugify', function () {\n  \u002F\u002F Anything declared INSIDE the factory is fine — it ships with the helper.\n  const NON_WORD = \u002F[^a-z0-9]+\u002Fg;\n  return function _slugify(input: string): string {\n    return input.toLowerCase().replace(NON_WORD, '-').replace(\u002F^-|-$\u002Fg, '');\n  };\n});\n",[154,846,847,868,872,877,882,887,891,925,930,955,980,1051,1056],{"__ignoreMap":164},[168,848,849,851,853,856,858,860,862,864,866],{"class":170,"line":171},[168,850,175],{"class":174},[168,852,213],{"class":181},[168,854,855],{"class":188},"registerPureFnFactory",[168,857,225],{"class":181},[168,859,228],{"class":174},[168,861,195],{"class":181},[168,863,233],{"class":198},[168,865,202],{"class":181},[168,867,205],{"class":181},[168,869,870],{"class":170,"line":208},[168,871,244],{"emptyLinePlaceholder":243},[168,873,874],{"class":170,"line":240},[168,875,876],{"class":250},"\u002F\u002F Pure functions are tiny, self-contained helpers the build can inline into\n",[168,878,879],{"class":170,"line":247},[168,880,881],{"class":250},"\u002F\u002F the generated (JIT) code. The factory returns the real function; it must\n",[168,883,884],{"class":170,"line":254},[168,885,886],{"class":250},"\u002F\u002F be self-contained — no outer-scope captures, no `this`, no await\u002Fyield.\n",[168,888,889],{"class":170,"line":260},[168,890,244],{"emptyLinePlaceholder":243},[168,892,893,895,898,901,903,906,908,910,913,915,917,920,923],{"class":170,"line":266},[168,894,586],{"class":174},[168,896,897],{"class":269}," const",[168,899,900],{"class":188}," slugify ",[168,902,276],{"class":181},[168,904,905],{"class":279}," registerPureFnFactory",[168,907,282],{"class":188},[168,909,202],{"class":181},[168,911,912],{"class":198},"app::slugify",[168,914,202],{"class":181},[168,916,219],{"class":181},[168,918,919],{"class":269}," function",[168,921,922],{"class":181}," ()",[168,924,735],{"class":181},[168,926,927],{"class":170,"line":288},[168,928,929],{"class":250},"  \u002F\u002F Anything declared INSIDE the factory is fine — it ships with the helper.\n",[168,931,932,935,938,940,943,946,949,953],{"class":170,"line":308},[168,933,934],{"class":269},"  const",[168,936,937],{"class":188}," NON_WORD",[168,939,394],{"class":181},[168,941,942],{"class":181}," \u002F[^",[168,944,945],{"class":198},"a-z0-9",[168,947,948],{"class":181},"]+\u002F",[168,950,952],{"class":951},"sbssI","g",[168,954,205],{"class":181},[168,956,957,959,961,964,966,969,971,973,976,978],{"class":170,"line":340},[168,958,779],{"class":174},[168,960,919],{"class":269},[168,962,963],{"class":279}," _slugify",[168,965,282],{"class":181},[168,967,968],{"class":722},"input",[168,970,295],{"class":181},[168,972,455],{"class":390},[168,974,975],{"class":181},"):",[168,977,455],{"class":390},[168,979,735],{"class":181},[168,981,982,985,988,990,993,995,997,1000,1002,1005,1007,1009,1012,1014,1016,1018,1020,1022,1025,1028,1030,1033,1035,1038,1040,1042,1044,1047,1049],{"class":170,"line":357},[168,983,984],{"class":174},"    return",[168,986,987],{"class":188}," input",[168,989,400],{"class":181},[168,991,992],{"class":279},"toLowerCase",[168,994,488],{"class":291},[168,996,400],{"class":181},[168,998,999],{"class":279},"replace",[168,1001,282],{"class":291},[168,1003,1004],{"class":188},"NON_WORD",[168,1006,219],{"class":181},[168,1008,195],{"class":181},[168,1010,1011],{"class":198},"-",[168,1013,202],{"class":181},[168,1015,362],{"class":291},[168,1017,400],{"class":181},[168,1019,999],{"class":279},[168,1021,282],{"class":291},[168,1023,1024],{"class":181},"\u002F",[168,1026,1027],{"class":174},"^",[168,1029,1011],{"class":198},[168,1031,1032],{"class":181},"|",[168,1034,1011],{"class":198},[168,1036,1037],{"class":174},"$",[168,1039,1024],{"class":181},[168,1041,952],{"class":951},[168,1043,219],{"class":181},[168,1045,1046],{"class":181}," ''",[168,1048,362],{"class":291},[168,1050,205],{"class":181},[168,1052,1053],{"class":170,"line":367},[168,1054,1055],{"class":181},"  };\n",[168,1057,1058,1060,1062],{"class":170,"line":372},[168,1059,225],{"class":181},[168,1061,362],{"class":188},[168,1063,205],{"class":181},[150,1065,1066,1067,1070,1071,1074,1075,1024,1078,1081,1082,1084,1085,1088],{},"The rules are strict because the helper gets lifted out of its surroundings: it must be ",[136,1068,1069],{},"self-contained",", with no outer-scope captures, no ",[154,1072,1073],{},"this",", no ",[154,1076,1077],{},"await",[154,1079,1080],{},"yield",", and no dynamic ",[154,1083,175],{},". Anything it needs goes ",[628,1086,1087],{},"inside"," the factory (like the regex above). Break a rule and you get a build-time diagnostic.",[145,1090,1092],{"id":1091},"overriding-compiler-output","Overriding compiler output",[150,1094,1095,1096,1099,1100,1103],{},"Sometimes you know a better function than anything the compiler can generate. A hand-tuned JSON encoder for a payload you send on every reply, a wire format that is not the plain shape of your type, or a quick workaround for a one-off bug. The ",[154,1097,1098],{},"overrideX"," helpers let you register your own pure function for one type, and every matching ",[154,1101,1102],{},"createX"," call returns it instead of the generated body.",[159,1105,1107],{"className":161,"code":1106,"language":163,"meta":164,"style":164},"import {overrideJsonEncoder, createJsonEncoder} from 'ts-runtypes';\n\n\u002F\u002F Declared once, near the type. The function must be pure, same rules as above.\noverrideJsonEncoder\u003CUser>((user) => `{\"id\":${user.id}}`);\n\n\u002F\u002F Anywhere else, nothing changes at the call site:\nconst encode = createJsonEncoder\u003CUser>();\n",[154,1108,1109,1135,1139,1144,1193,1197,1202],{"__ignoreMap":164},[168,1110,1111,1113,1115,1118,1120,1123,1125,1127,1129,1131,1133],{"class":170,"line":171},[168,1112,175],{"class":174},[168,1114,213],{"class":181},[168,1116,1117],{"class":188},"overrideJsonEncoder",[168,1119,219],{"class":181},[168,1121,1122],{"class":188}," createJsonEncoder",[168,1124,225],{"class":181},[168,1126,228],{"class":174},[168,1128,195],{"class":181},[168,1130,233],{"class":198},[168,1132,202],{"class":181},[168,1134,205],{"class":181},[168,1136,1137],{"class":170,"line":208},[168,1138,244],{"emptyLinePlaceholder":243},[168,1140,1141],{"class":170,"line":240},[168,1142,1143],{"class":250},"\u002F\u002F Declared once, near the type. The function must be pure, same rules as above.\n",[168,1145,1146,1148,1150,1153,1155,1157,1159,1162,1164,1166,1169,1172,1175,1177,1179,1182,1184,1186,1189,1191],{"class":170,"line":247},[168,1147,1117],{"class":279},[168,1149,479],{"class":181},[168,1151,1152],{"class":390},"User",[168,1154,485],{"class":181},[168,1156,282],{"class":188},[168,1158,282],{"class":181},[168,1160,1161],{"class":722},"user",[168,1163,362],{"class":181},[168,1165,732],{"class":269},[168,1167,1168],{"class":181}," `",[168,1170,1171],{"class":198},"{\"id\":",[168,1173,1174],{"class":181},"${",[168,1176,1161],{"class":188},[168,1178,400],{"class":181},[168,1180,1181],{"class":188},"id",[168,1183,225],{"class":181},[168,1185,225],{"class":198},[168,1187,1188],{"class":181},"`",[168,1190,362],{"class":188},[168,1192,205],{"class":181},[168,1194,1195],{"class":170,"line":254},[168,1196,244],{"emptyLinePlaceholder":243},[168,1198,1199],{"class":170,"line":260},[168,1200,1201],{"class":250},"\u002F\u002F Anywhere else, nothing changes at the call site:\n",[168,1203,1204,1206,1209,1211,1213,1215,1217,1219,1221],{"class":170,"line":266},[168,1205,270],{"class":269},[168,1207,1208],{"class":188}," encode ",[168,1210,276],{"class":181},[168,1212,1122],{"class":279},[168,1214,479],{"class":181},[168,1216,1152],{"class":390},[168,1218,485],{"class":181},[168,1220,488],{"class":188},[168,1222,205],{"class":181},[150,1224,1225,1226,1229,1230,1229,1232,1235],{},"There is one override twin for every factory (",[154,1227,1228],{},"overrideValidate",", ",[154,1231,1117],{},[154,1233,1234],{},"overrideBinaryEncoder",", and so on). Your function has to match the signature the family uses internally, so a validation-errors override receives the value, the path, and the errors list, exactly like the generated one.",[150,1237,1238],{},"An override applies to its type everywhere the type appears. If you override the encoder for a field type, every object that contains that field picks it up too. You can register exactly one override per type and function, so a second one (with any body) is a build error. Overriding validation is worth a second thought, because decoders use it to tell union branches apart, so a looser validator makes those decoders looser as well. The build warns you when that happens.",[150,1240,1241,1242,1245,1246,1249],{},"One thing to keep in mind: an override is matched by the ",[136,1243,1244],{},"shape"," of the type, not its name. So ",[154,1247,1248],{},"overrideValidate\u003Cstring>"," applies to every string in the build, including string fields inside other objects. That is often what you want for a wire format, but when you mean one specific type, give it a brand so it has its own shape:",[159,1251,1253],{"className":161,"code":1252,"language":163,"meta":164,"style":164},"type UserId = string & {readonly __brand: 'UserId'};\n\n\u002F\u002F Only UserId, not every string.\noverrideValidate\u003CUserId>((v) => typeof v === 'string' && (v as string).startsWith('u_'));\n",[154,1254,1255,1288,1292,1297],{"__ignoreMap":164},[168,1256,1257,1259,1262,1264,1266,1269,1271,1274,1277,1279,1281,1284,1286],{"class":170,"line":171},[168,1258,387],{"class":269},[168,1260,1261],{"class":390}," UserId",[168,1263,394],{"class":181},[168,1265,455],{"class":390},[168,1267,1268],{"class":181}," &",[168,1270,213],{"class":181},[168,1272,1273],{"class":269},"readonly",[168,1275,1276],{"class":291}," __brand",[168,1278,295],{"class":181},[168,1280,195],{"class":181},[168,1282,1283],{"class":198},"UserId",[168,1285,202],{"class":181},[168,1287,458],{"class":181},[168,1289,1290],{"class":170,"line":208},[168,1291,244],{"emptyLinePlaceholder":243},[168,1293,1294],{"class":170,"line":240},[168,1295,1296],{"class":250},"\u002F\u002F Only UserId, not every string.\n",[168,1298,1299,1301,1303,1305,1307,1309,1311,1314,1316,1318,1320,1323,1326,1328,1330,1332,1335,1338,1341,1343,1345,1347,1350,1352,1354,1357,1359,1362],{"class":170,"line":247},[168,1300,1228],{"class":279},[168,1302,479],{"class":181},[168,1304,1283],{"class":390},[168,1306,485],{"class":181},[168,1308,282],{"class":188},[168,1310,282],{"class":181},[168,1312,1313],{"class":722},"v",[168,1315,362],{"class":181},[168,1317,732],{"class":269},[168,1319,414],{"class":181},[168,1321,1322],{"class":188}," v ",[168,1324,1325],{"class":181},"===",[168,1327,195],{"class":181},[168,1329,714],{"class":198},[168,1331,202],{"class":181},[168,1333,1334],{"class":181}," &&",[168,1336,1337],{"class":188}," (v ",[168,1339,1340],{"class":174},"as",[168,1342,455],{"class":390},[168,1344,362],{"class":188},[168,1346,400],{"class":181},[168,1348,1349],{"class":279},"startsWith",[168,1351,282],{"class":188},[168,1353,202],{"class":181},[168,1355,1356],{"class":198},"u_",[168,1358,202],{"class":181},[168,1360,1361],{"class":188},"))",[168,1363,205],{"class":181},[1365,1366,1367],"style",{},"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}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}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 .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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}","Extend RunTypes with pure inline helpers and your own formats and mock generators.","md",null,{"toc":18},{"title":50,"description":1368},"wJ7btu4XyRjLnNk4Yty0fVS4bZcs0SIT4CN6BY5wYss",[1375,1377],{"title":46,"path":47,"stem":48,"description":1376,"children":-1},"The one marker you'll actually type, for wrapping your own helpers.",{"title":61,"path":56,"stem":62,"description":1378,"children":-1},"How AI agents and the compiler work together to enrich your types.",1781995977801]