[{"data":1,"prerenderedAt":2859},["ShallowReactive",2],{"navigation_docs":3,"-guide-type-formats":127,"-guide-type-formats-surround":2854},[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":30,"body":129,"description":2848,"extension":2849,"links":2850,"meta":2851,"navigation":243,"path":31,"seo":2852,"stem":32,"__hash__":2853},"docs\u002F2.guide\u002F2.type-formats.md",{"type":130,"value":131},"minimark",[132,137,155,848,851,855,858,1008,1043,1061,1065,1086,1179,1308,1332,1343,1489,1511,1517,1536,1813,1832,1920,1932,1936,1964,2242,2251,2261,2265,2278,2694,2697,2786,2801,2820,2824,2844],[133,134,136],"h2",{"id":135},"two-ways-same-result","Two ways, same result",[138,139,140,141,145,146,150,151,154],"p",{},"Import the format type from the ",[142,143,144],"code",{},"TF"," namespace and annotate, ",[147,148,149],"strong",{},"or"," reach for the matching ",[142,152,153],{},"TF.*"," builder if you like that feel. Either way gives you the same constraints.",[156,157,160,581],"div",{"className":158},[159],"rt-define-cols",[161,162,163],"code-group",{},[164,165,171],"pre",{"className":166,"code":167,"filename":168,"language":169,"meta":170,"style":170},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import type * as TF from 'ts-runtypes\u002Fformats';\nimport {createValidate} from 'ts-runtypes';\n\n\u002F\u002F Type-first formats: import a Format* alias and annotate. The constraint\n\u002F\u002F lives in the type — the build reads it and validates accordingly.\ntype Account = {\n  id: TF.UUIDv4;\n  email: TF.Email;\n  age: TF.Int32;\n  credits: TF.Positive;\n};\n\nconst isAccount = createValidate\u003CAccount>();\n\nisAccount({\n  id: '109156be-c4fb-41ea-b1b4-efe1671c5836',\n  email: 'ada@example.com',\n  age: 36,\n  credits: 100,\n}); \u002F\u002F true\n\nisAccount({id: 'not-a-uuid', email: 'nope', age: 1.5, credits: -5}); \u002F\u002F false\n\nexport {isAccount};\nexport type {Account};\n","Type Definition","ts","",[142,172,173,212,238,245,252,258,275,296,313,330,347,353,358,388,393,405,422,438,451,463,477,482,551,556,568],{"__ignoreMap":170},[174,175,178,182,185,189,192,196,199,202,206,209],"span",{"class":176,"line":177},"line",1,[174,179,181],{"class":180},"s7zQu","import",[174,183,184],{"class":180}," type",[174,186,188],{"class":187},"sMK4o"," *",[174,190,191],{"class":180}," as",[174,193,195],{"class":194},"sTEyZ"," TF ",[174,197,198],{"class":180},"from",[174,200,201],{"class":187}," '",[174,203,205],{"class":204},"sfazB","ts-runtypes\u002Fformats",[174,207,208],{"class":187},"'",[174,210,211],{"class":187},";\n",[174,213,215,217,220,223,226,229,231,234,236],{"class":176,"line":214},2,[174,216,181],{"class":180},[174,218,219],{"class":187}," {",[174,221,222],{"class":194},"createValidate",[174,224,225],{"class":187},"}",[174,227,228],{"class":180}," from",[174,230,201],{"class":187},[174,232,233],{"class":204},"ts-runtypes",[174,235,208],{"class":187},[174,237,211],{"class":187},[174,239,241],{"class":176,"line":240},3,[174,242,244],{"emptyLinePlaceholder":243},true,"\n",[174,246,248],{"class":176,"line":247},4,[174,249,251],{"class":250},"sHwdD","\u002F\u002F Type-first formats: import a Format* alias and annotate. The constraint\n",[174,253,255],{"class":176,"line":254},5,[174,256,257],{"class":250},"\u002F\u002F lives in the type — the build reads it and validates accordingly.\n",[174,259,261,265,269,272],{"class":176,"line":260},6,[174,262,264],{"class":263},"spNyl","type",[174,266,268],{"class":267},"sBMFI"," Account",[174,270,271],{"class":187}," =",[174,273,274],{"class":187}," {\n",[174,276,278,282,285,288,291,294],{"class":176,"line":277},7,[174,279,281],{"class":280},"swJcz","  id",[174,283,284],{"class":187},":",[174,286,287],{"class":267}," TF",[174,289,290],{"class":187},".",[174,292,293],{"class":267},"UUIDv4",[174,295,211],{"class":187},[174,297,299,302,304,306,308,311],{"class":176,"line":298},8,[174,300,301],{"class":280},"  email",[174,303,284],{"class":187},[174,305,287],{"class":267},[174,307,290],{"class":187},[174,309,310],{"class":267},"Email",[174,312,211],{"class":187},[174,314,316,319,321,323,325,328],{"class":176,"line":315},9,[174,317,318],{"class":280},"  age",[174,320,284],{"class":187},[174,322,287],{"class":267},[174,324,290],{"class":187},[174,326,327],{"class":267},"Int32",[174,329,211],{"class":187},[174,331,333,336,338,340,342,345],{"class":176,"line":332},10,[174,334,335],{"class":280},"  credits",[174,337,284],{"class":187},[174,339,287],{"class":267},[174,341,290],{"class":187},[174,343,344],{"class":267},"Positive",[174,346,211],{"class":187},[174,348,350],{"class":176,"line":349},11,[174,351,352],{"class":187},"};\n",[174,354,356],{"class":176,"line":355},12,[174,357,244],{"emptyLinePlaceholder":243},[174,359,361,364,367,370,374,377,380,383,386],{"class":176,"line":360},13,[174,362,363],{"class":263},"const",[174,365,366],{"class":194}," isAccount ",[174,368,369],{"class":187},"=",[174,371,373],{"class":372},"s2Zo4"," createValidate",[174,375,376],{"class":187},"\u003C",[174,378,379],{"class":267},"Account",[174,381,382],{"class":187},">",[174,384,385],{"class":194},"()",[174,387,211],{"class":187},[174,389,391],{"class":176,"line":390},14,[174,392,244],{"emptyLinePlaceholder":243},[174,394,396,399,402],{"class":176,"line":395},15,[174,397,398],{"class":372},"isAccount",[174,400,401],{"class":194},"(",[174,403,404],{"class":187},"{\n",[174,406,408,410,412,414,417,419],{"class":176,"line":407},16,[174,409,281],{"class":280},[174,411,284],{"class":187},[174,413,201],{"class":187},[174,415,416],{"class":204},"109156be-c4fb-41ea-b1b4-efe1671c5836",[174,418,208],{"class":187},[174,420,421],{"class":187},",\n",[174,423,425,427,429,431,434,436],{"class":176,"line":424},17,[174,426,301],{"class":280},[174,428,284],{"class":187},[174,430,201],{"class":187},[174,432,433],{"class":204},"ada@example.com",[174,435,208],{"class":187},[174,437,421],{"class":187},[174,439,441,443,445,449],{"class":176,"line":440},18,[174,442,318],{"class":280},[174,444,284],{"class":187},[174,446,448],{"class":447},"sbssI"," 36",[174,450,421],{"class":187},[174,452,454,456,458,461],{"class":176,"line":453},19,[174,455,335],{"class":280},[174,457,284],{"class":187},[174,459,460],{"class":447}," 100",[174,462,421],{"class":187},[174,464,466,468,471,474],{"class":176,"line":465},20,[174,467,225],{"class":187},[174,469,470],{"class":194},")",[174,472,473],{"class":187},";",[174,475,476],{"class":250}," \u002F\u002F true\n",[174,478,480],{"class":176,"line":479},21,[174,481,244],{"emptyLinePlaceholder":243},[174,483,485,487,489,492,495,497,499,502,504,507,510,512,514,517,519,521,524,526,529,531,534,536,539,542,544,546,548],{"class":176,"line":484},22,[174,486,398],{"class":372},[174,488,401],{"class":194},[174,490,491],{"class":187},"{",[174,493,494],{"class":280},"id",[174,496,284],{"class":187},[174,498,201],{"class":187},[174,500,501],{"class":204},"not-a-uuid",[174,503,208],{"class":187},[174,505,506],{"class":187},",",[174,508,509],{"class":280}," email",[174,511,284],{"class":187},[174,513,201],{"class":187},[174,515,516],{"class":204},"nope",[174,518,208],{"class":187},[174,520,506],{"class":187},[174,522,523],{"class":280}," age",[174,525,284],{"class":187},[174,527,528],{"class":447}," 1.5",[174,530,506],{"class":187},[174,532,533],{"class":280}," credits",[174,535,284],{"class":187},[174,537,538],{"class":187}," -",[174,540,541],{"class":447},"5",[174,543,225],{"class":187},[174,545,470],{"class":194},[174,547,473],{"class":187},[174,549,550],{"class":250}," \u002F\u002F false\n",[174,552,554],{"class":176,"line":553},23,[174,555,244],{"emptyLinePlaceholder":243},[174,557,559,562,564,566],{"class":176,"line":558},24,[174,560,561],{"class":180},"export",[174,563,219],{"class":187},[174,565,398],{"class":194},[174,567,352],{"class":187},[174,569,571,573,575,577,579],{"class":176,"line":570},25,[174,572,561],{"class":180},[174,574,184],{"class":180},[174,576,219],{"class":187},[174,578,379],{"class":194},[174,580,352],{"class":187},[161,582,583],{},[164,584,587],{"className":166,"code":585,"filename":586,"language":169,"meta":170,"style":170},"import * as TF from 'ts-runtypes\u002Fformats';\nimport {createValidate, type Static} from 'ts-runtypes';\nimport * as RT from 'ts-runtypes\u002Fschema';\n\n\u002F\u002F Schema-first formats: the same constraints as builders. TF.email(),\n\u002F\u002F TF.uuidv4(), TF.int32(), TF.positive() — pick the style you like.\nconst account = RT.object({\n  id: TF.uuidv4(),\n  email: TF.email(),\n  age: TF.int32(),\n  credits: TF.positive(),\n});\n\n\u002F\u002F Static\u003Ctypeof schema> hands the TypeScript type back.\ntype Account = Static\u003Ctypeof account>;\n\nconst isAccount = createValidate(account);\n\nexport {account, isAccount};\nexport type {Account};\n","Schema",[142,588,589,609,636,658,662,667,672,693,710,727,744,761,769,773,778,797,801,816,820,836],{"__ignoreMap":170},[174,590,591,593,595,597,599,601,603,605,607],{"class":176,"line":177},[174,592,181],{"class":180},[174,594,188],{"class":187},[174,596,191],{"class":180},[174,598,195],{"class":194},[174,600,198],{"class":180},[174,602,201],{"class":187},[174,604,205],{"class":204},[174,606,208],{"class":187},[174,608,211],{"class":187},[174,610,611,613,615,617,619,621,624,626,628,630,632,634],{"class":176,"line":214},[174,612,181],{"class":180},[174,614,219],{"class":187},[174,616,222],{"class":194},[174,618,506],{"class":187},[174,620,184],{"class":180},[174,622,623],{"class":194}," Static",[174,625,225],{"class":187},[174,627,228],{"class":180},[174,629,201],{"class":187},[174,631,233],{"class":204},[174,633,208],{"class":187},[174,635,211],{"class":187},[174,637,638,640,642,644,647,649,651,654,656],{"class":176,"line":240},[174,639,181],{"class":180},[174,641,188],{"class":187},[174,643,191],{"class":180},[174,645,646],{"class":194}," RT ",[174,648,198],{"class":180},[174,650,201],{"class":187},[174,652,653],{"class":204},"ts-runtypes\u002Fschema",[174,655,208],{"class":187},[174,657,211],{"class":187},[174,659,660],{"class":176,"line":247},[174,661,244],{"emptyLinePlaceholder":243},[174,663,664],{"class":176,"line":254},[174,665,666],{"class":250},"\u002F\u002F Schema-first formats: the same constraints as builders. TF.email(),\n",[174,668,669],{"class":176,"line":260},[174,670,671],{"class":250},"\u002F\u002F TF.uuidv4(), TF.int32(), TF.positive() — pick the style you like.\n",[174,673,674,676,679,681,684,686,689,691],{"class":176,"line":277},[174,675,363],{"class":263},[174,677,678],{"class":194}," account ",[174,680,369],{"class":187},[174,682,683],{"class":194}," RT",[174,685,290],{"class":187},[174,687,688],{"class":372},"object",[174,690,401],{"class":194},[174,692,404],{"class":187},[174,694,695,697,699,701,703,706,708],{"class":176,"line":298},[174,696,281],{"class":280},[174,698,284],{"class":187},[174,700,287],{"class":194},[174,702,290],{"class":187},[174,704,705],{"class":372},"uuidv4",[174,707,385],{"class":194},[174,709,421],{"class":187},[174,711,712,714,716,718,720,723,725],{"class":176,"line":315},[174,713,301],{"class":280},[174,715,284],{"class":187},[174,717,287],{"class":194},[174,719,290],{"class":187},[174,721,722],{"class":372},"email",[174,724,385],{"class":194},[174,726,421],{"class":187},[174,728,729,731,733,735,737,740,742],{"class":176,"line":332},[174,730,318],{"class":280},[174,732,284],{"class":187},[174,734,287],{"class":194},[174,736,290],{"class":187},[174,738,739],{"class":372},"int32",[174,741,385],{"class":194},[174,743,421],{"class":187},[174,745,746,748,750,752,754,757,759],{"class":176,"line":349},[174,747,335],{"class":280},[174,749,284],{"class":187},[174,751,287],{"class":194},[174,753,290],{"class":187},[174,755,756],{"class":372},"positive",[174,758,385],{"class":194},[174,760,421],{"class":187},[174,762,763,765,767],{"class":176,"line":355},[174,764,225],{"class":187},[174,766,470],{"class":194},[174,768,211],{"class":187},[174,770,771],{"class":176,"line":360},[174,772,244],{"emptyLinePlaceholder":243},[174,774,775],{"class":176,"line":390},[174,776,777],{"class":250},"\u002F\u002F Static\u003Ctypeof schema> hands the TypeScript type back.\n",[174,779,780,782,784,786,788,791,794],{"class":176,"line":395},[174,781,264],{"class":263},[174,783,268],{"class":267},[174,785,271],{"class":187},[174,787,623],{"class":267},[174,789,790],{"class":187},"\u003Ctypeof",[174,792,793],{"class":194}," account",[174,795,796],{"class":187},">;\n",[174,798,799],{"class":176,"line":407},[174,800,244],{"emptyLinePlaceholder":243},[174,802,803,805,807,809,811,814],{"class":176,"line":424},[174,804,363],{"class":263},[174,806,366],{"class":194},[174,808,369],{"class":187},[174,810,373],{"class":372},[174,812,813],{"class":194},"(account)",[174,815,211],{"class":187},[174,817,818],{"class":176,"line":440},[174,819,244],{"emptyLinePlaceholder":243},[174,821,822,824,826,829,831,834],{"class":176,"line":453},[174,823,561],{"class":180},[174,825,219],{"class":187},[174,827,828],{"class":194},"account",[174,830,506],{"class":187},[174,832,833],{"class":194}," isAccount",[174,835,352],{"class":187},[174,837,838,840,842,844,846],{"class":176,"line":465},[174,839,561],{"class":180},[174,841,184],{"class":180},[174,843,219],{"class":187},[174,845,379],{"class":194},[174,847,352],{"class":187},[138,849,850],{},"Both compile to the exact same validator. Mix them in the same file if you want.",[133,852,854],{"id":853},"whats-in-the-box","What's in the box",[138,856,857],{},"Formats come in four families. Here are the named ones (there are more, but these are the ones you'll reach for):",[859,860,861,874],"table",{},[862,863,864],"thead",{},[865,866,867,871],"tr",{},[868,869,870],"th",{},"Family",[868,872,873],{},"A few of the named formats",[875,876,877,916,953,980],"tbody",{},[865,878,879,885],{},[880,881,882],"td",{},[147,883,884],{},"String",[880,886,887,889,890,889,892,889,895,889,898,889,901,889,904,889,907,889,910,889,913],{},[142,888,722],{},", ",[142,891,705],{},[142,893,894],{},"uuidv7",[142,896,897],{},"url",[142,899,900],{},"ipv4",[142,902,903],{},"ipv6",[142,905,906],{},"domain",[142,908,909],{},"alpha",[142,911,912],{},"numeric",[142,914,915],{},"lowercase",[865,917,918,923],{},[880,919,920],{},[147,921,922],{},"Number",[880,924,925,889,928,889,931,889,933,889,936,889,939,889,942,889,945,889,948,889,950],{},[142,926,927],{},"int8",[142,929,930],{},"int16",[142,932,739],{},[142,934,935],{},"uint8",[142,937,938],{},"uint16",[142,940,941],{},"uint32",[142,943,944],{},"integer",[142,946,947],{},"float",[142,949,756],{},[142,951,952],{},"negative",[865,954,955,960],{},[880,956,957],{},[147,958,959],{},"BigInt",[880,961,962,889,965,889,968,889,971,889,974,889,977],{},[142,963,964],{},"bigInt64",[142,966,967],{},"bigUInt64",[142,969,970],{},"bigPositive",[142,972,973],{},"bigNegative",[142,975,976],{},"bigPositiveInt",[142,978,979],{},"bigNegativeInt",[865,981,982,987],{},[880,983,984],{},[147,985,986],{},"Date \u002F time",[880,988,989,990,889,993,889,996,999,1000,1003,1004,1007],{},"three representations, all sharing the same bounds (see below): string-encoded (",[142,991,992],{},"stringDate",[142,994,995],{},"stringTime",[142,997,998],{},"stringDateTime","), native ",[142,1001,1002],{},"date",", and the TC39 ",[142,1005,1006],{},"temporal.*"," types",[138,1009,1010,1011,1013,1014,889,1017,889,1020,889,1023,1026,1027,1030,1031,889,1034,889,1037,889,1040,290],{},"Type-first, it's the capitalized name on the ",[142,1012,144],{}," namespace, like ",[142,1015,1016],{},"TF.Email",[142,1018,1019],{},"TF.Int32",[142,1021,1022],{},"TF.BigInt64",[142,1024,1025],{},"TF.StringDate"," (from ",[142,1028,1029],{},"import * as TF from 'ts-runtypes\u002Fformats'","). Schema-first, the matching builders are ",[142,1032,1033],{},"TF.email()",[142,1035,1036],{},"TF.int32()",[142,1038,1039],{},"TF.bigInt64()",[142,1041,1042],{},"TF.stringDate()",[1044,1045,1046,1047,889,1049,1051,1052,1056,1057,1060],"note",{},"The fixed-width number\u002Fbigint formats (",[142,1048,739],{},[142,1050,967],{},", …) aren't just validation. They also tell the ",[1053,1054,1055],"a",{"href":35},"binary codec"," how many bytes to pack. A ",[142,1058,1059],{},"TF.UInt8"," field rides the wire in a single byte.",[133,1062,1064],{"id":1063},"dates-times-and-temporal","Dates, times and Temporal",[138,1066,1067,1068,1071,1072,1075,1076,1075,1079,1075,1082,1085],{},"A date-ish value shows up in three shapes, and there's a format family for each. They all take the ",[147,1069,1070],{},"same"," ",[142,1073,1074],{},"min"," \u002F ",[142,1077,1078],{},"max",[142,1080,1081],{},"gt",[142,1083,1084],{},"lt"," bounds, so a constraint means the same thing whichever representation you pick:",[1087,1088,1089,1112,1143],"ul",{},[1090,1091,1092,1095,1096,889,1098,889,1101,1104,1105,889,1108,1111],"li",{},[147,1093,1094],{},"String-encoded",": ",[142,1097,1025],{},[142,1099,1100],{},"TF.StringTime",[142,1102,1103],{},"TF.StringDateTime"," check an ISO string in a fixed layout (",[142,1106,1107],{},"'2020-01-01'",[142,1109,1110],{},"'08:30'",").",[1090,1113,1114,1095,1120,1123,1124,1126,1127,1075,1130,1133,1134,1136,1137,1075,1140,1111],{},[147,1115,1116,1117],{},"Native ",[142,1118,1119],{},"Date",[142,1121,1122],{},"TF.Date"," checks a real JS ",[142,1125,1119],{},"; ",[142,1128,1129],{},"TF.DateFuture",[142,1131,1132],{},"TF.DatePast"," are ready-made (a ",[142,1135,1119],{}," that's ",[142,1138,1139],{},">= now",[142,1141,1142],{},"\u003C= now",[1090,1144,1145,1095,1148,889,1151,889,1154,889,1157,889,1160,889,1163,1166,1167,1170,1171,1174,1175,1178],{},[147,1146,1147],{},"TC39 Temporal",[142,1149,1150],{},"TFT.PlainDate",[142,1152,1153],{},"TFT.ZonedDateTime",[142,1155,1156],{},"TFT.Instant",[142,1158,1159],{},"TFT.PlainTime",[142,1161,1162],{},"TFT.PlainDateTime",[142,1164,1165],{},"TFT.PlainYearMonth"," check an actual ",[142,1168,1169],{},"Temporal.*"," instance. Opt in from the dedicated ",[142,1172,1173],{},"ts-runtypes\u002Fformats\u002Ftemporal"," subpath (imported as ",[142,1176,1177],{},"TFT","), so consumers who don't use Temporal never pull in its lib.",[164,1180,1182],{"className":166,"code":1181,"language":169,"meta":170,"style":170},"import type * as TF from 'ts-runtypes\u002Fformats';\nimport type * as TFT from 'ts-runtypes\u002Fformats\u002Ftemporal';\n\n\u002F\u002F The same \"2020 or later\" bound, two representations:\ntype DateString = TF.StringDate\u003C{min: '2020-01-01'}>; \u002F\u002F an ISO string\ntype PlainDate = TFT.PlainDate\u003C{min: '2020-01-01'}>;  \u002F\u002F a Temporal.PlainDate\n",[142,1183,1184,1206,1229,1233,1238,1274],{"__ignoreMap":170},[174,1185,1186,1188,1190,1192,1194,1196,1198,1200,1202,1204],{"class":176,"line":177},[174,1187,181],{"class":180},[174,1189,184],{"class":180},[174,1191,188],{"class":187},[174,1193,191],{"class":180},[174,1195,195],{"class":194},[174,1197,198],{"class":180},[174,1199,201],{"class":187},[174,1201,205],{"class":204},[174,1203,208],{"class":187},[174,1205,211],{"class":187},[174,1207,1208,1210,1212,1214,1216,1219,1221,1223,1225,1227],{"class":176,"line":214},[174,1209,181],{"class":180},[174,1211,184],{"class":180},[174,1213,188],{"class":187},[174,1215,191],{"class":180},[174,1217,1218],{"class":194}," TFT ",[174,1220,198],{"class":180},[174,1222,201],{"class":187},[174,1224,1173],{"class":204},[174,1226,208],{"class":187},[174,1228,211],{"class":187},[174,1230,1231],{"class":176,"line":240},[174,1232,244],{"emptyLinePlaceholder":243},[174,1234,1235],{"class":176,"line":247},[174,1236,1237],{"class":250},"\u002F\u002F The same \"2020 or later\" bound, two representations:\n",[174,1239,1240,1242,1245,1247,1249,1251,1254,1257,1259,1261,1263,1266,1268,1271],{"class":176,"line":254},[174,1241,264],{"class":263},[174,1243,1244],{"class":267}," DateString",[174,1246,271],{"class":187},[174,1248,287],{"class":267},[174,1250,290],{"class":187},[174,1252,1253],{"class":267},"StringDate",[174,1255,1256],{"class":187},"\u003C{",[174,1258,1074],{"class":280},[174,1260,284],{"class":187},[174,1262,201],{"class":187},[174,1264,1265],{"class":204},"2020-01-01",[174,1267,208],{"class":187},[174,1269,1270],{"class":187},"}>;",[174,1272,1273],{"class":250}," \u002F\u002F an ISO string\n",[174,1275,1276,1278,1281,1283,1286,1288,1291,1293,1295,1297,1299,1301,1303,1305],{"class":176,"line":260},[174,1277,264],{"class":263},[174,1279,1280],{"class":267}," PlainDate",[174,1282,271],{"class":187},[174,1284,1285],{"class":267}," TFT",[174,1287,290],{"class":187},[174,1289,1290],{"class":267},"PlainDate",[174,1292,1256],{"class":187},[174,1294,1074],{"class":280},[174,1296,284],{"class":187},[174,1298,201],{"class":187},[174,1300,1265],{"class":204},[174,1302,208],{"class":187},[174,1304,1270],{"class":187},[174,1306,1307],{"class":250},"  \u002F\u002F a Temporal.PlainDate\n",[138,1309,1310,1311,1313,1314,1316,1317,1313,1320,1323,1324,1327,1328,1331],{},"The bound literal is written in the type's own ISO form. A ",[142,1312,1290],{}," takes ",[142,1315,1107],{},", an ",[142,1318,1319],{},"Instant",[142,1321,1322],{},"'2020-01-01T00:00:00Z'",". (",[142,1325,1326],{},"Temporal.PlainMonthDay"," and ",[142,1329,1330],{},"Temporal.Duration"," have no min\u002Fmax ordering, so they're validated by identity only, with no bounds.)",[138,1333,1334,1335,1338,1339,1342],{},"Schema-first, the same builders live under ",[142,1336,1337],{},"TF.date(...)"," and the ",[142,1340,1341],{},"TFT.*"," temporal namespace:",[164,1344,1346],{"className":166,"code":1345,"language":169,"meta":170,"style":170},"import * as TF from 'ts-runtypes\u002Fformats';\nimport * as TFT from 'ts-runtypes\u002Fformats\u002Ftemporal';\n\nTF.date({max: 'now'});               \u002F\u002F a Date in the past\nTFT.plainDate({min: '2020-01-01'});  \u002F\u002F a Temporal.PlainDate, 2020 on\nTFT.instant({min: 'now-PT1H'});      \u002F\u002F an Instant within the last hour\n",[142,1347,1348,1368,1388,1392,1424,1456],{"__ignoreMap":170},[174,1349,1350,1352,1354,1356,1358,1360,1362,1364,1366],{"class":176,"line":177},[174,1351,181],{"class":180},[174,1353,188],{"class":187},[174,1355,191],{"class":180},[174,1357,195],{"class":194},[174,1359,198],{"class":180},[174,1361,201],{"class":187},[174,1363,205],{"class":204},[174,1365,208],{"class":187},[174,1367,211],{"class":187},[174,1369,1370,1372,1374,1376,1378,1380,1382,1384,1386],{"class":176,"line":214},[174,1371,181],{"class":180},[174,1373,188],{"class":187},[174,1375,191],{"class":180},[174,1377,1218],{"class":194},[174,1379,198],{"class":180},[174,1381,201],{"class":187},[174,1383,1173],{"class":204},[174,1385,208],{"class":187},[174,1387,211],{"class":187},[174,1389,1390],{"class":176,"line":240},[174,1391,244],{"emptyLinePlaceholder":243},[174,1393,1394,1396,1398,1400,1402,1404,1406,1408,1410,1413,1415,1417,1419,1421],{"class":176,"line":247},[174,1395,144],{"class":194},[174,1397,290],{"class":187},[174,1399,1002],{"class":372},[174,1401,401],{"class":194},[174,1403,491],{"class":187},[174,1405,1078],{"class":280},[174,1407,284],{"class":187},[174,1409,201],{"class":187},[174,1411,1412],{"class":204},"now",[174,1414,208],{"class":187},[174,1416,225],{"class":187},[174,1418,470],{"class":194},[174,1420,473],{"class":187},[174,1422,1423],{"class":250},"               \u002F\u002F a Date in the past\n",[174,1425,1426,1428,1430,1433,1435,1437,1439,1441,1443,1445,1447,1449,1451,1453],{"class":176,"line":254},[174,1427,1177],{"class":194},[174,1429,290],{"class":187},[174,1431,1432],{"class":372},"plainDate",[174,1434,401],{"class":194},[174,1436,491],{"class":187},[174,1438,1074],{"class":280},[174,1440,284],{"class":187},[174,1442,201],{"class":187},[174,1444,1265],{"class":204},[174,1446,208],{"class":187},[174,1448,225],{"class":187},[174,1450,470],{"class":194},[174,1452,473],{"class":187},[174,1454,1455],{"class":250},"  \u002F\u002F a Temporal.PlainDate, 2020 on\n",[174,1457,1458,1460,1462,1465,1467,1469,1471,1473,1475,1478,1480,1482,1484,1486],{"class":176,"line":260},[174,1459,1177],{"class":194},[174,1461,290],{"class":187},[174,1463,1464],{"class":372},"instant",[174,1466,401],{"class":194},[174,1468,491],{"class":187},[174,1470,1074],{"class":280},[174,1472,284],{"class":187},[174,1474,201],{"class":187},[174,1476,1477],{"class":204},"now-PT1H",[174,1479,208],{"class":187},[174,1481,225],{"class":187},[174,1483,470],{"class":194},[174,1485,473],{"class":187},[174,1487,1488],{"class":250},"      \u002F\u002F an Instant within the last hour\n",[1044,1490,1491,1492,1495,1496,1499,1500,1503,1504,1507,1508,290],{},"Temporal values are validated by ",[147,1493,1494],{},"identity"," (",[142,1497,1498],{},"instanceof","), not by structural shape. They also survive ",[142,1501,1502],{},"DataOnly"," whole, so ",[142,1505,1506],{},"DataOnly\u003CTemporal.PlainDate>"," stays a ",[142,1509,1510],{},"Temporal.PlainDate",[133,1512,1514,1515],{"id":1513},"relative-bounds-with-now","Relative bounds with ",[142,1516,1412],{},[138,1518,1519,1520,1522,1523,1525,1526,1495,1529,1075,1532,1535],{},"A bound doesn't have to be an absolute date. Write ",[142,1521,1412],{},", or ",[142,1524,1412],{}," plus or minus an ",[147,1527,1528],{},"ISO-8601 duration",[142,1530,1531],{},"now+P…",[142,1533,1534],{},"now-P…","), and the build resolves it against the current time every time it validates:",[164,1537,1539],{"className":166,"code":1538,"language":169,"meta":170,"style":170},"import type * as TF from 'ts-runtypes\u002Fformats';\nimport {createValidate} from 'ts-runtypes';\n\n\u002F\u002F A bound can be RELATIVE: `now`, or `now` ± an ISO-8601 duration. The build\n\u002F\u002F resolves it against the current time each time it validates a value.\n\n\u002F\u002F A birth date in the past, no more than 120 years ago.\ntype BirthDate = TF.StringDate\u003C{min: 'now-P120Y'; max: 'now'}>;\n\n\u002F\u002F A meeting that starts within the next 30 days.\ntype StartsSoon = TF.StringDateTime\u003C{min: 'now'; max: 'now+P30D'}>;\n\nconst isBirthDate = createValidate\u003CBirthDate>();\nconst startsSoon = createValidate\u003CStartsSoon>();\n\nisBirthDate('1990-05-20'); \u002F\u002F true\nisBirthDate('1850-01-01'); \u002F\u002F false — more than 120 years ago\n\nexport {isBirthDate, startsSoon};\n",[142,1540,1541,1563,1583,1587,1592,1597,1601,1606,1650,1654,1659,1702,1706,1728,1750,1754,1774,1794,1798],{"__ignoreMap":170},[174,1542,1543,1545,1547,1549,1551,1553,1555,1557,1559,1561],{"class":176,"line":177},[174,1544,181],{"class":180},[174,1546,184],{"class":180},[174,1548,188],{"class":187},[174,1550,191],{"class":180},[174,1552,195],{"class":194},[174,1554,198],{"class":180},[174,1556,201],{"class":187},[174,1558,205],{"class":204},[174,1560,208],{"class":187},[174,1562,211],{"class":187},[174,1564,1565,1567,1569,1571,1573,1575,1577,1579,1581],{"class":176,"line":214},[174,1566,181],{"class":180},[174,1568,219],{"class":187},[174,1570,222],{"class":194},[174,1572,225],{"class":187},[174,1574,228],{"class":180},[174,1576,201],{"class":187},[174,1578,233],{"class":204},[174,1580,208],{"class":187},[174,1582,211],{"class":187},[174,1584,1585],{"class":176,"line":240},[174,1586,244],{"emptyLinePlaceholder":243},[174,1588,1589],{"class":176,"line":247},[174,1590,1591],{"class":250},"\u002F\u002F A bound can be RELATIVE: `now`, or `now` ± an ISO-8601 duration. The build\n",[174,1593,1594],{"class":176,"line":254},[174,1595,1596],{"class":250},"\u002F\u002F resolves it against the current time each time it validates a value.\n",[174,1598,1599],{"class":176,"line":260},[174,1600,244],{"emptyLinePlaceholder":243},[174,1602,1603],{"class":176,"line":277},[174,1604,1605],{"class":250},"\u002F\u002F A birth date in the past, no more than 120 years ago.\n",[174,1607,1608,1610,1613,1615,1617,1619,1621,1623,1625,1627,1629,1632,1634,1636,1639,1641,1643,1645,1647],{"class":176,"line":298},[174,1609,264],{"class":263},[174,1611,1612],{"class":267}," BirthDate",[174,1614,271],{"class":187},[174,1616,287],{"class":267},[174,1618,290],{"class":187},[174,1620,1253],{"class":267},[174,1622,1256],{"class":187},[174,1624,1074],{"class":280},[174,1626,284],{"class":187},[174,1628,201],{"class":187},[174,1630,1631],{"class":204},"now-P120Y",[174,1633,208],{"class":187},[174,1635,473],{"class":187},[174,1637,1638],{"class":280}," max",[174,1640,284],{"class":187},[174,1642,201],{"class":187},[174,1644,1412],{"class":204},[174,1646,208],{"class":187},[174,1648,1649],{"class":187},"}>;\n",[174,1651,1652],{"class":176,"line":315},[174,1653,244],{"emptyLinePlaceholder":243},[174,1655,1656],{"class":176,"line":332},[174,1657,1658],{"class":250},"\u002F\u002F A meeting that starts within the next 30 days.\n",[174,1660,1661,1663,1666,1668,1670,1672,1675,1677,1679,1681,1683,1685,1687,1689,1691,1693,1695,1698,1700],{"class":176,"line":349},[174,1662,264],{"class":263},[174,1664,1665],{"class":267}," StartsSoon",[174,1667,271],{"class":187},[174,1669,287],{"class":267},[174,1671,290],{"class":187},[174,1673,1674],{"class":267},"StringDateTime",[174,1676,1256],{"class":187},[174,1678,1074],{"class":280},[174,1680,284],{"class":187},[174,1682,201],{"class":187},[174,1684,1412],{"class":204},[174,1686,208],{"class":187},[174,1688,473],{"class":187},[174,1690,1638],{"class":280},[174,1692,284],{"class":187},[174,1694,201],{"class":187},[174,1696,1697],{"class":204},"now+P30D",[174,1699,208],{"class":187},[174,1701,1649],{"class":187},[174,1703,1704],{"class":176,"line":355},[174,1705,244],{"emptyLinePlaceholder":243},[174,1707,1708,1710,1713,1715,1717,1719,1722,1724,1726],{"class":176,"line":360},[174,1709,363],{"class":263},[174,1711,1712],{"class":194}," isBirthDate ",[174,1714,369],{"class":187},[174,1716,373],{"class":372},[174,1718,376],{"class":187},[174,1720,1721],{"class":267},"BirthDate",[174,1723,382],{"class":187},[174,1725,385],{"class":194},[174,1727,211],{"class":187},[174,1729,1730,1732,1735,1737,1739,1741,1744,1746,1748],{"class":176,"line":390},[174,1731,363],{"class":263},[174,1733,1734],{"class":194}," startsSoon ",[174,1736,369],{"class":187},[174,1738,373],{"class":372},[174,1740,376],{"class":187},[174,1742,1743],{"class":267},"StartsSoon",[174,1745,382],{"class":187},[174,1747,385],{"class":194},[174,1749,211],{"class":187},[174,1751,1752],{"class":176,"line":395},[174,1753,244],{"emptyLinePlaceholder":243},[174,1755,1756,1759,1761,1763,1766,1768,1770,1772],{"class":176,"line":407},[174,1757,1758],{"class":372},"isBirthDate",[174,1760,401],{"class":194},[174,1762,208],{"class":187},[174,1764,1765],{"class":204},"1990-05-20",[174,1767,208],{"class":187},[174,1769,470],{"class":194},[174,1771,473],{"class":187},[174,1773,476],{"class":250},[174,1775,1776,1778,1780,1782,1785,1787,1789,1791],{"class":176,"line":424},[174,1777,1758],{"class":372},[174,1779,401],{"class":194},[174,1781,208],{"class":187},[174,1783,1784],{"class":204},"1850-01-01",[174,1786,208],{"class":187},[174,1788,470],{"class":194},[174,1790,473],{"class":187},[174,1792,1793],{"class":250}," \u002F\u002F false — more than 120 years ago\n",[174,1795,1796],{"class":176,"line":440},[174,1797,244],{"emptyLinePlaceholder":243},[174,1799,1800,1802,1804,1806,1808,1811],{"class":176,"line":453},[174,1801,561],{"class":180},[174,1803,219],{"class":187},[174,1805,1758],{"class":194},[174,1807,506],{"class":187},[174,1809,1810],{"class":194}," startsSoon",[174,1812,352],{"class":187},[138,1814,1815,1816,1819,1820,1823,1824,1827,1828,1831],{},"The ",[142,1817,1818],{},"P…"," tail is a full ISO-8601 duration, such as ",[142,1821,1822],{},"P1Y2M10D"," (1 year, 2 months, 10 days), ",[142,1825,1826],{},"P1W"," (1 week), or ",[142,1829,1830],{},"PT12H30M"," (12 hours, 30 minutes). The build checks the units fit the field: a date-only format takes only date units, a time-only format only time units.",[859,1833,1834,1843],{},[862,1835,1836],{},[865,1837,1838,1840],{},[868,1839,870],{},[868,1841,1842],{},"Relative units",[875,1844,1845,1874,1899],{},[865,1846,1847,1859],{},[880,1848,1849,1850,889,1853,889,1856,470],{},"Date-only (",[142,1851,1852],{},"TF.stringDate",[142,1854,1855],{},"TFT.plainDate",[142,1857,1858],{},"TFT.plainYearMonth",[880,1860,1861,1862,1071,1865,1071,1868,1071,1871],{},"date: ",[142,1863,1864],{},"Y",[142,1866,1867],{},"M",[142,1869,1870],{},"W",[142,1872,1873],{},"D",[865,1875,1876,1888],{},[880,1877,1878,1879,889,1882,889,1885,470],{},"Time-only (",[142,1880,1881],{},"TF.stringTime",[142,1883,1884],{},"TFT.plainTime",[142,1886,1887],{},"TFT.instant",[880,1889,1890,1891,1071,1894,1071,1896],{},"time: ",[142,1892,1893],{},"H",[142,1895,1867],{},[142,1897,1898],{},"S",[865,1900,1901,1917],{},[880,1902,1903,1904,1907,1908,889,1911,889,1914,470],{},"Date + time (",[142,1905,1906],{},"TF.stringDateTime",", native ",[142,1909,1910],{},"TF.date",[142,1912,1913],{},"TFT.plainDateTime",[142,1915,1916],{},"TFT.zonedDateTime",[880,1918,1919],{},"both",[138,1921,1922,1075,1924,1926,1927,1075,1929,1931],{},[142,1923,1074],{},[142,1925,1078],{}," are inclusive; ",[142,1928,1081],{},[142,1930,1084],{}," are the exclusive twins. Give each edge as one or the other, never both.",[133,1933,1935],{"id":1934},"branded-nominal-types","Branded (nominal) types",[138,1937,1938,1939,1942,1943,1946,1947,1950,1951,1954,1955,1959,1960,1963],{},"By default a format is still structurally a ",[142,1940,1941],{},"string"," or ",[142,1944,1945],{},"number",". That's handy, but it won't stop you from passing a raw string where a ",[142,1948,1949],{},"UserId"," belongs. Add a ",[147,1952,1953],{},"brand name"," (the second type argument) and the format becomes ",[1956,1957,1958],"em",{},"nominal",": nothing else is assignable to it without an explicit ",[142,1961,1962],{},"as"," cast.",[164,1965,1967],{"className":166,"code":1966,"language":169,"meta":170,"style":170},"import type * as TF from 'ts-runtypes\u002Fformats';\n\n\u002F\u002F Add a brand name (the 2nd type arg) and the format becomes a NOMINAL type.\n\u002F\u002F A plain string is no longer assignable — you must opt in with `as`.\ntype UserId = TF.String\u003C{minLength: 1}, 'UserId'>;\ntype Cents = TF.Number\u003C{min: 0; integer: true}, 'Cents'>;\n\n\u002F\u002F A bare string won't fit — that's the point. Cast at the boundary where\n\u002F\u002F you've actually checked the value.\nconst id = 'usr_abc123' as UserId;\nconst price = 4999 as Cents;\n\n\u002F\u002F Now UserId and Cents don't mix with each other or with raw string\u002Fnumber.\nfunction chargeUser(_user: UserId, _amount: Cents): void {}\nchargeUser(id, price); \u002F\u002F ok\n\nexport {id, price, chargeUser};\nexport type {UserId, Cents};\n",[142,1968,1969,1991,1995,2000,2005,2041,2086,2090,2095,2100,2122,2140,2144,2149,2185,2203,2207,2226],{"__ignoreMap":170},[174,1970,1971,1973,1975,1977,1979,1981,1983,1985,1987,1989],{"class":176,"line":177},[174,1972,181],{"class":180},[174,1974,184],{"class":180},[174,1976,188],{"class":187},[174,1978,191],{"class":180},[174,1980,195],{"class":194},[174,1982,198],{"class":180},[174,1984,201],{"class":187},[174,1986,205],{"class":204},[174,1988,208],{"class":187},[174,1990,211],{"class":187},[174,1992,1993],{"class":176,"line":214},[174,1994,244],{"emptyLinePlaceholder":243},[174,1996,1997],{"class":176,"line":240},[174,1998,1999],{"class":250},"\u002F\u002F Add a brand name (the 2nd type arg) and the format becomes a NOMINAL type.\n",[174,2001,2002],{"class":176,"line":247},[174,2003,2004],{"class":250},"\u002F\u002F A plain string is no longer assignable — you must opt in with `as`.\n",[174,2006,2007,2009,2012,2014,2016,2018,2020,2022,2025,2027,2030,2033,2035,2037,2039],{"class":176,"line":254},[174,2008,264],{"class":263},[174,2010,2011],{"class":267}," UserId",[174,2013,271],{"class":187},[174,2015,287],{"class":267},[174,2017,290],{"class":187},[174,2019,884],{"class":267},[174,2021,1256],{"class":187},[174,2023,2024],{"class":280},"minLength",[174,2026,284],{"class":187},[174,2028,2029],{"class":447}," 1",[174,2031,2032],{"class":187},"},",[174,2034,201],{"class":187},[174,2036,1949],{"class":204},[174,2038,208],{"class":187},[174,2040,796],{"class":187},[174,2042,2043,2045,2048,2050,2052,2054,2056,2058,2060,2062,2065,2067,2070,2072,2075,2077,2079,2082,2084],{"class":176,"line":260},[174,2044,264],{"class":263},[174,2046,2047],{"class":267}," Cents",[174,2049,271],{"class":187},[174,2051,287],{"class":267},[174,2053,290],{"class":187},[174,2055,922],{"class":267},[174,2057,1256],{"class":187},[174,2059,1074],{"class":280},[174,2061,284],{"class":187},[174,2063,2064],{"class":447}," 0",[174,2066,473],{"class":187},[174,2068,2069],{"class":280}," integer",[174,2071,284],{"class":187},[174,2073,2074],{"class":267}," true",[174,2076,2032],{"class":187},[174,2078,201],{"class":187},[174,2080,2081],{"class":204},"Cents",[174,2083,208],{"class":187},[174,2085,796],{"class":187},[174,2087,2088],{"class":176,"line":277},[174,2089,244],{"emptyLinePlaceholder":243},[174,2091,2092],{"class":176,"line":298},[174,2093,2094],{"class":250},"\u002F\u002F A bare string won't fit — that's the point. Cast at the boundary where\n",[174,2096,2097],{"class":176,"line":315},[174,2098,2099],{"class":250},"\u002F\u002F you've actually checked the value.\n",[174,2101,2102,2104,2107,2109,2111,2114,2116,2118,2120],{"class":176,"line":332},[174,2103,363],{"class":263},[174,2105,2106],{"class":194}," id ",[174,2108,369],{"class":187},[174,2110,201],{"class":187},[174,2112,2113],{"class":204},"usr_abc123",[174,2115,208],{"class":187},[174,2117,191],{"class":180},[174,2119,2011],{"class":267},[174,2121,211],{"class":187},[174,2123,2124,2126,2129,2131,2134,2136,2138],{"class":176,"line":349},[174,2125,363],{"class":263},[174,2127,2128],{"class":194}," price ",[174,2130,369],{"class":187},[174,2132,2133],{"class":447}," 4999",[174,2135,191],{"class":180},[174,2137,2047],{"class":267},[174,2139,211],{"class":187},[174,2141,2142],{"class":176,"line":355},[174,2143,244],{"emptyLinePlaceholder":243},[174,2145,2146],{"class":176,"line":360},[174,2147,2148],{"class":250},"\u002F\u002F Now UserId and Cents don't mix with each other or with raw string\u002Fnumber.\n",[174,2150,2151,2154,2157,2159,2163,2165,2167,2169,2172,2174,2176,2179,2182],{"class":176,"line":390},[174,2152,2153],{"class":263},"function",[174,2155,2156],{"class":372}," chargeUser",[174,2158,401],{"class":187},[174,2160,2162],{"class":2161},"sHdIc","_user",[174,2164,284],{"class":187},[174,2166,2011],{"class":267},[174,2168,506],{"class":187},[174,2170,2171],{"class":2161}," _amount",[174,2173,284],{"class":187},[174,2175,2047],{"class":267},[174,2177,2178],{"class":187},"):",[174,2180,2181],{"class":267}," void",[174,2183,2184],{"class":187}," {}\n",[174,2186,2187,2190,2193,2195,2198,2200],{"class":176,"line":395},[174,2188,2189],{"class":372},"chargeUser",[174,2191,2192],{"class":194},"(id",[174,2194,506],{"class":187},[174,2196,2197],{"class":194}," price)",[174,2199,473],{"class":187},[174,2201,2202],{"class":250}," \u002F\u002F ok\n",[174,2204,2205],{"class":176,"line":407},[174,2206,244],{"emptyLinePlaceholder":243},[174,2208,2209,2211,2213,2215,2217,2220,2222,2224],{"class":176,"line":424},[174,2210,561],{"class":180},[174,2212,219],{"class":187},[174,2214,494],{"class":194},[174,2216,506],{"class":187},[174,2218,2219],{"class":194}," price",[174,2221,506],{"class":187},[174,2223,2156],{"class":194},[174,2225,352],{"class":187},[174,2227,2228,2230,2232,2234,2236,2238,2240],{"class":176,"line":440},[174,2229,561],{"class":180},[174,2231,184],{"class":180},[174,2233,219],{"class":187},[174,2235,1949],{"class":194},[174,2237,506],{"class":187},[174,2239,2047],{"class":194},[174,2241,352],{"class":187},[2243,2244,1815,2245,2247,2248,2250],"tip",{},[142,2246,1962],{}," cast is a feature, not a chore. It marks the exact line where you've decided a raw value is now a ",[142,2249,1949],{},", usually right after you've validated it. Everywhere else, the type system keeps your ids, cents and timestamps from getting mixed up.",[138,2252,2253,2254,2257,2258,290],{},"Schema-first, brand with the ",[142,2255,2256],{},"brand()"," tag: ",[142,2259,2260],{},"TF.string({minLength: 1}, TF.brand('UserId'))",[133,2262,2264],{"id":2263},"custom-formats","Custom formats",[138,2266,2267,2268,889,2271,1327,2274,2277],{},"No named format fits? ",[142,2269,2270],{},"TF.String",[142,2272,2273],{},"TF.Number",[142,2275,2276],{},"TF.BigInt"," are the escape hatches. Pass your own params.",[164,2279,2281],{"className":166,"code":2280,"language":169,"meta":170,"style":170},"import type * as TF from 'ts-runtypes\u002Fformats';\nimport {createValidate} from 'ts-runtypes';\n\n\u002F\u002F TF.String \u002F TF.Number \u002F TF.BigInt are the escape hatches: pass\n\u002F\u002F your own params when no named format fits.\ntype Username = TF.String\u003C{minLength: 3; maxLength: 20; pattern: {source: '^[a-z0-9_]+$'; mockSamples: ['ada_99', 'grace']}}>;\ntype Percentage = TF.Number\u003C{min: 0; max: 100}>;\ntype BigPositive = TF.BigInt\u003C{min: 0n}>;\n\ntype Profile = {\n  handle: Username;\n  completion: Percentage;\n  followers: BigPositive;\n};\n\nconst isProfile = createValidate\u003CProfile>();\n\nisProfile({handle: 'ada_99', completion: 80, followers: 1200n}); \u002F\u002F true\nisProfile({handle: 'no', completion: 150, followers: -1n}); \u002F\u002F false\n\nexport {isProfile};\nexport type {Profile};\n",[142,2282,2283,2305,2325,2329,2334,2339,2426,2459,2487,2491,2502,2513,2524,2535,2539,2543,2565,2569,2619,2668,2672,2682],{"__ignoreMap":170},[174,2284,2285,2287,2289,2291,2293,2295,2297,2299,2301,2303],{"class":176,"line":177},[174,2286,181],{"class":180},[174,2288,184],{"class":180},[174,2290,188],{"class":187},[174,2292,191],{"class":180},[174,2294,195],{"class":194},[174,2296,198],{"class":180},[174,2298,201],{"class":187},[174,2300,205],{"class":204},[174,2302,208],{"class":187},[174,2304,211],{"class":187},[174,2306,2307,2309,2311,2313,2315,2317,2319,2321,2323],{"class":176,"line":214},[174,2308,181],{"class":180},[174,2310,219],{"class":187},[174,2312,222],{"class":194},[174,2314,225],{"class":187},[174,2316,228],{"class":180},[174,2318,201],{"class":187},[174,2320,233],{"class":204},[174,2322,208],{"class":187},[174,2324,211],{"class":187},[174,2326,2327],{"class":176,"line":240},[174,2328,244],{"emptyLinePlaceholder":243},[174,2330,2331],{"class":176,"line":247},[174,2332,2333],{"class":250},"\u002F\u002F TF.String \u002F TF.Number \u002F TF.BigInt are the escape hatches: pass\n",[174,2335,2336],{"class":176,"line":254},[174,2337,2338],{"class":250},"\u002F\u002F your own params when no named format fits.\n",[174,2340,2341,2343,2346,2348,2350,2352,2354,2356,2358,2360,2363,2365,2368,2370,2373,2375,2378,2380,2382,2385,2387,2389,2392,2394,2396,2399,2401,2404,2406,2409,2411,2413,2415,2418,2420,2423],{"class":176,"line":260},[174,2342,264],{"class":263},[174,2344,2345],{"class":267}," Username",[174,2347,271],{"class":187},[174,2349,287],{"class":267},[174,2351,290],{"class":187},[174,2353,884],{"class":267},[174,2355,1256],{"class":187},[174,2357,2024],{"class":280},[174,2359,284],{"class":187},[174,2361,2362],{"class":447}," 3",[174,2364,473],{"class":187},[174,2366,2367],{"class":280}," maxLength",[174,2369,284],{"class":187},[174,2371,2372],{"class":447}," 20",[174,2374,473],{"class":187},[174,2376,2377],{"class":280}," pattern",[174,2379,284],{"class":187},[174,2381,219],{"class":187},[174,2383,2384],{"class":280},"source",[174,2386,284],{"class":187},[174,2388,201],{"class":187},[174,2390,2391],{"class":204},"^[a-z0-9_]+$",[174,2393,208],{"class":187},[174,2395,473],{"class":187},[174,2397,2398],{"class":280}," mockSamples",[174,2400,284],{"class":187},[174,2402,2403],{"class":194}," [",[174,2405,208],{"class":187},[174,2407,2408],{"class":204},"ada_99",[174,2410,208],{"class":187},[174,2412,506],{"class":187},[174,2414,201],{"class":187},[174,2416,2417],{"class":204},"grace",[174,2419,208],{"class":187},[174,2421,2422],{"class":194},"]",[174,2424,2425],{"class":187},"}}>;\n",[174,2427,2428,2430,2433,2435,2437,2439,2441,2443,2445,2447,2449,2451,2453,2455,2457],{"class":176,"line":277},[174,2429,264],{"class":263},[174,2431,2432],{"class":267}," Percentage",[174,2434,271],{"class":187},[174,2436,287],{"class":267},[174,2438,290],{"class":187},[174,2440,922],{"class":267},[174,2442,1256],{"class":187},[174,2444,1074],{"class":280},[174,2446,284],{"class":187},[174,2448,2064],{"class":447},[174,2450,473],{"class":187},[174,2452,1638],{"class":280},[174,2454,284],{"class":187},[174,2456,460],{"class":447},[174,2458,1649],{"class":187},[174,2460,2461,2463,2466,2468,2470,2472,2474,2476,2478,2480,2482,2485],{"class":176,"line":298},[174,2462,264],{"class":263},[174,2464,2465],{"class":267}," BigPositive",[174,2467,271],{"class":187},[174,2469,287],{"class":267},[174,2471,290],{"class":187},[174,2473,959],{"class":267},[174,2475,1256],{"class":187},[174,2477,1074],{"class":280},[174,2479,284],{"class":187},[174,2481,2064],{"class":447},[174,2483,2484],{"class":263},"n",[174,2486,1649],{"class":187},[174,2488,2489],{"class":176,"line":315},[174,2490,244],{"emptyLinePlaceholder":243},[174,2492,2493,2495,2498,2500],{"class":176,"line":332},[174,2494,264],{"class":263},[174,2496,2497],{"class":267}," Profile",[174,2499,271],{"class":187},[174,2501,274],{"class":187},[174,2503,2504,2507,2509,2511],{"class":176,"line":349},[174,2505,2506],{"class":280},"  handle",[174,2508,284],{"class":187},[174,2510,2345],{"class":267},[174,2512,211],{"class":187},[174,2514,2515,2518,2520,2522],{"class":176,"line":355},[174,2516,2517],{"class":280},"  completion",[174,2519,284],{"class":187},[174,2521,2432],{"class":267},[174,2523,211],{"class":187},[174,2525,2526,2529,2531,2533],{"class":176,"line":360},[174,2527,2528],{"class":280},"  followers",[174,2530,284],{"class":187},[174,2532,2465],{"class":267},[174,2534,211],{"class":187},[174,2536,2537],{"class":176,"line":390},[174,2538,352],{"class":187},[174,2540,2541],{"class":176,"line":395},[174,2542,244],{"emptyLinePlaceholder":243},[174,2544,2545,2547,2550,2552,2554,2556,2559,2561,2563],{"class":176,"line":407},[174,2546,363],{"class":263},[174,2548,2549],{"class":194}," isProfile ",[174,2551,369],{"class":187},[174,2553,373],{"class":372},[174,2555,376],{"class":187},[174,2557,2558],{"class":267},"Profile",[174,2560,382],{"class":187},[174,2562,385],{"class":194},[174,2564,211],{"class":187},[174,2566,2567],{"class":176,"line":424},[174,2568,244],{"emptyLinePlaceholder":243},[174,2570,2571,2574,2576,2578,2581,2583,2585,2587,2589,2591,2594,2596,2599,2601,2604,2606,2609,2611,2613,2615,2617],{"class":176,"line":440},[174,2572,2573],{"class":372},"isProfile",[174,2575,401],{"class":194},[174,2577,491],{"class":187},[174,2579,2580],{"class":280},"handle",[174,2582,284],{"class":187},[174,2584,201],{"class":187},[174,2586,2408],{"class":204},[174,2588,208],{"class":187},[174,2590,506],{"class":187},[174,2592,2593],{"class":280}," completion",[174,2595,284],{"class":187},[174,2597,2598],{"class":447}," 80",[174,2600,506],{"class":187},[174,2602,2603],{"class":280}," followers",[174,2605,284],{"class":187},[174,2607,2608],{"class":447}," 1200",[174,2610,2484],{"class":263},[174,2612,225],{"class":187},[174,2614,470],{"class":194},[174,2616,473],{"class":187},[174,2618,476],{"class":250},[174,2620,2621,2623,2625,2627,2629,2631,2633,2636,2638,2640,2642,2644,2647,2649,2651,2653,2655,2658,2660,2662,2664,2666],{"class":176,"line":453},[174,2622,2573],{"class":372},[174,2624,401],{"class":194},[174,2626,491],{"class":187},[174,2628,2580],{"class":280},[174,2630,284],{"class":187},[174,2632,201],{"class":187},[174,2634,2635],{"class":204},"no",[174,2637,208],{"class":187},[174,2639,506],{"class":187},[174,2641,2593],{"class":280},[174,2643,284],{"class":187},[174,2645,2646],{"class":447}," 150",[174,2648,506],{"class":187},[174,2650,2603],{"class":280},[174,2652,284],{"class":187},[174,2654,538],{"class":187},[174,2656,2657],{"class":447},"1",[174,2659,2484],{"class":263},[174,2661,225],{"class":187},[174,2663,470],{"class":194},[174,2665,473],{"class":187},[174,2667,550],{"class":250},[174,2669,2670],{"class":176,"line":465},[174,2671,244],{"emptyLinePlaceholder":243},[174,2673,2674,2676,2678,2680],{"class":176,"line":479},[174,2675,561],{"class":180},[174,2677,219],{"class":187},[174,2679,2573],{"class":194},[174,2681,352],{"class":187},[174,2683,2684,2686,2688,2690,2692],{"class":176,"line":484},[174,2685,561],{"class":180},[174,2687,184],{"class":180},[174,2689,219],{"class":187},[174,2691,2558],{"class":194},[174,2693,352],{"class":187},[138,2695,2696],{},"The common params:",[859,2698,2699,2709],{},[862,2700,2701],{},[865,2702,2703,2706],{},[868,2704,2705],{},"Format",[868,2707,2708],{},"Params",[875,2710,2711,2737,2760],{},[865,2712,2713,2717],{},[880,2714,2715],{},[142,2716,2270],{},[880,2718,2719,889,2721,889,2724,889,2727,889,2730,889,2733,2736],{},[142,2720,2024],{},[142,2722,2723],{},"maxLength",[142,2725,2726],{},"length",[142,2728,2729],{},"pattern",[142,2731,2732],{},"allowedChars",[142,2734,2735],{},"allowedValues",", …",[865,2738,2739,2743],{},[880,2740,2741],{},[142,2742,2273],{},[880,2744,2745,889,2747,889,2749,889,2751,889,2753,889,2755,889,2757],{},[142,2746,1074],{},[142,2748,1078],{},[142,2750,1081],{},[142,2752,1084],{},[142,2754,944],{},[142,2756,947],{},[142,2758,2759],{},"multipleOf",[865,2761,2762,2766],{},[880,2763,2764],{},[142,2765,2276],{},[880,2767,2768,889,2770,889,2772,889,2774,889,2776,2778,2779,2782,2783,470],{},[142,2769,1074],{},[142,2771,1078],{},[142,2773,1081],{},[142,2775,1084],{},[142,2777,2759],{}," (all ",[142,2780,2781],{},"bigint"," literals, e.g. ",[142,2784,2785],{},"0n",[138,2787,2788,2790,2791,1926,2793,2790,2795,2797,2798,290],{},[142,2789,1074],{},"\u002F",[142,2792,1078],{},[142,2794,1081],{},[142,2796,1084],{}," are their exclusive twins. A bound is one or the other, never both. The build rejects ",[142,2799,2800],{},"{min: 0, gt: 0}",[1044,2802,2803,2804,2806,2807,2810,2811,2816,2817,290],{},"A ",[142,2805,2729],{}," always needs ",[142,2808,2809],{},"mockSamples",", the canonical valid values the mock generator can draw from (a bare regex with no samples is rejected). Reusing a pattern across types? Register it once with ",[1053,2812,2813],{"href":51},[142,2814,2815],{},"registerFormatPattern"," and reference it by ",[142,2818,2819],{},"typeof",[133,2821,2823],{"id":2822},"smaller-on-the-wire","Smaller on the wire",[138,2825,2826,2827,2829,2830,1327,2832,2834,2835,1942,2837,2839,2840,2843],{},"A format constraint is not only a validation rule. The binary codec uses it to size the payload: a fixed width like ",[142,2828,927],{},", or a ",[142,2831,1074],{},[142,2833,1078],{}," bound, lets the encoder pack the value into the narrowest field that fits, instead of the 8 bytes an unconstrained ",[142,2836,1945],{},[142,2838,2781],{}," needs. The ",[1053,2841,2842],{"href":121},"serialization formats benchmark"," measures the saving per type.",[2845,2846,2847],"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 .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}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}","Bake constraints like email, UUID, int32 or positive straight into your types or schemas.","md",null,{"toc":18},{"title":30,"description":2848},"TU1ofXulLQJt4q7qB6er_WRxvfiKlOox9v9p_-dtAaE",[2855,2857],{"title":27,"path":22,"stem":28,"description":2856,"children":-1},"Describe a shape as a plain TypeScript type or with schema builders; both compile to the same thing.",{"title":34,"path":35,"stem":36,"description":2858,"children":-1},"JSON and binary codecs generated from your type, so Date, BigInt, Map and Set survive the round-trip.",1781995977801]