[{"data":1,"prerenderedAt":2853},["ShallowReactive",2],{"navigation_docs":3,"-guide-json-schema-generation":149,"-guide-json-schema-generation-surround":2848},[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":78,"body":151,"description":2842,"extension":2843,"links":2844,"meta":2845,"navigation":247,"path":79,"seo":2846,"stem":80,"__hash__":2847},"docs\u002F02.guide\u002F14.json-schema-generation.md",{"type":152,"value":153},"minimark",[154,158,161,166,177,319,339,343,350,410,413,417,424,533,540,544,565,725,741,745,791,807,810,821,824,827,830,897,911,918,923,937,1105,1108,1112,1117,1122,1201,1205,1291,1300,1304,1365,1375,1379,1459,1472,1476,1520,1525,1529,1538,1653,1662,1771,1774,1778,1787,1791,1933,1940,1944,2091,2101,2105,2233,2250,2254,2427,2436,2440,2612,2618,2622,2798,2804,2808,2819,2830,2838],[155,156,157],"p",{},"Every type the library can validate can also describe itself as a JSON Schema document (draft 2020-12). The document is generated at build time, exactly like the validators, so reading it at runtime is a plain function call with no reflection and no schema assembly.",[155,159,160],{},"Use it to publish an OpenAPI description of your request bodies, to hand a tool-calling AI the shape of a function's arguments, or to let any schema-aware tool understand your types without knowing anything about this library.",[162,163,165],"h2",{"id":164},"getting-the-document","Getting the document",[155,167,168,172,173,176],{},[169,170,171],"code",{},"createJsonSchemaFn\u003CT>()"," returns a function that produces the document for ",[169,174,175],{},"T",". It accepts the same three call forms as every other factory (type-first, value-first, run-type).",[178,179,184],"pre",{"className":180,"code":181,"language":182,"meta":183,"style":183},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F createJsonSchemaFn -> a function that returns the JSON Schema document\n\u002F\u002F describing T. The document is generated at build time; calling it costs\n\u002F\u002F nothing at runtime.\nconst orderSchemaDoc = createJsonSchemaFn\u003COrder>();\n\norderSchemaDoc();\n\u002F\u002F {\n\u002F\u002F   type: 'object',\n\u002F\u002F   properties: {\n\u002F\u002F     id: {type: 'string'},\n\u002F\u002F     total: {type: 'string', pattern: '^-?[0-9]+$', jsType: 'bigint'},\n\u002F\u002F     placed: {type: 'string', format: 'date-time', jsType: 'Date'},\n\u002F\u002F     note: {type: 'string'},\n\u002F\u002F   },\n\u002F\u002F   required: ['id', 'total', 'placed'],\n\u002F\u002F }\n","ts","",[169,185,186,195,201,207,242,249,259,265,271,277,283,289,295,301,307,313],{"__ignoreMap":183},[187,188,191],"span",{"class":189,"line":190},"line",1,[187,192,194],{"class":193},"sHwdD","\u002F\u002F createJsonSchemaFn -> a function that returns the JSON Schema document\n",[187,196,198],{"class":189,"line":197},2,[187,199,200],{"class":193},"\u002F\u002F describing T. The document is generated at build time; calling it costs\n",[187,202,204],{"class":189,"line":203},3,[187,205,206],{"class":193},"\u002F\u002F nothing at runtime.\n",[187,208,210,214,218,222,226,229,233,236,239],{"class":189,"line":209},4,[187,211,213],{"class":212},"spNyl","const",[187,215,217],{"class":216},"sTEyZ"," orderSchemaDoc ",[187,219,221],{"class":220},"sMK4o","=",[187,223,225],{"class":224},"s2Zo4"," createJsonSchemaFn",[187,227,228],{"class":220},"\u003C",[187,230,232],{"class":231},"sBMFI","Order",[187,234,235],{"class":220},">",[187,237,238],{"class":216},"()",[187,240,241],{"class":220},";\n",[187,243,245],{"class":189,"line":244},5,[187,246,248],{"emptyLinePlaceholder":247},true,"\n",[187,250,252,255,257],{"class":189,"line":251},6,[187,253,254],{"class":224},"orderSchemaDoc",[187,256,238],{"class":216},[187,258,241],{"class":220},[187,260,262],{"class":189,"line":261},7,[187,263,264],{"class":193},"\u002F\u002F {\n",[187,266,268],{"class":189,"line":267},8,[187,269,270],{"class":193},"\u002F\u002F   type: 'object',\n",[187,272,274],{"class":189,"line":273},9,[187,275,276],{"class":193},"\u002F\u002F   properties: {\n",[187,278,280],{"class":189,"line":279},10,[187,281,282],{"class":193},"\u002F\u002F     id: {type: 'string'},\n",[187,284,286],{"class":189,"line":285},11,[187,287,288],{"class":193},"\u002F\u002F     total: {type: 'string', pattern: '^-?[0-9]+$', jsType: 'bigint'},\n",[187,290,292],{"class":189,"line":291},12,[187,293,294],{"class":193},"\u002F\u002F     placed: {type: 'string', format: 'date-time', jsType: 'Date'},\n",[187,296,298],{"class":189,"line":297},13,[187,299,300],{"class":193},"\u002F\u002F     note: {type: 'string'},\n",[187,302,304],{"class":189,"line":303},14,[187,305,306],{"class":193},"\u002F\u002F   },\n",[187,308,310],{"class":189,"line":309},15,[187,311,312],{"class":193},"\u002F\u002F   required: ['id', 'total', 'placed'],\n",[187,314,316],{"class":189,"line":315},16,[187,317,318],{"class":193},"\u002F\u002F }\n",[155,320,321,322,325,326,325,329,332,333,338],{},"The standard keywords describe the JSON that travels on the wire. Where a value is JavaScript-only (a ",[169,323,324],{},"Date",", a ",[169,327,328],{},"bigint",[169,330,331],{},"Map","), an extra keyword sits next to them and says what the JSON becomes after decoding; those extra keywords are the ",[334,335,337],"a",{"href":336},"#json-schema-js","JSON Schema JS"," extension, and every document that carries them is still a valid standard schema (validators ignore keywords they do not know).",[162,340,342],{"id":341},"plain-standard-documents","Plain standard documents",[155,344,345,346,349],{},"If a consumer should see only standard vocabulary, pass ",[169,347,348],{},"portable",":",[178,351,353],{"className":180,"code":352,"language":182,"meta":183,"style":183},"\u002F\u002F {portable: true} strips the extension keywords, leaving plain draft\n\u002F\u002F 2020-12 any tool can consume.\norderSchemaDoc({libraryOptions: {portable: true}});\n\u002F\u002F placed is now {type: 'string', format: 'date-time'} and total is\n\u002F\u002F {type: 'string', pattern: '^-?[0-9]+$'}: only standard keywords survive.\n",[169,354,355,360,365,400,405],{"__ignoreMap":183},[187,356,357],{"class":189,"line":190},[187,358,359],{"class":193},"\u002F\u002F {portable: true} strips the extension keywords, leaving plain draft\n",[187,361,362],{"class":189,"line":197},[187,363,364],{"class":193},"\u002F\u002F 2020-12 any tool can consume.\n",[187,366,367,369,372,375,379,381,384,386,388,392,395,398],{"class":189,"line":203},[187,368,254],{"class":224},[187,370,371],{"class":216},"(",[187,373,374],{"class":220},"{",[187,376,378],{"class":377},"swJcz","libraryOptions",[187,380,349],{"class":220},[187,382,383],{"class":220}," {",[187,385,348],{"class":377},[187,387,349],{"class":220},[187,389,391],{"class":390},"sfNiH"," true",[187,393,394],{"class":220},"}}",[187,396,397],{"class":216},")",[187,399,241],{"class":220},[187,401,402],{"class":189,"line":209},[187,403,404],{"class":193},"\u002F\u002F placed is now {type: 'string', format: 'date-time'} and total is\n",[187,406,407],{"class":189,"line":244},[187,408,409],{"class":193},"\u002F\u002F {type: 'string', pattern: '^-?[0-9]+$'}: only standard keywords survive.\n",[155,411,412],{},"Stripping the extension never changes which values the document accepts; it only removes the JavaScript annotations.",[162,414,416],{"id":415},"closed-objects-follow-the-encoder","Closed objects follow the encoder",[155,418,419,420,423],{},"By default a generated document says nothing about extra keys, matching how validation treats them (an undeclared key is ignored, not an error). Whether extra keys can actually appear on the wire is decided by the ",[334,421,422],{"href":51},"JSON encoder's strategy",": the clone and direct strategies build the output from the declared shape, so their wire never carries an undeclared key, while mutate passes extras through. Declare the strategy you pair the document with, and the document closes to match:",[178,425,427],{"className":180,"code":426,"language":182,"meta":183,"style":183},"\u002F\u002F Declaring the paired encoder strategy closes the document to the keys the\n\u002F\u002F wire can actually carry: clone and direct never emit undeclared keys, so\n\u002F\u002F every object with declared properties gains additionalProperties: false.\norderSchemaDoc({libraryOptions: {encoderStrategy: 'clone'}});\n\u002F\u002F {type: 'object', properties: {...}, required: [...], additionalProperties: false}\n\n\u002F\u002F A mutate pairing preserves extra keys on the wire, so its document stays\n\u002F\u002F open; records keep the index schema additionalProperties already carries.\norderSchemaDoc({libraryOptions: {encoderStrategy: 'mutate'}}); \u002F\u002F unchanged\n",[169,428,429,434,439,444,479,484,488,493,498],{"__ignoreMap":183},[187,430,431],{"class":189,"line":190},[187,432,433],{"class":193},"\u002F\u002F Declaring the paired encoder strategy closes the document to the keys the\n",[187,435,436],{"class":189,"line":197},[187,437,438],{"class":193},"\u002F\u002F wire can actually carry: clone and direct never emit undeclared keys, so\n",[187,440,441],{"class":189,"line":203},[187,442,443],{"class":193},"\u002F\u002F every object with declared properties gains additionalProperties: false.\n",[187,445,446,448,450,452,454,456,458,461,463,466,470,473,475,477],{"class":189,"line":209},[187,447,254],{"class":224},[187,449,371],{"class":216},[187,451,374],{"class":220},[187,453,378],{"class":377},[187,455,349],{"class":220},[187,457,383],{"class":220},[187,459,460],{"class":377},"encoderStrategy",[187,462,349],{"class":220},[187,464,465],{"class":220}," '",[187,467,469],{"class":468},"sfazB","clone",[187,471,472],{"class":220},"'",[187,474,394],{"class":220},[187,476,397],{"class":216},[187,478,241],{"class":220},[187,480,481],{"class":189,"line":244},[187,482,483],{"class":193},"\u002F\u002F {type: 'object', properties: {...}, required: [...], additionalProperties: false}\n",[187,485,486],{"class":189,"line":251},[187,487,248],{"emptyLinePlaceholder":247},[187,489,490],{"class":189,"line":261},[187,491,492],{"class":193},"\u002F\u002F A mutate pairing preserves extra keys on the wire, so its document stays\n",[187,494,495],{"class":189,"line":267},[187,496,497],{"class":193},"\u002F\u002F open; records keep the index schema additionalProperties already carries.\n",[187,499,500,502,504,506,508,510,512,514,516,518,521,523,525,527,530],{"class":189,"line":273},[187,501,254],{"class":224},[187,503,371],{"class":216},[187,505,374],{"class":220},[187,507,378],{"class":377},[187,509,349],{"class":220},[187,511,383],{"class":220},[187,513,460],{"class":377},[187,515,349],{"class":220},[187,517,465],{"class":220},[187,519,520],{"class":468},"mutate",[187,522,472],{"class":220},[187,524,394],{"class":220},[187,526,397],{"class":216},[187,528,529],{"class":220},";",[187,531,532],{"class":193}," \u002F\u002F unchanged\n",[155,534,535,536,539],{},"There is no separate option to force ",[169,537,538],{},"additionalProperties"," by hand. The key policy belongs to the codec, and deriving it keeps the document from ever contradicting what the wire really does. The compact strategy is refused here: its wire is positional arrays, which a keyed document does not describe.",[162,541,543],{"id":542},"the-standard-interface","The standard interface",[155,545,546,549,550,556,557,560,561,564],{},[169,547,548],{},"createStandardSchema\u003CT>()"," implements two interoperability standards from ",[334,551,555],{"href":552,"rel":553},"https:\u002F\u002Fgithub.com\u002Fstandard-schema\u002Fstandard-schema",[554],"nofollow","Standard Schema"," in one object: the validation interface (",[169,558,559],{},"~standard.validate",") and the JSON Schema interface (",[169,562,563],{},"~standard.jsonSchema","). Any framework that understands either standard can consume it directly.",[178,566,568],{"className":180,"code":567,"language":182,"meta":183,"style":183},"\u002F\u002F createStandardSchema returns ONE object implementing both standard\n\u002F\u002F interfaces: validation (validate) and JSON Schema conversion (jsonSchema).\nconst orderSchema = createStandardSchema\u003COrder>();\n\norderSchema['~standard'].validate({id: 'o1'}); \u002F\u002F {issues: [...]}\norderSchema['~standard'].jsonSchema.input(); \u002F\u002F the same document as above\norderSchema['~standard'].jsonSchema.output({target: 'draft-2020-12'});\n",[169,569,570,575,580,602,606,653,682],{"__ignoreMap":183},[187,571,572],{"class":189,"line":190},[187,573,574],{"class":193},"\u002F\u002F createStandardSchema returns ONE object implementing both standard\n",[187,576,577],{"class":189,"line":197},[187,578,579],{"class":193},"\u002F\u002F interfaces: validation (validate) and JSON Schema conversion (jsonSchema).\n",[187,581,582,584,587,589,592,594,596,598,600],{"class":189,"line":203},[187,583,213],{"class":212},[187,585,586],{"class":216}," orderSchema ",[187,588,221],{"class":220},[187,590,591],{"class":224}," createStandardSchema",[187,593,228],{"class":220},[187,595,232],{"class":231},[187,597,235],{"class":220},[187,599,238],{"class":216},[187,601,241],{"class":220},[187,603,604],{"class":189,"line":209},[187,605,248],{"emptyLinePlaceholder":247},[187,607,608,611,613,616,618,621,624,627,629,631,634,636,638,641,643,646,648,650],{"class":189,"line":244},[187,609,610],{"class":216},"orderSchema[",[187,612,472],{"class":220},[187,614,615],{"class":468},"~standard",[187,617,472],{"class":220},[187,619,620],{"class":216},"]",[187,622,623],{"class":220},".",[187,625,626],{"class":224},"validate",[187,628,371],{"class":216},[187,630,374],{"class":220},[187,632,633],{"class":377},"id",[187,635,349],{"class":220},[187,637,465],{"class":220},[187,639,640],{"class":468},"o1",[187,642,472],{"class":220},[187,644,645],{"class":220},"}",[187,647,397],{"class":216},[187,649,529],{"class":220},[187,651,652],{"class":193}," \u002F\u002F {issues: [...]}\n",[187,654,655,657,659,661,663,665,667,670,672,675,677,679],{"class":189,"line":251},[187,656,610],{"class":216},[187,658,472],{"class":220},[187,660,615],{"class":468},[187,662,472],{"class":220},[187,664,620],{"class":216},[187,666,623],{"class":220},[187,668,669],{"class":216},"jsonSchema",[187,671,623],{"class":220},[187,673,674],{"class":224},"input",[187,676,238],{"class":216},[187,678,529],{"class":220},[187,680,681],{"class":193}," \u002F\u002F the same document as above\n",[187,683,684,686,688,690,692,694,696,698,700,703,705,707,710,712,714,717,719,721,723],{"class":189,"line":261},[187,685,610],{"class":216},[187,687,472],{"class":220},[187,689,615],{"class":468},[187,691,472],{"class":220},[187,693,620],{"class":216},[187,695,623],{"class":220},[187,697,669],{"class":216},[187,699,623],{"class":220},[187,701,702],{"class":224},"output",[187,704,371],{"class":216},[187,706,374],{"class":220},[187,708,709],{"class":377},"target",[187,711,349],{"class":220},[187,713,465],{"class":220},[187,715,716],{"class":468},"draft-2020-12",[187,718,472],{"class":220},[187,720,645],{"class":220},[187,722,397],{"class":216},[187,724,241],{"class":220},[155,726,727,730,731,734,735,737,738,740],{},[169,728,729],{},"input()"," and ",[169,732,733],{},"output()"," return the same document: this library validates values without transforming them, so what goes in is what comes out. The optional ",[169,736,709],{}," names the dialect; only ",[169,739,716],{}," is supported, and any other value throws rather than emitting a document that could be read wrong.",[162,742,744],{"id":743},"unions-follow-the-serialized-wire","Unions follow the serialized wire",[155,746,747,748,751,752,755,756,759,760,763,764,767,768,770,771,774,775,778,779,782,783,786,787,790],{},"The documents describe what actually travels, and for unions that is this library's own wire. A union whose members are all plain JSON (",[169,749,750],{},"'a' | 'b'",", ",[169,753,754],{},"string | null",") travels as the bare value and gets the ordinary ",[169,757,758],{},"enum"," or ",[169,761,762],{},"anyOf"," document. A union with JavaScript-only or object members travels as a two slot array, ",[169,765,766],{},"[index, value]",", because plain JSON could not say which member a value belongs to once it is encoded: once a ",[169,769,324],{}," member and a ",[169,772,773],{},"string"," member have both encoded the wire holds just a string, so the encoder writes ",[169,776,777],{},"[0, \"2026-08-10T09:00:00Z\"]"," and the first slot names the member. The document spells out exactly those pairs (object members share one merged arm under index ",[169,780,781],{},"-1",") and marks the node with ",[169,784,785],{},"jsType: 'union'",". So a value that validates against the document is precisely a value the ",[334,788,789],{"href":51},"JSON decoder"," can decode, unions included.",[792,793,794,795,798,799,802,803,806],"note",{},"Recursive types close over themselves with standard references: a type that contains itself emits ",[169,796,797],{},"{$ref: '#'}"," at the cycle, and shared inner cycles ride ",[169,800,801],{},"$defs",". Whatever a document cannot express (a function member, a class identity) is left out or widened to ",[169,804,805],{},"{}",", so a generated document may say less than the type, but never something wrong.",[162,808,337],{"id":809},"json-schema-js",[155,811,812,813,325,815,817,818,820],{},"JSON Schema can not describe all JavaScript values. A ",[169,814,324],{},[169,816,328],{}," or a ",[169,819,331],{}," still travels fine as JSON (a Date as an ISO string, a bigint as a string of digits, a Map as an array of pairs), but a standard schema can only describe the string or the array. It can not say that the string should come back as a Date once the JSON is decoded.",[155,822,823],{},"This extension adds that missing piece. A few extra keywords sit next to the standard ones and say what the JSON becomes in JavaScript after decoding. The standard keywords keep describing the JSON that travels.",[792,825,826],{},"The main goal of this extension is to store full JavaScript and TypeScript type information inside a JSON Schema. The generator above writes it: the documents it emits carry these keywords so a reader knows what the JSON decodes to.",[155,828,829],{},"Every document that uses the extension is still a valid JSON Schema (draft 2020-12). The standard requires validators to ignore keywords they do not know, so any validator reads the schema, skips the extra keywords, and checks exactly the same values. Delete every extension keyword and no validator changes its mind about any value.",[178,831,835],{"className":832,"code":833,"language":834,"meta":183,"style":183},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\"type\": \"string\", \"format\": \"date-time\", \"jsType\": \"Date\"}\n","json",[169,836,837],{"__ignoreMap":183},[187,838,839,841,844,847,849,851,854,856,858,861,863,866,868,870,872,875,877,879,881,884,886,888,890,892,894],{"class":189,"line":190},[187,840,374],{"class":220},[187,842,843],{"class":220},"\"",[187,845,846],{"class":212},"type",[187,848,843],{"class":220},[187,850,349],{"class":220},[187,852,853],{"class":220}," \"",[187,855,773],{"class":468},[187,857,843],{"class":220},[187,859,860],{"class":220},",",[187,862,853],{"class":220},[187,864,865],{"class":212},"format",[187,867,843],{"class":220},[187,869,349],{"class":220},[187,871,853],{"class":220},[187,873,874],{"class":468},"date-time",[187,876,843],{"class":220},[187,878,860],{"class":220},[187,880,853],{"class":220},[187,882,883],{"class":212},"jsType",[187,885,843],{"class":220},[187,887,349],{"class":220},[187,889,853],{"class":220},[187,891,324],{"class":468},[187,893,843],{"class":220},[187,895,896],{"class":220},"}\n",[155,898,899,900,903,904,907,908,910],{},"Every validator agrees this accepts ",[169,901,902],{},"\"2026-08-10T09:00:00Z\""," and rejects ",[169,905,906],{},"42",". A reader that knows the extension learns one more thing: the decoded value is a ",[169,909,324],{},", not a string.",[155,912,913,914,917],{},"You never write these keywords by hand. The generator emits them in the documents it produces. If you need schemas with no extension at all, pass ",[169,915,916],{},"{portable: true}"," and it strips every extension keyword.",[919,920,922],"h3",{"id":921},"the-keywords-at-a-glance","The keywords at a glance",[155,924,925,926,929,930,933,934,936],{},"Each keyword starts with a prefix that says where the described thing comes from: ",[169,927,928],{},"js"," is a JavaScript value, ",[169,931,932],{},"rt"," is a RunTypes type format, and ",[169,935,182],{}," is a TypeScript-only fact that no JSON value can show.",[938,939,940,956],"table",{},[941,942,943],"thead",{},[944,945,946,950,953],"tr",{},[947,948,949],"th",{},"Keyword",[947,951,952],{},"Sits beside",[947,954,955],{},"Says",[957,958,959,973,988,1002,1015,1030,1045,1064,1079,1092],"tbody",{},[944,960,961,966,970],{},[962,963,964],"td",{},[169,965,883],{},[962,967,968],{},[169,969,846],{},[962,971,972],{},"which JavaScript value the JSON decodes to",[944,974,975,980,985],{},[962,976,977],{},[169,978,979],{},"jsResolved",[962,981,982],{},[169,983,984],{},"jsType: 'Promise'",[962,986,987],{},"the schema of the resolved value",[944,989,990,995,999],{},[962,991,992],{},[169,993,994],{},"rtFormat",[962,996,997],{},[169,998,865],{},[962,1000,1001],{},"which type format the value belongs to",[944,1003,1004,1009,1012],{},[962,1005,1006],{},[169,1007,1008],{},"rtFormatParams",[962,1010,1011],{},"the constraint keywords",[962,1013,1014],{},"the format parameters, exactly as written",[944,1016,1017,1022,1027],{},[962,1018,1019],{},[169,1020,1021],{},"tsLabels",[962,1023,1024],{},[169,1025,1026],{},"prefixItems",[962,1028,1029],{},"the tuple slot names",[944,1031,1032,1037,1042],{},[962,1033,1034],{},[169,1035,1036],{},"tsReadonly",[962,1038,1039],{},[169,1040,1041],{},"required",[962,1043,1044],{},"which members are readonly",[944,1046,1047,1052,1061],{},[962,1048,1049],{},[169,1050,1051],{},"tsIndexes",[962,1053,1054,1057,1058],{},[169,1055,1056],{},"propertyNames"," \u002F ",[169,1059,1060],{},"patternProperties",[962,1062,1063],{},"index signatures whose key is not a plain string",[944,1065,1066,1071,1076],{},[962,1067,1068],{},[169,1069,1070],{},"tsTemplate",[962,1072,1073],{},[169,1074,1075],{},"pattern",[962,1077,1078],{},"the parts of a template literal type",[944,1080,1081,1086,1089],{},[962,1082,1083],{},[169,1084,1085],{},"tsFunction",[962,1087,1088],{},"nothing (functions have no JSON form)",[962,1090,1091],{},"a function signature",[944,1093,1094,1099,1102],{},[962,1095,1096],{},[169,1097,1098],{},"tsMeta",[962,1100,1101],{},"nothing (metadata has no JSON form)",[962,1103,1104],{},"a branded or metadata intersection type",[155,1106,1107],{},"Every keyword is optional. A schema that uses none of them is ordinary JSON Schema.",[919,1109,1111],{"id":1110},"jstype-what-the-json-decodes-to","jsType: what the JSON decodes to",[155,1113,1114,1116],{},[169,1115,883],{}," names the JavaScript value the JSON turns into. It always sits next to the standard keywords that describe the JSON itself.",[1118,1119,1121],"h4",{"id":1120},"values-that-travel-as-a-string","Values that travel as a string",[938,1123,1124,1137],{},[941,1125,1126],{},[944,1127,1128,1131,1134],{},[947,1129,1130],{},"TypeScript type",[947,1132,1133],{},"Schema",[947,1135,1136],{},"Travels as",[957,1138,1139,1153,1167,1183],{},[944,1140,1141,1145,1150],{},[962,1142,1143],{},[169,1144,324],{},[962,1146,1147],{},[169,1148,1149],{},"{type: 'string', format: 'date-time', jsType: 'Date'}",[962,1151,1152],{},"an ISO date-time string",[944,1154,1155,1159,1164],{},[962,1156,1157],{},[169,1158,328],{},[962,1160,1161],{},[169,1162,1163],{},"{type: 'string', pattern: '^-?[0-9]+$', jsType: 'bigint'}",[962,1165,1166],{},"a string of digits",[944,1168,1169,1175,1180],{},[962,1170,1171,1174],{},[169,1172,1173],{},"123n"," (a bigint literal)",[962,1176,1177],{},[169,1178,1179],{},"{type: 'string', const: '123', jsType: 'bigint'}",[962,1181,1182],{},"that exact digit string",[944,1184,1185,1190,1195],{},[962,1186,1187],{},[169,1188,1189],{},"RegExp",[962,1191,1192],{},[169,1193,1194],{},"{type: 'string', jsType: 'RegExp'}",[962,1196,1197,1198,397],{},"the regex as text, slashes and flags included (",[169,1199,1200],{},"\"\u002F^ab?c$\u002Fgi\"",[1118,1202,1204],{"id":1203},"temporal-values","Temporal values",[938,1206,1207,1217],{},[941,1208,1209],{},[944,1210,1211,1213,1215],{},[947,1212,1130],{},[947,1214,1133],{},[947,1216,1136],{},[957,1218,1219,1234,1249,1264],{},[944,1220,1221,1226,1231],{},[962,1222,1223],{},[169,1224,1225],{},"Temporal.Instant",[962,1227,1228],{},[169,1229,1230],{},"{type: 'string', format: 'date-time', jsType: 'Temporal.Instant'}",[962,1232,1233],{},"a date-time string",[944,1235,1236,1241,1246],{},[962,1237,1238],{},[169,1239,1240],{},"Temporal.PlainDate",[962,1242,1243],{},[169,1244,1245],{},"{type: 'string', format: 'date', jsType: 'Temporal.PlainDate'}",[962,1247,1248],{},"a date string",[944,1250,1251,1256,1261],{},[962,1252,1253],{},[169,1254,1255],{},"Temporal.Duration",[962,1257,1258],{},[169,1259,1260],{},"{type: 'string', format: 'duration', jsType: 'Temporal.Duration'}",[962,1262,1263],{},"a duration string",[944,1265,1266,1283,1288],{},[962,1267,1268,751,1271,751,1274,751,1277,751,1280],{},[169,1269,1270],{},"Temporal.ZonedDateTime",[169,1272,1273],{},"Temporal.PlainTime",[169,1275,1276],{},"Temporal.PlainDateTime",[169,1278,1279],{},"Temporal.PlainYearMonth",[169,1281,1282],{},"Temporal.PlainMonthDay",[962,1284,1285],{},[169,1286,1287],{},"{type: 'string', pattern: '...', jsType: '...'}",[962,1289,1290],{},"the string the type's own toJSON produces",[155,1292,1293,1294,1296,1297,1299],{},"The last row uses ",[169,1295,1075],{}," instead of ",[169,1298,865],{}," because those string shapes are not registered JSON Schema formats. A ZonedDateTime string carries a time zone name in brackets, which the standard date-time format does not allow, so claiming that format would make good data fail on other validators.",[1118,1301,1303],{"id":1302},"values-that-travel-as-a-container","Values that travel as a container",[938,1305,1306,1316],{},[941,1307,1308],{},[944,1309,1310,1312,1314],{},[947,1311,1130],{},[947,1313,1133],{},[947,1315,1136],{},[957,1317,1318,1333,1348],{},[944,1319,1320,1325,1330],{},[962,1321,1322],{},[169,1323,1324],{},"Map\u003CK, V>",[962,1326,1327],{},[169,1328,1329],{},"{type: 'array', items: {type: 'array', prefixItems: [K, V], items: false, minItems: 2}, jsType: 'Map'}",[962,1331,1332],{},"an array of key and value pairs",[944,1334,1335,1340,1345],{},[962,1336,1337],{},[169,1338,1339],{},"Set\u003CV>",[962,1341,1342],{},[169,1343,1344],{},"{type: 'array', items: V, uniqueItems: true, jsType: 'Set'}",[962,1346,1347],{},"an array of unique items",[944,1349,1350,1353,1362],{},[962,1351,1352],{},"a union with JavaScript-only or object members",[962,1354,1355,1358,1359,1361],{},[169,1356,1357],{},"{anyOf: [...], jsType: 'union'}",", each arm an ",[169,1360,766],{}," pair schema",[962,1363,1364],{},"a two slot array: the member index, then the member's own wire value",[155,1366,1367,1368,1370,1371,1374],{},"The key and value types are read from the schema itself: a Map's key and value are the two ",[169,1369,1026],{},", a Set's item is ",[169,1372,1373],{},"items",". There is no separate argument list, because the schema already had to describe the same JSON.",[1118,1376,1378],{"id":1377},"values-with-no-json-of-their-own","Values with no JSON of their own",[938,1380,1381,1391],{},[941,1382,1383],{},[944,1384,1385,1387,1389],{},[947,1386,1130],{},[947,1388,1133],{},[947,1390,1136],{},[957,1392,1393,1410,1426,1444],{},[944,1394,1395,1400,1405],{},[962,1396,1397],{},[169,1398,1399],{},"undefined",[962,1401,1402],{},[169,1403,1404],{},"{type: 'null', jsType: 'undefined'}",[962,1406,1407],{},[169,1408,1409],{},"null",[944,1411,1412,1417,1422],{},[962,1413,1414],{},[169,1415,1416],{},"void",[962,1418,1419],{},[169,1420,1421],{},"{type: 'null', jsType: 'void'}",[962,1423,1424],{},[169,1425,1409],{},[944,1427,1428,1433,1438],{},[962,1429,1430],{},[169,1431,1432],{},"Promise\u003CT>",[962,1434,1435],{},[169,1436,1437],{},"{jsType: 'Promise', jsResolved: T}",[962,1439,1440,1441,1443],{},"whatever ",[169,1442,175],{}," travels as",[944,1445,1446,1451,1456],{},[962,1447,1448],{},[169,1449,1450],{},"symbol",[962,1452,1453],{},[169,1454,1455],{},"{jsType: 'symbol'}",[962,1457,1458],{},"nothing, a symbol can not be encoded",[155,1460,1461,730,1463,1465,1466,1468,1469,1471],{},[169,1462,1399],{},[169,1464,1416],{}," both travel as JSON ",[169,1467,1409],{},", so on the wire the three look the same; only the keyword says which one comes back after decoding. A Promise is awaited before encoding, so what travels is the resolved value, and ",[169,1470,979],{}," holds its schema. A symbol has no encoding at all; the keyword only records the type so the document still states the TypeScript it came from.",[1118,1473,1475],{"id":1474},"the-two-broad-types","The two broad types",[938,1477,1478,1488],{},[941,1479,1480],{},[944,1481,1482,1484,1486],{},[947,1483,1130],{},[947,1485,1133],{},[947,1487,1136],{},[957,1489,1490,1505],{},[944,1491,1492,1497,1502],{},[962,1493,1494],{},[169,1495,1496],{},"any",[962,1498,1499],{},[169,1500,1501],{},"{jsType: 'any'}",[962,1503,1504],{},"any JSON value",[944,1506,1507,1512,1517],{},[962,1508,1509],{},[169,1510,1511],{},"object",[962,1513,1514],{},[169,1515,1516],{},"{type: ['object', 'array'], jsType: 'object'}",[962,1518,1519],{},"any object or array",[155,1521,1522,1524],{},[169,1523,1511],{}," here is the TypeScript keyword that means \"not a primitive\". It accepts arrays too, which is why its JSON side lists both types.",[919,1526,1528],{"id":1527},"rtformat-named-type-formats","rtFormat: named type formats",[155,1530,1531,1534,1535,1537],{},[334,1532,1533],{"href":39},"Type formats"," give a value a named type with parameters, like an email whose local part has a maximum length. ",[169,1536,994],{}," writes the format name into the schema, and every parameter a standard validator can check rides on a standard keyword, so other validators keep enforcing it:",[938,1539,1540,1550],{},[941,1541,1542],{},[944,1543,1544,1547],{},[947,1545,1546],{},"Format parameter",[947,1548,1549],{},"Standard keyword",[957,1551,1552,1568,1578,1596,1614,1625,1641],{},[944,1553,1554,1562],{},[962,1555,1556,1057,1559],{},[169,1557,1558],{},"minLength",[169,1560,1561],{},"maxLength",[962,1563,1564,1057,1566],{},[169,1565,1558],{},[169,1567,1561],{},[944,1569,1570,1574],{},[962,1571,1572],{},[169,1573,1075],{},[962,1575,1576],{},[169,1577,1075],{},[944,1579,1580,1588],{},[962,1581,1582,1057,1585],{},[169,1583,1584],{},"min",[169,1586,1587],{},"max",[962,1589,1590,1057,1593],{},[169,1591,1592],{},"minimum",[169,1594,1595],{},"maximum",[944,1597,1598,1606],{},[962,1599,1600,1057,1603],{},[169,1601,1602],{},"gt",[169,1604,1605],{},"lt",[962,1607,1608,1057,1611],{},[169,1609,1610],{},"exclusiveMinimum",[169,1612,1613],{},"exclusiveMaximum",[944,1615,1616,1621],{},[962,1617,1618],{},[169,1619,1620],{},"multipleOf",[962,1622,1623],{},[169,1624,1620],{},[944,1626,1627,1638],{},[962,1628,1629,1057,1632,1057,1635],{},[169,1630,1631],{},"minItems",[169,1633,1634],{},"maxItems",[169,1636,1637],{},"uniqueItems",[962,1639,1640],{},"the same names",[944,1642,1643,1651],{},[962,1644,1645,1057,1648],{},[169,1646,1647],{},"minProperties",[169,1649,1650],{},"maxProperties",[962,1652,1640],{},[155,1654,1655,1657,1658,1661],{},[169,1656,1008],{}," carries the full parameter set exactly as written, so the format type can be rebuilt without loss. That matters for parameters the standard has no keyword for: bigint bounds travel as digit strings, and parameters like mock samples or ",[169,1659,1660],{},"trim"," describe no validation at all, so no standard keyword can carry them.",[178,1663,1665],{"className":832,"code":1664,"language":834,"meta":183,"style":183},"{\n  \"type\": \"string\",\n  \"format\": \"email\",\n  \"rtFormat\": \"email\",\n  \"rtFormatParams\": {\"localPart\": {\"maxLength\": 64}}\n}\n",[169,1666,1667,1672,1692,1711,1729,1767],{"__ignoreMap":183},[187,1668,1669],{"class":189,"line":190},[187,1670,1671],{"class":220},"{\n",[187,1673,1674,1677,1679,1681,1683,1685,1687,1689],{"class":189,"line":197},[187,1675,1676],{"class":220},"  \"",[187,1678,846],{"class":212},[187,1680,843],{"class":220},[187,1682,349],{"class":220},[187,1684,853],{"class":220},[187,1686,773],{"class":468},[187,1688,843],{"class":220},[187,1690,1691],{"class":220},",\n",[187,1693,1694,1696,1698,1700,1702,1704,1707,1709],{"class":189,"line":203},[187,1695,1676],{"class":220},[187,1697,865],{"class":212},[187,1699,843],{"class":220},[187,1701,349],{"class":220},[187,1703,853],{"class":220},[187,1705,1706],{"class":468},"email",[187,1708,843],{"class":220},[187,1710,1691],{"class":220},[187,1712,1713,1715,1717,1719,1721,1723,1725,1727],{"class":189,"line":209},[187,1714,1676],{"class":220},[187,1716,994],{"class":212},[187,1718,843],{"class":220},[187,1720,349],{"class":220},[187,1722,853],{"class":220},[187,1724,1706],{"class":468},[187,1726,843],{"class":220},[187,1728,1691],{"class":220},[187,1730,1731,1733,1735,1737,1739,1741,1743,1746,1748,1750,1752,1754,1757,1759,1761,1764],{"class":189,"line":244},[187,1732,1676],{"class":220},[187,1734,1008],{"class":212},[187,1736,843],{"class":220},[187,1738,349],{"class":220},[187,1740,383],{"class":220},[187,1742,843],{"class":220},[187,1744,1745],{"class":231},"localPart",[187,1747,843],{"class":220},[187,1749,349],{"class":220},[187,1751,383],{"class":220},[187,1753,843],{"class":220},[187,1755,1561],{"class":1756},"sbssI",[187,1758,843],{"class":220},[187,1760,349],{"class":220},[187,1762,1763],{"class":1756}," 64",[187,1765,1766],{"class":220},"}}\n",[187,1768,1769],{"class":189,"line":251},[187,1770,896],{"class":220},[155,1772,1773],{},"A standard validator checks the email format. A RunTypes reader also recovers the exact format type, bounded local part included.",[919,1775,1777],{"id":1776},"ts-keywords-typescript-only-facts","ts keywords: TypeScript-only facts",[155,1779,1780,1781,1783,1784,1786],{},"Some TypeScript facts leave no trace in JSON. A readonly modifier, a tuple slot name or a function signature does not change a single byte on the wire. The ",[169,1782,182],{}," keywords record those facts so a schema still describes the exact type it came from. They check nothing: strip every keyword that starts with ",[169,1785,182],{}," and every validator still accepts and rejects exactly the same values.",[1118,1788,1790],{"id":1789},"tslabels-tuple-slot-names","tsLabels: tuple slot names",[178,1792,1794],{"className":832,"code":1793,"language":834,"meta":183,"style":183},"{\n  \"type\": \"array\",\n  \"prefixItems\": [{\"type\": \"number\"}, {\"type\": \"number\"}],\n  \"minItems\": 2,\n  \"items\": false,\n  \"tsLabels\": [\"x\", \"y\"]\n}\n",[169,1795,1796,1800,1819,1869,1884,1897,1929],{"__ignoreMap":183},[187,1797,1798],{"class":189,"line":190},[187,1799,1671],{"class":220},[187,1801,1802,1804,1806,1808,1810,1812,1815,1817],{"class":189,"line":197},[187,1803,1676],{"class":220},[187,1805,846],{"class":212},[187,1807,843],{"class":220},[187,1809,349],{"class":220},[187,1811,853],{"class":220},[187,1813,1814],{"class":468},"array",[187,1816,843],{"class":220},[187,1818,1691],{"class":220},[187,1820,1821,1823,1825,1827,1829,1832,1834,1836,1838,1840,1842,1845,1847,1850,1852,1854,1856,1858,1860,1862,1864,1866],{"class":189,"line":203},[187,1822,1676],{"class":220},[187,1824,1026],{"class":212},[187,1826,843],{"class":220},[187,1828,349],{"class":220},[187,1830,1831],{"class":220}," [{",[187,1833,843],{"class":220},[187,1835,846],{"class":231},[187,1837,843],{"class":220},[187,1839,349],{"class":220},[187,1841,853],{"class":220},[187,1843,1844],{"class":468},"number",[187,1846,843],{"class":220},[187,1848,1849],{"class":220},"},",[187,1851,383],{"class":220},[187,1853,843],{"class":220},[187,1855,846],{"class":231},[187,1857,843],{"class":220},[187,1859,349],{"class":220},[187,1861,853],{"class":220},[187,1863,1844],{"class":468},[187,1865,843],{"class":220},[187,1867,1868],{"class":220},"}],\n",[187,1870,1871,1873,1875,1877,1879,1882],{"class":189,"line":209},[187,1872,1676],{"class":220},[187,1874,1631],{"class":212},[187,1876,843],{"class":220},[187,1878,349],{"class":220},[187,1880,1881],{"class":1756}," 2",[187,1883,1691],{"class":220},[187,1885,1886,1888,1890,1892,1894],{"class":189,"line":244},[187,1887,1676],{"class":220},[187,1889,1373],{"class":212},[187,1891,843],{"class":220},[187,1893,349],{"class":220},[187,1895,1896],{"class":220}," false,\n",[187,1898,1899,1901,1903,1905,1907,1910,1912,1915,1917,1919,1921,1924,1926],{"class":189,"line":251},[187,1900,1676],{"class":220},[187,1902,1021],{"class":212},[187,1904,843],{"class":220},[187,1906,349],{"class":220},[187,1908,1909],{"class":220}," [",[187,1911,843],{"class":220},[187,1913,1914],{"class":468},"x",[187,1916,843],{"class":220},[187,1918,860],{"class":220},[187,1920,853],{"class":220},[187,1922,1923],{"class":468},"y",[187,1925,843],{"class":220},[187,1927,1928],{"class":220},"]\n",[187,1930,1931],{"class":189,"line":261},[187,1932,896],{"class":220},[155,1934,1935,1936,1939],{},"Decodes to ",[169,1937,1938],{},"[x: number, y: number]",". The list names every slot in order, the rest slot included; a list that does not cover every slot is ignored whole.",[1118,1941,1943],{"id":1942},"tsreadonly-readonly-members","tsReadonly: readonly members",[178,1945,1947],{"className":832,"code":1946,"language":834,"meta":183,"style":183},"{\n  \"type\": \"object\",\n  \"properties\": {\"id\": {\"type\": \"string\"}, \"hits\": {\"type\": \"number\"}},\n  \"required\": [\"id\", \"hits\"],\n  \"tsReadonly\": [\"id\"]\n}\n",[169,1948,1949,1953,1971,2038,2067,2087],{"__ignoreMap":183},[187,1950,1951],{"class":189,"line":190},[187,1952,1671],{"class":220},[187,1954,1955,1957,1959,1961,1963,1965,1967,1969],{"class":189,"line":197},[187,1956,1676],{"class":220},[187,1958,846],{"class":212},[187,1960,843],{"class":220},[187,1962,349],{"class":220},[187,1964,853],{"class":220},[187,1966,1511],{"class":468},[187,1968,843],{"class":220},[187,1970,1691],{"class":220},[187,1972,1973,1975,1978,1980,1982,1984,1986,1988,1990,1992,1994,1996,1998,2000,2002,2004,2006,2008,2010,2012,2015,2017,2019,2021,2023,2025,2027,2029,2031,2033,2035],{"class":189,"line":203},[187,1974,1676],{"class":220},[187,1976,1977],{"class":212},"properties",[187,1979,843],{"class":220},[187,1981,349],{"class":220},[187,1983,383],{"class":220},[187,1985,843],{"class":220},[187,1987,633],{"class":231},[187,1989,843],{"class":220},[187,1991,349],{"class":220},[187,1993,383],{"class":220},[187,1995,843],{"class":220},[187,1997,846],{"class":1756},[187,1999,843],{"class":220},[187,2001,349],{"class":220},[187,2003,853],{"class":220},[187,2005,773],{"class":468},[187,2007,843],{"class":220},[187,2009,1849],{"class":220},[187,2011,853],{"class":220},[187,2013,2014],{"class":231},"hits",[187,2016,843],{"class":220},[187,2018,349],{"class":220},[187,2020,383],{"class":220},[187,2022,843],{"class":220},[187,2024,846],{"class":1756},[187,2026,843],{"class":220},[187,2028,349],{"class":220},[187,2030,853],{"class":220},[187,2032,1844],{"class":468},[187,2034,843],{"class":220},[187,2036,2037],{"class":220},"}},\n",[187,2039,2040,2042,2044,2046,2048,2050,2052,2054,2056,2058,2060,2062,2064],{"class":189,"line":209},[187,2041,1676],{"class":220},[187,2043,1041],{"class":212},[187,2045,843],{"class":220},[187,2047,349],{"class":220},[187,2049,1909],{"class":220},[187,2051,843],{"class":220},[187,2053,633],{"class":468},[187,2055,843],{"class":220},[187,2057,860],{"class":220},[187,2059,853],{"class":220},[187,2061,2014],{"class":468},[187,2063,843],{"class":220},[187,2065,2066],{"class":220},"],\n",[187,2068,2069,2071,2073,2075,2077,2079,2081,2083,2085],{"class":189,"line":244},[187,2070,1676],{"class":220},[187,2072,1036],{"class":212},[187,2074,843],{"class":220},[187,2076,349],{"class":220},[187,2078,1909],{"class":220},[187,2080,843],{"class":220},[187,2082,633],{"class":468},[187,2084,843],{"class":220},[187,2086,1928],{"class":220},[187,2088,2089],{"class":189,"line":251},[187,2090,896],{"class":220},[155,2092,1935,2093,2096,2097,2100],{},[169,2094,2095],{},"{readonly id: string; hits: number}",". This is not the standard ",[169,2098,2099],{},"readOnly"," keyword, which is an annotation about write access to a resource; the two can appear together and mean different things.",[1118,2102,2104],{"id":2103},"tsindexes-index-signatures-beyond-string-keys","tsIndexes: index signatures beyond string keys",[178,2106,2108],{"className":832,"code":2107,"language":834,"meta":183,"style":183},"{\n  \"type\": \"object\",\n  \"propertyNames\": {\"pattern\": \"^(?:0|[1-9][0-9]*)$\"},\n  \"tsIndexes\": [{\"key\": {\"type\": \"number\"}, \"value\": {\"type\": \"string\"}}]\n}\n",[169,2109,2110,2114,2132,2162,2229],{"__ignoreMap":183},[187,2111,2112],{"class":189,"line":190},[187,2113,1671],{"class":220},[187,2115,2116,2118,2120,2122,2124,2126,2128,2130],{"class":189,"line":197},[187,2117,1676],{"class":220},[187,2119,846],{"class":212},[187,2121,843],{"class":220},[187,2123,349],{"class":220},[187,2125,853],{"class":220},[187,2127,1511],{"class":468},[187,2129,843],{"class":220},[187,2131,1691],{"class":220},[187,2133,2134,2136,2138,2140,2142,2144,2146,2148,2150,2152,2154,2157,2159],{"class":189,"line":203},[187,2135,1676],{"class":220},[187,2137,1056],{"class":212},[187,2139,843],{"class":220},[187,2141,349],{"class":220},[187,2143,383],{"class":220},[187,2145,843],{"class":220},[187,2147,1075],{"class":231},[187,2149,843],{"class":220},[187,2151,349],{"class":220},[187,2153,853],{"class":220},[187,2155,2156],{"class":468},"^(?:0|[1-9][0-9]*)$",[187,2158,843],{"class":220},[187,2160,2161],{"class":220},"},\n",[187,2163,2164,2166,2168,2170,2172,2174,2176,2179,2181,2183,2185,2187,2189,2191,2193,2195,2197,2199,2201,2203,2206,2208,2210,2212,2214,2216,2218,2220,2222,2224,2226],{"class":189,"line":209},[187,2165,1676],{"class":220},[187,2167,1051],{"class":212},[187,2169,843],{"class":220},[187,2171,349],{"class":220},[187,2173,1831],{"class":220},[187,2175,843],{"class":220},[187,2177,2178],{"class":231},"key",[187,2180,843],{"class":220},[187,2182,349],{"class":220},[187,2184,383],{"class":220},[187,2186,843],{"class":220},[187,2188,846],{"class":1756},[187,2190,843],{"class":220},[187,2192,349],{"class":220},[187,2194,853],{"class":220},[187,2196,1844],{"class":468},[187,2198,843],{"class":220},[187,2200,1849],{"class":220},[187,2202,853],{"class":220},[187,2204,2205],{"class":231},"value",[187,2207,843],{"class":220},[187,2209,349],{"class":220},[187,2211,383],{"class":220},[187,2213,843],{"class":220},[187,2215,846],{"class":1756},[187,2217,843],{"class":220},[187,2219,349],{"class":220},[187,2221,853],{"class":220},[187,2223,773],{"class":468},[187,2225,843],{"class":220},[187,2227,2228],{"class":220},"}}]\n",[187,2230,2231],{"class":189,"line":244},[187,2232,896],{"class":220},[155,2234,1935,2235,2238,2239,2241,2242,2244,2245,759,2247,2249],{},[169,2236,2237],{},"{[key: number]: string}",". JSON object keys are always strings, so ",[169,2240,538],{}," already covers the plain string-key signature. ",[169,2243,1051],{}," covers the rest: numeric keys, template literal keys, and shapes with more than one signature. The JSON side of the constraint still rides ",[169,2246,1056],{},[169,2248,1060],{},", so other validators check the keys too.",[1118,2251,2253],{"id":2252},"tstemplate-template-literal-types","tsTemplate: template literal types",[178,2255,2257],{"className":832,"code":2256,"language":834,"meta":183,"style":183},"{\n  \"type\": \"string\",\n  \"pattern\": \"^api\u002F[\\\\s\\\\S]*\u002Fv[\\\\s\\\\S]*$\",\n  \"tsTemplate\": {\n    \"texts\": [\"api\u002F\", \"\u002Fv\", \"\"],\n    \"placeholders\": [{\"type\": \"string\"}, {\"type\": \"number\"}]\n  }\n}\n",[169,2258,2259,2263,2281,2320,2333,2370,2418,2423],{"__ignoreMap":183},[187,2260,2261],{"class":189,"line":190},[187,2262,1671],{"class":220},[187,2264,2265,2267,2269,2271,2273,2275,2277,2279],{"class":189,"line":197},[187,2266,1676],{"class":220},[187,2268,846],{"class":212},[187,2270,843],{"class":220},[187,2272,349],{"class":220},[187,2274,853],{"class":220},[187,2276,773],{"class":468},[187,2278,843],{"class":220},[187,2280,1691],{"class":220},[187,2282,2283,2285,2287,2289,2291,2293,2296,2299,2302,2304,2307,2309,2311,2313,2316,2318],{"class":189,"line":203},[187,2284,1676],{"class":220},[187,2286,1075],{"class":212},[187,2288,843],{"class":220},[187,2290,349],{"class":220},[187,2292,853],{"class":220},[187,2294,2295],{"class":468},"^api\u002F[",[187,2297,2298],{"class":216},"\\\\",[187,2300,2301],{"class":468},"s",[187,2303,2298],{"class":216},[187,2305,2306],{"class":468},"S]*\u002Fv[",[187,2308,2298],{"class":216},[187,2310,2301],{"class":468},[187,2312,2298],{"class":216},[187,2314,2315],{"class":468},"S]*$",[187,2317,843],{"class":220},[187,2319,1691],{"class":220},[187,2321,2322,2324,2326,2328,2330],{"class":189,"line":209},[187,2323,1676],{"class":220},[187,2325,1070],{"class":212},[187,2327,843],{"class":220},[187,2329,349],{"class":220},[187,2331,2332],{"class":220}," {\n",[187,2334,2335,2338,2341,2343,2345,2347,2349,2352,2354,2356,2358,2361,2363,2365,2368],{"class":189,"line":244},[187,2336,2337],{"class":220},"    \"",[187,2339,2340],{"class":231},"texts",[187,2342,843],{"class":220},[187,2344,349],{"class":220},[187,2346,1909],{"class":220},[187,2348,843],{"class":220},[187,2350,2351],{"class":468},"api\u002F",[187,2353,843],{"class":220},[187,2355,860],{"class":220},[187,2357,853],{"class":220},[187,2359,2360],{"class":468},"\u002Fv",[187,2362,843],{"class":220},[187,2364,860],{"class":220},[187,2366,2367],{"class":220}," \"\"",[187,2369,2066],{"class":220},[187,2371,2372,2374,2377,2379,2381,2383,2385,2387,2389,2391,2393,2395,2397,2399,2401,2403,2405,2407,2409,2411,2413,2415],{"class":189,"line":251},[187,2373,2337],{"class":220},[187,2375,2376],{"class":231},"placeholders",[187,2378,843],{"class":220},[187,2380,349],{"class":220},[187,2382,1831],{"class":220},[187,2384,843],{"class":220},[187,2386,846],{"class":1756},[187,2388,843],{"class":220},[187,2390,349],{"class":220},[187,2392,853],{"class":220},[187,2394,773],{"class":468},[187,2396,843],{"class":220},[187,2398,1849],{"class":220},[187,2400,383],{"class":220},[187,2402,843],{"class":220},[187,2404,846],{"class":1756},[187,2406,843],{"class":220},[187,2408,349],{"class":220},[187,2410,853],{"class":220},[187,2412,1844],{"class":468},[187,2414,843],{"class":220},[187,2416,2417],{"class":220},"}]\n",[187,2419,2420],{"class":189,"line":261},[187,2421,2422],{"class":220},"  }\n",[187,2424,2425],{"class":189,"line":267},[187,2426,896],{"class":220},[155,2428,1935,2429,2432,2433,2435],{},[169,2430,2431],{},"`api\u002F${string}\u002Fv${number}`",". The pattern beside it lets any validator check the fixed parts of the string; the parts under ",[169,2434,1070],{}," let a RunTypes reader rebuild the exact type, which a pattern alone can not do.",[1118,2437,2439],{"id":2438},"tsfunction-function-signatures","tsFunction: function signatures",[178,2441,2443],{"className":832,"code":2442,"language":834,"meta":183,"style":183},"{\n  \"tsFunction\": {\n    \"params\": {\n      \"type\": \"array\",\n      \"prefixItems\": [{\"type\": \"string\"}],\n      \"minItems\": 1,\n      \"items\": false,\n      \"tsLabels\": [\"message\"]\n    },\n    \"return\": {\"type\": \"boolean\"}\n  }\n}\n",[169,2444,2445,2449,2461,2474,2493,2521,2536,2548,2569,2574,2604,2608],{"__ignoreMap":183},[187,2446,2447],{"class":189,"line":190},[187,2448,1671],{"class":220},[187,2450,2451,2453,2455,2457,2459],{"class":189,"line":197},[187,2452,1676],{"class":220},[187,2454,1085],{"class":212},[187,2456,843],{"class":220},[187,2458,349],{"class":220},[187,2460,2332],{"class":220},[187,2462,2463,2465,2468,2470,2472],{"class":189,"line":203},[187,2464,2337],{"class":220},[187,2466,2467],{"class":231},"params",[187,2469,843],{"class":220},[187,2471,349],{"class":220},[187,2473,2332],{"class":220},[187,2475,2476,2479,2481,2483,2485,2487,2489,2491],{"class":189,"line":209},[187,2477,2478],{"class":220},"      \"",[187,2480,846],{"class":1756},[187,2482,843],{"class":220},[187,2484,349],{"class":220},[187,2486,853],{"class":220},[187,2488,1814],{"class":468},[187,2490,843],{"class":220},[187,2492,1691],{"class":220},[187,2494,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513,2515,2517,2519],{"class":189,"line":244},[187,2496,2478],{"class":220},[187,2498,1026],{"class":1756},[187,2500,843],{"class":220},[187,2502,349],{"class":220},[187,2504,1831],{"class":220},[187,2506,843],{"class":220},[187,2508,846],{"class":377},[187,2510,843],{"class":220},[187,2512,349],{"class":220},[187,2514,853],{"class":220},[187,2516,773],{"class":468},[187,2518,843],{"class":220},[187,2520,1868],{"class":220},[187,2522,2523,2525,2527,2529,2531,2534],{"class":189,"line":251},[187,2524,2478],{"class":220},[187,2526,1631],{"class":1756},[187,2528,843],{"class":220},[187,2530,349],{"class":220},[187,2532,2533],{"class":1756}," 1",[187,2535,1691],{"class":220},[187,2537,2538,2540,2542,2544,2546],{"class":189,"line":261},[187,2539,2478],{"class":220},[187,2541,1373],{"class":1756},[187,2543,843],{"class":220},[187,2545,349],{"class":220},[187,2547,1896],{"class":220},[187,2549,2550,2552,2554,2556,2558,2560,2562,2565,2567],{"class":189,"line":267},[187,2551,2478],{"class":220},[187,2553,1021],{"class":1756},[187,2555,843],{"class":220},[187,2557,349],{"class":220},[187,2559,1909],{"class":220},[187,2561,843],{"class":220},[187,2563,2564],{"class":468},"message",[187,2566,843],{"class":220},[187,2568,1928],{"class":220},[187,2570,2571],{"class":189,"line":273},[187,2572,2573],{"class":220},"    },\n",[187,2575,2576,2578,2581,2583,2585,2587,2589,2591,2593,2595,2597,2600,2602],{"class":189,"line":279},[187,2577,2337],{"class":220},[187,2579,2580],{"class":231},"return",[187,2582,843],{"class":220},[187,2584,349],{"class":220},[187,2586,383],{"class":220},[187,2588,843],{"class":220},[187,2590,846],{"class":1756},[187,2592,843],{"class":220},[187,2594,349],{"class":220},[187,2596,853],{"class":220},[187,2598,2599],{"class":468},"boolean",[187,2601,843],{"class":220},[187,2603,896],{"class":220},[187,2605,2606],{"class":189,"line":285},[187,2607,2422],{"class":220},[187,2609,2610],{"class":189,"line":291},[187,2611,896],{"class":220},[155,2613,1935,2614,2617],{},[169,2615,2616],{},"(message: string) => boolean",". A function has no JSON form, so there are no standard keywords beside it. The parameters are written as an ordinary tuple schema, which is how optional parameters, rest parameters and parameter names all come for free.",[1118,2619,2621],{"id":2620},"tsmeta-branded-and-metadata-types","tsMeta: branded and metadata types",[178,2623,2625],{"className":832,"code":2624,"language":834,"meta":183,"style":183},"{\n  \"tsMeta\": {\n    \"base\": {\"type\": \"string\"},\n    \"meta\": [{\n      \"type\": \"object\",\n      \"properties\": {\"__brand\": {\"const\": \"UserId\"}},\n      \"required\": [\"__brand\"],\n      \"tsReadonly\": [\"__brand\"]\n    }]\n  }\n}\n",[169,2626,2627,2631,2643,2672,2686,2704,2745,2765,2785,2790,2794],{"__ignoreMap":183},[187,2628,2629],{"class":189,"line":190},[187,2630,1671],{"class":220},[187,2632,2633,2635,2637,2639,2641],{"class":189,"line":197},[187,2634,1676],{"class":220},[187,2636,1098],{"class":212},[187,2638,843],{"class":220},[187,2640,349],{"class":220},[187,2642,2332],{"class":220},[187,2644,2645,2647,2650,2652,2654,2656,2658,2660,2662,2664,2666,2668,2670],{"class":189,"line":203},[187,2646,2337],{"class":220},[187,2648,2649],{"class":231},"base",[187,2651,843],{"class":220},[187,2653,349],{"class":220},[187,2655,383],{"class":220},[187,2657,843],{"class":220},[187,2659,846],{"class":1756},[187,2661,843],{"class":220},[187,2663,349],{"class":220},[187,2665,853],{"class":220},[187,2667,773],{"class":468},[187,2669,843],{"class":220},[187,2671,2161],{"class":220},[187,2673,2674,2676,2679,2681,2683],{"class":189,"line":209},[187,2675,2337],{"class":220},[187,2677,2678],{"class":231},"meta",[187,2680,843],{"class":220},[187,2682,349],{"class":220},[187,2684,2685],{"class":220}," [{\n",[187,2687,2688,2690,2692,2694,2696,2698,2700,2702],{"class":189,"line":244},[187,2689,2478],{"class":220},[187,2691,846],{"class":1756},[187,2693,843],{"class":220},[187,2695,349],{"class":220},[187,2697,853],{"class":220},[187,2699,1511],{"class":468},[187,2701,843],{"class":220},[187,2703,1691],{"class":220},[187,2705,2706,2708,2710,2712,2714,2716,2718,2721,2723,2725,2727,2729,2732,2734,2736,2738,2741,2743],{"class":189,"line":251},[187,2707,2478],{"class":220},[187,2709,1977],{"class":1756},[187,2711,843],{"class":220},[187,2713,349],{"class":220},[187,2715,383],{"class":220},[187,2717,843],{"class":220},[187,2719,2720],{"class":377},"__brand",[187,2722,843],{"class":220},[187,2724,349],{"class":220},[187,2726,383],{"class":220},[187,2728,843],{"class":220},[187,2730,213],{"class":2731},"su27w",[187,2733,843],{"class":220},[187,2735,349],{"class":220},[187,2737,853],{"class":220},[187,2739,2740],{"class":468},"UserId",[187,2742,843],{"class":220},[187,2744,2037],{"class":220},[187,2746,2747,2749,2751,2753,2755,2757,2759,2761,2763],{"class":189,"line":261},[187,2748,2478],{"class":220},[187,2750,1041],{"class":1756},[187,2752,843],{"class":220},[187,2754,349],{"class":220},[187,2756,1909],{"class":220},[187,2758,843],{"class":220},[187,2760,2720],{"class":468},[187,2762,843],{"class":220},[187,2764,2066],{"class":220},[187,2766,2767,2769,2771,2773,2775,2777,2779,2781,2783],{"class":189,"line":267},[187,2768,2478],{"class":220},[187,2770,1036],{"class":1756},[187,2772,843],{"class":220},[187,2774,349],{"class":220},[187,2776,1909],{"class":220},[187,2778,843],{"class":220},[187,2780,2720],{"class":468},[187,2782,843],{"class":220},[187,2784,1928],{"class":220},[187,2786,2787],{"class":189,"line":273},[187,2788,2789],{"class":220},"    }]\n",[187,2791,2792],{"class":189,"line":279},[187,2793,2422],{"class":220},[187,2795,2796],{"class":189,"line":285},[187,2797,896],{"class":220},[155,2799,1935,2800,2803],{},[169,2801,2802],{},"string & {readonly __brand: 'UserId'}",", the usual way a branded type is written. Only the base describes JSON that actually travels; the metadata half exists in the type and never in the data.",[919,2805,2807],{"id":2806},"how-the-pieces-stack","How the pieces stack",[155,2809,2810,2811,2814,2815,2818],{},"A schema node can carry several of these keywords at once, next to the standard ones. The rule is simple: the standard keywords always describe the JSON that travels, and the extension keyword decides the type that comes back. In the opening example, ",[169,2812,2813],{},"format: 'date-time'"," describes the string on the wire and ",[169,2816,2817],{},"jsType: 'Date'"," decides that the decoded value is a Date.",[155,2820,2821,2822,2825,2826,2829],{},"A schema may declare the dialect with ",[169,2823,2824],{},"$schema"," set to ",[169,2827,2828],{},"https:\u002F\u002Fruntypes.pages.dev\u002Fschema\u002F2020-12-javascript",", but it does not have to. Other validators ignore the keywords either way, so the declaration is a hint for tooling, not a requirement.",[155,2831,2832,2833,623],{},"The formal version of the extension, one precise rule per keyword, lives in the repository at ",[334,2834,2837],{"href":2835,"rel":2836},"https:\u002F\u002Fgithub.com\u002FMionKit\u002Fts-run-types\u002Fblob\u002Fmain\u002Fdocs\u002Fjson-schema-2020-12-javascript.md",[554],"json-schema-2020-12-javascript.md",[2839,2840,2841],"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 .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .su27w, html code.shiki .su27w{--shiki-light:#916B53;--shiki-default:#916B53;--shiki-dark:#916B53}","JSON Schema documents generated from your types at build time.","md",null,{"toc":26},{"title":78,"description":2842},"E5BsA9g4y3pL8oLXeQ_Zc7khsA3hORgy50EICU7wV44",[2849,2851],{"title":74,"path":75,"stem":76,"description":2850,"children":-1},"Rewrite files between plain types and type builders with one command.",{"title":89,"path":84,"stem":90,"description":2852,"children":-1},"How AI agents and the compiler work together to enrich your types.",1787523491133]