[{"data":1,"prerenderedAt":897},["ShallowReactive",2],{"navigation_docs":3,"-introduction-about-ts-runtypes":127,"-introduction-about-ts-runtypes-surround":894},[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":12,"body":129,"description":888,"extension":889,"links":890,"meta":891,"navigation":300,"path":7,"seo":892,"stem":13,"__hash__":893},"docs\u002F1.introduction\u002F1.about-ts-runtypes.md",{"type":130,"value":131},"minimark",[132,141,148,153,179,190,197,490,494,505,684,687,715,719,734,749,760,764,767,787,791,794,809,827,831,841,873,884],[133,134,135,136,140],"p",{},"TypeScript decided it's \"just a linter\" and throws your types away before your code ever runs. ",[137,138,139],"strong",{},"RunTypes"," reads them first, at build time, and hands the runtime back what it lost: validators, JSON + binary (de)serializers, mock data and reflection.",[133,142,143,144,147],{},"Plenty of libraries generate runtime checks. This page isn't a feature tour. It's the handful of ",[137,145,146],{},"design decisions"," that make RunTypes what it is.",[149,150,152],"h2",{"id":151},"driven-by-typescript-nothing-else","Driven by TypeScript, nothing else",[133,154,155,156,160,161,165,166,165,169,165,172,165,175,178],{},"The runtime model is exactly what the TypeScript type system can express, no more and no less. The goal is to support the ",[157,158,159],"em",{},"whole"," type system: atomics, objects, arrays, tuples, unions, intersections, template literals, generics, the utility types, ",[162,163,164],"code",{},"Map","\u002F",[162,167,168],{},"Set",[162,170,171],{},"Promise",[162,173,174],{},"Date",[162,176,177],{},"Temporal",", recursive and circular shapes.",[133,180,181,182,185,186,189],{},"The flip side is just as deliberate: ",[137,183,184],{},"if something isn't part of TypeScript's type system, it's out of scope by design."," We don't invent a parallel \"schema dialect\" with concepts TypeScript doesn't have. Your types ",[157,187,188],{},"are"," the schema. There's no second language to learn and nothing to keep in sync.",[133,191,192,193,196],{},"That principle is why the two ways to describe a shape are really one. A plain type and an ",[162,194,195],{},"RT.*"," schema builder are two doors into the same engine. They resolve to the identical structural representation:",[198,199,202,333],"div",{"className":200},[201],"rt-define-cols",[203,204,205],"code-group",{},[206,207,213],"pre",{"className":208,"code":209,"filename":210,"language":211,"meta":212,"style":212},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F packages\u002Fexamples\u002Fsrc\u002Fintroduction\u002Fwhatis-duality.ts\n\u002F\u002F Option A — a plain TypeScript type. Fastest, zero ceremony.\ntype UserFromType = {\n  id: number;\n  name: string;\n  email: string;\n};\n\nconst isUserA = createValidate\u003CUserFromType>();\n","Type Definition","ts","",[162,214,215,224,230,248,264,277,289,295,302],{"__ignoreMap":212},[216,217,220],"span",{"class":218,"line":219},"line",1,[216,221,223],{"class":222},"sHwdD","\u002F\u002F packages\u002Fexamples\u002Fsrc\u002Fintroduction\u002Fwhatis-duality.ts\n",[216,225,227],{"class":218,"line":226},2,[216,228,229],{"class":222},"\u002F\u002F Option A — a plain TypeScript type. Fastest, zero ceremony.\n",[216,231,233,237,241,245],{"class":218,"line":232},3,[216,234,236],{"class":235},"spNyl","type",[216,238,240],{"class":239},"sBMFI"," UserFromType",[216,242,244],{"class":243},"sMK4o"," =",[216,246,247],{"class":243}," {\n",[216,249,251,255,258,261],{"class":218,"line":250},4,[216,252,254],{"class":253},"swJcz","  id",[216,256,257],{"class":243},":",[216,259,260],{"class":239}," number",[216,262,263],{"class":243},";\n",[216,265,267,270,272,275],{"class":218,"line":266},5,[216,268,269],{"class":253},"  name",[216,271,257],{"class":243},[216,273,274],{"class":239}," string",[216,276,263],{"class":243},[216,278,280,283,285,287],{"class":218,"line":279},6,[216,281,282],{"class":253},"  email",[216,284,257],{"class":243},[216,286,274],{"class":239},[216,288,263],{"class":243},[216,290,292],{"class":218,"line":291},7,[216,293,294],{"class":243},"};\n",[216,296,298],{"class":218,"line":297},8,[216,299,301],{"emptyLinePlaceholder":300},true,"\n",[216,303,305,308,312,315,319,322,325,328,331],{"class":218,"line":304},9,[216,306,307],{"class":235},"const",[216,309,311],{"class":310},"sTEyZ"," isUserA ",[216,313,314],{"class":243},"=",[216,316,318],{"class":317},"s2Zo4"," createValidate",[216,320,321],{"class":243},"\u003C",[216,323,324],{"class":239},"UserFromType",[216,326,327],{"class":243},">",[216,329,330],{"class":310},"()",[216,332,263],{"class":243},[203,334,335],{},[206,336,339],{"className":208,"code":337,"filename":338,"language":211,"meta":212,"style":212},"\u002F\u002F packages\u002Fexamples\u002Fsrc\u002Fintroduction\u002Fwhatis-duality.ts\n\u002F\u002F Option B — the RT.* builders, if you like the Zod \u002F TypeBox feel.\nconst userSchema = RT.object({\n  id: TF.number(),\n  name: TF.string(),\n  email: TF.email(),\n});\n\n\u002F\u002F Recover the type from the schema whenever you need it.\ntype UserFromSchema = Static\u003Ctypeof userSchema>;\n\nconst isUserB = createValidate(userSchema);\n","Schema",[162,340,341,345,350,374,393,410,427,437,441,446,468,473],{"__ignoreMap":212},[216,342,343],{"class":218,"line":219},[216,344,223],{"class":222},[216,346,347],{"class":218,"line":226},[216,348,349],{"class":222},"\u002F\u002F Option B — the RT.* builders, if you like the Zod \u002F TypeBox feel.\n",[216,351,352,354,357,359,362,365,368,371],{"class":218,"line":232},[216,353,307],{"class":235},[216,355,356],{"class":310}," userSchema ",[216,358,314],{"class":243},[216,360,361],{"class":310}," RT",[216,363,364],{"class":243},".",[216,366,367],{"class":317},"object",[216,369,370],{"class":310},"(",[216,372,373],{"class":243},"{\n",[216,375,376,378,380,383,385,388,390],{"class":218,"line":250},[216,377,254],{"class":253},[216,379,257],{"class":243},[216,381,382],{"class":310}," TF",[216,384,364],{"class":243},[216,386,387],{"class":317},"number",[216,389,330],{"class":310},[216,391,392],{"class":243},",\n",[216,394,395,397,399,401,403,406,408],{"class":218,"line":266},[216,396,269],{"class":253},[216,398,257],{"class":243},[216,400,382],{"class":310},[216,402,364],{"class":243},[216,404,405],{"class":317},"string",[216,407,330],{"class":310},[216,409,392],{"class":243},[216,411,412,414,416,418,420,423,425],{"class":218,"line":279},[216,413,282],{"class":253},[216,415,257],{"class":243},[216,417,382],{"class":310},[216,419,364],{"class":243},[216,421,422],{"class":317},"email",[216,424,330],{"class":310},[216,426,392],{"class":243},[216,428,429,432,435],{"class":218,"line":291},[216,430,431],{"class":243},"}",[216,433,434],{"class":310},")",[216,436,263],{"class":243},[216,438,439],{"class":218,"line":297},[216,440,301],{"emptyLinePlaceholder":300},[216,442,443],{"class":218,"line":304},[216,444,445],{"class":222},"\u002F\u002F Recover the type from the schema whenever you need it.\n",[216,447,449,451,454,456,459,462,465],{"class":218,"line":448},10,[216,450,236],{"class":235},[216,452,453],{"class":239}," UserFromSchema",[216,455,244],{"class":243},[216,457,458],{"class":239}," Static",[216,460,461],{"class":243},"\u003Ctypeof",[216,463,464],{"class":310}," userSchema",[216,466,467],{"class":243},">;\n",[216,469,471],{"class":218,"line":470},11,[216,472,301],{"emptyLinePlaceholder":300},[216,474,476,478,481,483,485,488],{"class":218,"line":475},12,[216,477,307],{"class":235},[216,479,480],{"class":310}," isUserB ",[216,482,314],{"class":243},[216,484,318],{"class":317},[216,486,487],{"class":310},"(userSchema)",[216,489,263],{"class":243},[149,491,493],{"id":492},"one-type-one-id","One type, one id",[133,495,496,497,500,501,504],{},"Every type collapses to a single, stable ",[137,498,499],{},"structural id"," that stands for its shape. Two types with the same shape resolve to the ",[157,502,503],{},"same"," id, whether you reach the same type two different ways or write two distinct types that happen to look identical. Either way, RunTypes folds them into a single cache entry.",[206,506,508],{"className":208,"code":507,"language":211,"meta":212,"style":212},"\u002F\u002F packages\u002Fexamples\u002Fsrc\u002Fintroduction\u002Fone-type-one-id.ts\nimport {getRunTypeId} from 'ts-runtypes';\n\n\u002F\u002F Two interfaces, different names — but the exact same shape.\ninterface User {\n  id: number;\n  name: string;\n}\n\ninterface Account {\n  id: number;\n  name: string;\n}\n\n\u002F\u002F Same structure resolves to the same structural id — one shared cache entry.\nconsole.log(getRunTypeId\u003CUser>() === getRunTypeId\u003CAccount>()); \u002F\u002F true\n",[162,509,510,515,544,548,553,563,573,583,588,592,601,611,621,626,631,637],{"__ignoreMap":212},[216,511,512],{"class":218,"line":219},[216,513,514],{"class":222},"\u002F\u002F packages\u002Fexamples\u002Fsrc\u002Fintroduction\u002Fone-type-one-id.ts\n",[216,516,517,521,524,527,529,532,535,539,542],{"class":218,"line":226},[216,518,520],{"class":519},"s7zQu","import",[216,522,523],{"class":243}," {",[216,525,526],{"class":310},"getRunTypeId",[216,528,431],{"class":243},[216,530,531],{"class":519}," from",[216,533,534],{"class":243}," '",[216,536,538],{"class":537},"sfazB","ts-runtypes",[216,540,541],{"class":243},"'",[216,543,263],{"class":243},[216,545,546],{"class":218,"line":232},[216,547,301],{"emptyLinePlaceholder":300},[216,549,550],{"class":218,"line":250},[216,551,552],{"class":222},"\u002F\u002F Two interfaces, different names — but the exact same shape.\n",[216,554,555,558,561],{"class":218,"line":266},[216,556,557],{"class":235},"interface",[216,559,560],{"class":239}," User",[216,562,247],{"class":243},[216,564,565,567,569,571],{"class":218,"line":279},[216,566,254],{"class":253},[216,568,257],{"class":243},[216,570,260],{"class":239},[216,572,263],{"class":243},[216,574,575,577,579,581],{"class":218,"line":291},[216,576,269],{"class":253},[216,578,257],{"class":243},[216,580,274],{"class":239},[216,582,263],{"class":243},[216,584,585],{"class":218,"line":297},[216,586,587],{"class":243},"}\n",[216,589,590],{"class":218,"line":304},[216,591,301],{"emptyLinePlaceholder":300},[216,593,594,596,599],{"class":218,"line":448},[216,595,557],{"class":235},[216,597,598],{"class":239}," Account",[216,600,247],{"class":243},[216,602,603,605,607,609],{"class":218,"line":470},[216,604,254],{"class":253},[216,606,257],{"class":243},[216,608,260],{"class":239},[216,610,263],{"class":243},[216,612,613,615,617,619],{"class":218,"line":475},[216,614,269],{"class":253},[216,616,257],{"class":243},[216,618,274],{"class":239},[216,620,263],{"class":243},[216,622,624],{"class":218,"line":623},13,[216,625,587],{"class":243},[216,627,629],{"class":218,"line":628},14,[216,630,301],{"emptyLinePlaceholder":300},[216,632,634],{"class":218,"line":633},15,[216,635,636],{"class":222},"\u002F\u002F Same structure resolves to the same structural id — one shared cache entry.\n",[216,638,640,643,645,648,650,652,654,657,659,662,665,668,670,673,675,678,681],{"class":218,"line":639},16,[216,641,642],{"class":310},"console",[216,644,364],{"class":243},[216,646,647],{"class":317},"log",[216,649,370],{"class":310},[216,651,526],{"class":317},[216,653,321],{"class":243},[216,655,656],{"class":239},"User",[216,658,327],{"class":243},[216,660,661],{"class":310},"() ",[216,663,664],{"class":243},"===",[216,666,667],{"class":317}," getRunTypeId",[216,669,321],{"class":243},[216,671,672],{"class":239},"Account",[216,674,327],{"class":243},[216,676,677],{"class":310},"())",[216,679,680],{"class":243},";",[216,682,683],{"class":222}," \u002F\u002F true\n",[133,685,686],{},"This idempotency is the quiet engine behind everything else:",[688,689,690,697,703,709],"ul",{},[691,692,693,696],"li",{},[137,694,695],{},"One source of truth, no drift."," The validator and the serializer are generated from the same shape, so they can never disagree about what your type means. Change the type, every generated function changes with it.",[691,698,699,702],{},[137,700,701],{},"Stable, reproducible output."," The same type always emits the same id and the same code, build after build.",[691,704,705,708],{},[137,706,707],{},"Ship only what you use."," A function only holds the types your own code actually asks for. A file that just reflects an id ships zero validation code.",[691,710,711,714],{},[137,712,713],{},"Native tree-shaking."," Every cache entry is its own module, so bundlers code-split and drop what you never call. There's no central registry to defeat them.",[149,716,718],{"id":717},"build-time-not-run-time","Build time, not run time",[133,720,721,722,725,726,733],{},"TypeScript 7 ships the compiler as a compiled ",[137,723,724],{},"Go binary",". The legacy custom-transformer hook that runtime-reflection libraries used to plug into (",[727,728,732],"a",{"href":729,"rel":730},"https:\u002F\u002Fgithub.com\u002Fmicrosoft\u002Ftypescript-go\u002Fissues\u002F516",[731],"nofollow","microsoft\u002Ftypescript-go#516",") was never ported, and the compiler can no longer be monkey-patched from Node.",[133,735,736,737,740,741,744,745,748],{},"So RunTypes asks the real TypeScript compiler directly. What we resolve as type ",[162,738,739],{},"T"," is exactly what the compiler resolves. The work older libraries did ",[157,742,743],{},"lazily, at first call"," now happens ahead of time during the build: each ",[162,746,747],{},"createValidate\u003CT>()"," is a specialized function written out for you.",[750,751,752,753,756,757,759],"note",{},"There's no reflection happening when your app is live, and the published Vite plugin carries ",[137,754,755],{},"zero runtime dependencies",". The only thing in your bundle is the small ",[162,758,538],{}," runtime plus the functions you actually called.",[149,761,763],{"id":762},"fast-by-construction","Fast by construction",[133,765,766],{},"The performance comes from the architecture, not micro-tuning:",[688,768,769,775,781],{},[691,770,771,774],{},[137,772,773],{},"A Go compiler underneath."," Type resolution uses the same fast, native view of your code that the TypeScript compiler does.",[691,776,777,780],{},[137,778,779],{},"No first-call cost."," Everything is emitted ahead of time, so there's nothing to compile when your code runs.",[691,782,783,786],{},[137,784,785],{},"Generated code with real source maps",", immutable cached modules, and a compact binary format for the paths where every byte counts.",[149,788,790],{"id":789},"proven-by-its-test-suite","Proven by its test suite",[133,792,793],{},"The port is backed by a deep test suite: a Go suite (70+ test files) and a TypeScript suite (90+ test files) that spawns the real binary and asserts the full round-trip, covering everything from atomic kinds to recursive and circular types.",[133,795,796,797,800,801,804,805,808],{},"A couple of rules keep it honest. Every marker API is tested in ",[137,798,799],{},"both"," call shapes, static ",[162,802,803],{},"getRunTypeId\u003CT>()"," and value-first ",[162,806,807],{},"getRunTypeId(value)",", with an assertion that the two agree. And the optimisation that skips redundant transforms is checked by a dedicated corpus test so it never skips one it shouldn't.",[133,810,811,812,817,818,821,822,826],{},"And you don't have to take our word for it. The ",[727,813,814],{"href":74},[137,815,816],{},"Suites"," on this very site are generated ",[157,819,820],{},"straight from that test suite",": every case, the type it came from, the equivalent schema, and the actual JavaScript the build emits. The ",[727,823,824],{"href":98},[137,825,96],{}," show each competitor's real source, so you can judge the comparison yourself.",[149,828,830],{"id":829},"a-deliberate-contract-serializable-data","A deliberate contract: serializable data",[133,832,833,836,837,840],{},[162,834,835],{},"createValidate",", the JSON codec and the binary codec all operate on the ",[137,838,839],{},"serializable projection"," of your type. Functions, methods and symbol keys are dropped (with a build-time warning), because they don't survive JSON anyway.",[133,842,843,844,849,850,852,853,855,856,858,859,862,863,866,867,872],{},"That projection has a name in the types, too: ",[137,845,846],{},[162,847,848],{},"DataOnly\u003CT>",", a type that strips the non-serializable members from ",[162,851,739],{},". It isn't just a runtime convention. ",[162,854,747],{}," narrows to ",[162,857,848],{},", and ",[162,860,861],{},"createJsonDecoder\u003CT>()"," \u002F ",[162,864,865],{},"createBinaryDecoder\u003CT>()"," ",[137,868,869,870],{},"return ",[162,871,848],{},", so a value that passes validation, or comes back from a decoder, is strongly typed as exactly the data. The dropped methods and functions are gone at compile time, not just at runtime.",[133,874,875,876,879,880,883],{},"That's a design choice, not a shortcoming. It matches how these tools are actually used (RPC, persistence, network IO), and it keeps the cache bound to ",[157,877,878],{},"shapes",", not live JavaScript values, which is exactly the coupling we left ",[162,881,882],{},"tsc"," to escape.",[885,886,887],"style",{},"html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}","The design decisions behind RunTypes and why everything happens at build time.","md",null,{"toc":18},{"title":12,"description":888},"o9C07TfhYxsZCv25ffja2cVWeQRni5w1hym0VHO5ngs",[890,895],{"title":15,"path":16,"stem":17,"description":896,"children":-1},"Install the package + Vite plugin and generate your first validator from a TypeScript type.",1781995977193]