[{"data":1,"prerenderedAt":5191},["ShallowReactive",2],{"page-\u002Fjs\u002F28-typescript-essentials":3},{"id":4,"title":5,"body":6,"description":5184,"extension":5185,"meta":5186,"navigation":52,"path":5187,"seo":5188,"stem":5189,"__hash__":5190},"content\u002Fjs\u002F28-typescript-essentials.md","JavaScript 28 — TypeScript Essentials: Type System, Generics & Conditional Types",{"type":7,"value":8,"toc":5168},"minimark",[9,14,19,390,398,810,814,1509,1513,2086,2090,2816,2820,3383,3390,3655,3662,4017,4021,4418,4422,4714,4718,4722,4892,5164],[10,11,13],"h1",{"id":12},"_28-typescript-essentials-type-system-generics-conditional-types","28 — TypeScript Essentials: Type System, Generics & Conditional Types",[15,16,18],"h2",{"id":17},"structural-typing-vs-nominal-typing","Structural Typing vs Nominal Typing",[20,21,23],"code-wrapper",{"language":22},"typescript",[24,25,29],"pre",{"className":26,"code":27,"language":22,"meta":28,"style":28},"language-typescript shiki shiki-themes github-light github-dark","\u002F\u002F ── TypeScript uses STRUCTURAL typing (duck typing) ──\n\u002F\u002F Objects are compatible if their SHAPE matches — names don't matter.\n\ninterface User { id: number; name: string; }\ninterface Product { id: number; name: string; }\n\nconst user: User = { id: 1, name: \"Alice\" };\nconst product: Product = user;  \u002F\u002F ✅ compiles (same shape — structural compatibility)\n\u002F\u002F In nominal typing (Java, C#), this would fail (different types by name).\n\n\u002F\u002F ── Branded types: simulate nominal typing (distinguish same-shaped types) ──\ntype UserId = number & { readonly __brand: \"UserId\" };\ntype ProductId = number & { readonly __brand: \"ProductId\" };\n\nfunction getUser(id: UserId) { \u002F* ... *\u002F }\nfunction getProduct(id: ProductId) { \u002F* ... *\u002F }\n\nconst userId = 1 as UserId;  \u002F\u002F must cast (branding at creation)\nconst productId = 2 as ProductId;\n\ngetUser(userId);      \u002F\u002F ✅ correct brand\ngetProduct(userId);   \u002F\u002F ❌ Type 'UserId' is not assignable to type 'ProductId'\n\u002F\u002F Brands prevent mixing same-shaped types (UserId vs ProductId) — runtime safety.\n","",[30,31,32,41,47,54,94,120,125,157,177,183,188,194,225,252,257,284,306,311,335,355,360,372,384],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","\u002F\u002F ── TypeScript uses STRUCTURAL typing (duck typing) ──\n",[33,42,44],{"class":35,"line":43},2,[33,45,46],{"class":39},"\u002F\u002F Objects are compatible if their SHAPE matches — names don't matter.\n",[33,48,50],{"class":35,"line":49},3,[33,51,53],{"emptyLinePlaceholder":52},true,"\n",[33,55,57,61,65,69,73,76,80,83,86,88,91],{"class":35,"line":56},4,[33,58,60],{"class":59},"svdQ7","interface",[33,62,64],{"class":63},"sIsaT"," User",[33,66,68],{"class":67},"ssxIu"," { ",[33,70,72],{"class":71},"sCrzJ","id",[33,74,75],{"class":59},":",[33,77,79],{"class":78},"snvgF"," number",[33,81,82],{"class":67},"; ",[33,84,85],{"class":71},"name",[33,87,75],{"class":59},[33,89,90],{"class":78}," string",[33,92,93],{"class":67},"; }\n",[33,95,97,99,102,104,106,108,110,112,114,116,118],{"class":35,"line":96},5,[33,98,60],{"class":59},[33,100,101],{"class":63}," Product",[33,103,68],{"class":67},[33,105,72],{"class":71},[33,107,75],{"class":59},[33,109,79],{"class":78},[33,111,82],{"class":67},[33,113,85],{"class":71},[33,115,75],{"class":59},[33,117,90],{"class":78},[33,119,93],{"class":67},[33,121,123],{"class":35,"line":122},6,[33,124,53],{"emptyLinePlaceholder":52},[33,126,128,131,134,136,138,141,144,147,150,154],{"class":35,"line":127},7,[33,129,130],{"class":59},"const",[33,132,133],{"class":78}," user",[33,135,75],{"class":59},[33,137,64],{"class":63},[33,139,140],{"class":59}," =",[33,142,143],{"class":67}," { id: ",[33,145,146],{"class":78},"1",[33,148,149],{"class":67},", name: ",[33,151,153],{"class":152},"sJ6F3","\"Alice\"",[33,155,156],{"class":67}," };\n",[33,158,160,162,165,167,169,171,174],{"class":35,"line":159},8,[33,161,130],{"class":59},[33,163,164],{"class":78}," product",[33,166,75],{"class":59},[33,168,101],{"class":63},[33,170,140],{"class":59},[33,172,173],{"class":67}," user;  ",[33,175,176],{"class":39},"\u002F\u002F ✅ compiles (same shape — structural compatibility)\n",[33,178,180],{"class":35,"line":179},9,[33,181,182],{"class":39},"\u002F\u002F In nominal typing (Java, C#), this would fail (different types by name).\n",[33,184,186],{"class":35,"line":185},10,[33,187,53],{"emptyLinePlaceholder":52},[33,189,191],{"class":35,"line":190},11,[33,192,193],{"class":39},"\u002F\u002F ── Branded types: simulate nominal typing (distinguish same-shaped types) ──\n",[33,195,197,200,203,205,207,210,212,215,218,220,223],{"class":35,"line":196},12,[33,198,199],{"class":59},"type",[33,201,202],{"class":63}," UserId",[33,204,140],{"class":59},[33,206,79],{"class":78},[33,208,209],{"class":59}," &",[33,211,68],{"class":67},[33,213,214],{"class":59},"readonly",[33,216,217],{"class":71}," __brand",[33,219,75],{"class":59},[33,221,222],{"class":152}," \"UserId\"",[33,224,156],{"class":67},[33,226,228,230,233,235,237,239,241,243,245,247,250],{"class":35,"line":227},13,[33,229,199],{"class":59},[33,231,232],{"class":63}," ProductId",[33,234,140],{"class":59},[33,236,79],{"class":78},[33,238,209],{"class":59},[33,240,68],{"class":67},[33,242,214],{"class":59},[33,244,217],{"class":71},[33,246,75],{"class":59},[33,248,249],{"class":152}," \"ProductId\"",[33,251,156],{"class":67},[33,253,255],{"class":35,"line":254},14,[33,256,53],{"emptyLinePlaceholder":52},[33,258,260,263,266,269,271,273,275,278,281],{"class":35,"line":259},15,[33,261,262],{"class":59},"function",[33,264,265],{"class":63}," getUser",[33,267,268],{"class":67},"(",[33,270,72],{"class":71},[33,272,75],{"class":59},[33,274,202],{"class":63},[33,276,277],{"class":67},") { ",[33,279,280],{"class":39},"\u002F* ... *\u002F",[33,282,283],{"class":67}," }\n",[33,285,287,289,292,294,296,298,300,302,304],{"class":35,"line":286},16,[33,288,262],{"class":59},[33,290,291],{"class":63}," getProduct",[33,293,268],{"class":67},[33,295,72],{"class":71},[33,297,75],{"class":59},[33,299,232],{"class":63},[33,301,277],{"class":67},[33,303,280],{"class":39},[33,305,283],{"class":67},[33,307,309],{"class":35,"line":308},17,[33,310,53],{"emptyLinePlaceholder":52},[33,312,314,316,319,321,324,327,329,332],{"class":35,"line":313},18,[33,315,130],{"class":59},[33,317,318],{"class":78}," userId",[33,320,140],{"class":59},[33,322,323],{"class":78}," 1",[33,325,326],{"class":59}," as",[33,328,202],{"class":63},[33,330,331],{"class":67},";  ",[33,333,334],{"class":39},"\u002F\u002F must cast (branding at creation)\n",[33,336,338,340,343,345,348,350,352],{"class":35,"line":337},19,[33,339,130],{"class":59},[33,341,342],{"class":78}," productId",[33,344,140],{"class":59},[33,346,347],{"class":78}," 2",[33,349,326],{"class":59},[33,351,232],{"class":63},[33,353,354],{"class":67},";\n",[33,356,358],{"class":35,"line":357},20,[33,359,53],{"emptyLinePlaceholder":52},[33,361,363,366,369],{"class":35,"line":362},21,[33,364,365],{"class":63},"getUser",[33,367,368],{"class":67},"(userId);      ",[33,370,371],{"class":39},"\u002F\u002F ✅ correct brand\n",[33,373,375,378,381],{"class":35,"line":374},22,[33,376,377],{"class":63},"getProduct",[33,379,380],{"class":67},"(userId);   ",[33,382,383],{"class":39},"\u002F\u002F ❌ Type 'UserId' is not assignable to type 'ProductId'\n",[33,385,387],{"class":35,"line":386},23,[33,388,389],{"class":39},"\u002F\u002F Brands prevent mixing same-shaped types (UserId vs ProductId) — runtime safety.\n",[15,391,393,395,396],{"id":392},"type-vs-interface",[30,394,199],{}," vs ",[30,397,60],{},[20,399,400],{"language":22},[24,401,403],{"className":26,"code":402,"language":22,"meta":28,"style":28},"\u002F\u002F ── interface: object shapes, can be merged (declaration merging) ──\ninterface Window {\n    customProp: string;  \u002F\u002F augments the global Window interface\n}\ninterface Window {  \u002F\u002F declaration merging — adds to the existing interface\n    anotherProp: number;\n}\n\u002F\u002F window.customProp;  window.anotherProp;  \u002F\u002F both available\n\n\u002F\u002F ── type: more flexible (unions, intersections, primitives, mapped types) ──\ntype ID = number | string;           \u002F\u002F union (interface can't do this)\ntype Callback\u003CT> = (value: T) => void; \u002F\u002F function type\ntype Nullable\u003CT> = T | null;         \u002F\u002F conditional\u002Fgeneric type alias\ntype Pair = [string, number];        \u002F\u002F tuple (interface can't do this)\n\n\u002F\u002F ── When to use which ──\n\u002F\u002F interface: object shapes, class implementations, extensible (merging), public API\n\u002F\u002F type: unions, intersections, tuples, mapped types, utility types, internal types\n\n\u002F\u002F ── Extending ──\ninterface Animal { name: string; }\ninterface Dog extends Animal { bark(): void; }  \u002F\u002F interface extends interface\n\ntype Animal2 = { name: string };\ntype Dog2 = Animal2 & { bark(): void };  \u002F\u002F type intersection (&)\n\n\u002F\u002F ── Both can represent object shapes ──\ntype UserType = { id: number; name: string };\ninterface UserInterface { id: number; name: string; }\n\u002F\u002F Prefer interface for objects (extensible, better error messages)\n\u002F\u002F Prefer type for unions, intersections, and complex type logic\n",[30,404,405,410,420,434,439,451,462,466,474,478,483,505,549,577,604,608,613,618,623,627,632,649,679,683,703,733,738,744,772,798,804],{"__ignoreMap":28},[33,406,407],{"class":35,"line":36},[33,408,409],{"class":39},"\u002F\u002F ── interface: object shapes, can be merged (declaration merging) ──\n",[33,411,412,414,417],{"class":35,"line":43},[33,413,60],{"class":59},[33,415,416],{"class":63}," Window",[33,418,419],{"class":67}," {\n",[33,421,422,425,427,429,431],{"class":35,"line":49},[33,423,424],{"class":71},"    customProp",[33,426,75],{"class":59},[33,428,90],{"class":78},[33,430,331],{"class":67},[33,432,433],{"class":39},"\u002F\u002F augments the global Window interface\n",[33,435,436],{"class":35,"line":56},[33,437,438],{"class":67},"}\n",[33,440,441,443,445,448],{"class":35,"line":96},[33,442,60],{"class":59},[33,444,416],{"class":63},[33,446,447],{"class":67}," {  ",[33,449,450],{"class":39},"\u002F\u002F declaration merging — adds to the existing interface\n",[33,452,453,456,458,460],{"class":35,"line":122},[33,454,455],{"class":71},"    anotherProp",[33,457,75],{"class":59},[33,459,79],{"class":78},[33,461,354],{"class":67},[33,463,464],{"class":35,"line":127},[33,465,438],{"class":67},[33,467,468,471],{"class":35,"line":159},[33,469,470],{"class":39},"\u002F\u002F window.customProp;  window.anotherProp;",[33,472,473],{"class":39},"  \u002F\u002F both available\n",[33,475,476],{"class":35,"line":179},[33,477,53],{"emptyLinePlaceholder":52},[33,479,480],{"class":35,"line":185},[33,481,482],{"class":39},"\u002F\u002F ── type: more flexible (unions, intersections, primitives, mapped types) ──\n",[33,484,485,487,490,492,494,497,499,502],{"class":35,"line":190},[33,486,199],{"class":59},[33,488,489],{"class":63}," ID",[33,491,140],{"class":59},[33,493,79],{"class":78},[33,495,496],{"class":59}," |",[33,498,90],{"class":78},[33,500,501],{"class":67},";           ",[33,503,504],{"class":39},"\u002F\u002F union (interface can't do this)\n",[33,506,507,509,512,515,518,521,524,527,530,532,535,538,541,544,546],{"class":35,"line":196},[33,508,199],{"class":59},[33,510,511],{"class":63}," Callback",[33,513,514],{"class":67},"\u003C",[33,516,517],{"class":63},"T",[33,519,520],{"class":67},"> ",[33,522,523],{"class":59},"=",[33,525,526],{"class":67}," (",[33,528,529],{"class":71},"value",[33,531,75],{"class":59},[33,533,534],{"class":63}," T",[33,536,537],{"class":67},") ",[33,539,540],{"class":59},"=>",[33,542,543],{"class":78}," void",[33,545,82],{"class":67},[33,547,548],{"class":39},"\u002F\u002F function type\n",[33,550,551,553,556,558,560,562,564,566,568,571,574],{"class":35,"line":227},[33,552,199],{"class":59},[33,554,555],{"class":63}," Nullable",[33,557,514],{"class":67},[33,559,517],{"class":63},[33,561,520],{"class":67},[33,563,523],{"class":59},[33,565,534],{"class":63},[33,567,496],{"class":59},[33,569,570],{"class":78}," null",[33,572,573],{"class":67},";         ",[33,575,576],{"class":39},"\u002F\u002F conditional\u002Fgeneric type alias\n",[33,578,579,581,584,586,589,592,595,598,601],{"class":35,"line":254},[33,580,199],{"class":59},[33,582,583],{"class":63}," Pair",[33,585,140],{"class":59},[33,587,588],{"class":67}," [",[33,590,591],{"class":78},"string",[33,593,594],{"class":67},", ",[33,596,597],{"class":78},"number",[33,599,600],{"class":67},"];        ",[33,602,603],{"class":39},"\u002F\u002F tuple (interface can't do this)\n",[33,605,606],{"class":35,"line":259},[33,607,53],{"emptyLinePlaceholder":52},[33,609,610],{"class":35,"line":286},[33,611,612],{"class":39},"\u002F\u002F ── When to use which ──\n",[33,614,615],{"class":35,"line":308},[33,616,617],{"class":39},"\u002F\u002F interface: object shapes, class implementations, extensible (merging), public API\n",[33,619,620],{"class":35,"line":313},[33,621,622],{"class":39},"\u002F\u002F type: unions, intersections, tuples, mapped types, utility types, internal types\n",[33,624,625],{"class":35,"line":337},[33,626,53],{"emptyLinePlaceholder":52},[33,628,629],{"class":35,"line":357},[33,630,631],{"class":39},"\u002F\u002F ── Extending ──\n",[33,633,634,636,639,641,643,645,647],{"class":35,"line":362},[33,635,60],{"class":59},[33,637,638],{"class":63}," Animal",[33,640,68],{"class":67},[33,642,85],{"class":71},[33,644,75],{"class":59},[33,646,90],{"class":78},[33,648,93],{"class":67},[33,650,651,653,656,659,661,663,666,669,671,673,676],{"class":35,"line":374},[33,652,60],{"class":59},[33,654,655],{"class":63}," Dog",[33,657,658],{"class":59}," extends",[33,660,638],{"class":63},[33,662,68],{"class":67},[33,664,665],{"class":63},"bark",[33,667,668],{"class":67},"()",[33,670,75],{"class":59},[33,672,543],{"class":78},[33,674,675],{"class":67},"; }  ",[33,677,678],{"class":39},"\u002F\u002F interface extends interface\n",[33,680,681],{"class":35,"line":386},[33,682,53],{"emptyLinePlaceholder":52},[33,684,686,688,691,693,695,697,699,701],{"class":35,"line":685},24,[33,687,199],{"class":59},[33,689,690],{"class":63}," Animal2",[33,692,140],{"class":59},[33,694,68],{"class":67},[33,696,85],{"class":71},[33,698,75],{"class":59},[33,700,90],{"class":78},[33,702,156],{"class":67},[33,704,706,708,711,713,715,717,719,721,723,725,727,730],{"class":35,"line":705},25,[33,707,199],{"class":59},[33,709,710],{"class":63}," Dog2",[33,712,140],{"class":59},[33,714,690],{"class":63},[33,716,209],{"class":59},[33,718,68],{"class":67},[33,720,665],{"class":63},[33,722,668],{"class":67},[33,724,75],{"class":59},[33,726,543],{"class":78},[33,728,729],{"class":67}," };  ",[33,731,732],{"class":39},"\u002F\u002F type intersection (&)\n",[33,734,736],{"class":35,"line":735},26,[33,737,53],{"emptyLinePlaceholder":52},[33,739,741],{"class":35,"line":740},27,[33,742,743],{"class":39},"\u002F\u002F ── Both can represent object shapes ──\n",[33,745,747,749,752,754,756,758,760,762,764,766,768,770],{"class":35,"line":746},28,[33,748,199],{"class":59},[33,750,751],{"class":63}," UserType",[33,753,140],{"class":59},[33,755,68],{"class":67},[33,757,72],{"class":71},[33,759,75],{"class":59},[33,761,79],{"class":78},[33,763,82],{"class":67},[33,765,85],{"class":71},[33,767,75],{"class":59},[33,769,90],{"class":78},[33,771,156],{"class":67},[33,773,775,777,780,782,784,786,788,790,792,794,796],{"class":35,"line":774},29,[33,776,60],{"class":59},[33,778,779],{"class":63}," UserInterface",[33,781,68],{"class":67},[33,783,72],{"class":71},[33,785,75],{"class":59},[33,787,79],{"class":78},[33,789,82],{"class":67},[33,791,85],{"class":71},[33,793,75],{"class":59},[33,795,90],{"class":78},[33,797,93],{"class":67},[33,799,801],{"class":35,"line":800},30,[33,802,803],{"class":39},"\u002F\u002F Prefer interface for objects (extensible, better error messages)\n",[33,805,807],{"class":35,"line":806},31,[33,808,809],{"class":39},"\u002F\u002F Prefer type for unions, intersections, and complex type logic\n",[15,811,813],{"id":812},"generics-with-constraints","Generics with Constraints",[20,815,816],{"language":22},[24,817,819],{"className":26,"code":818,"language":22,"meta":28,"style":28},"\u002F\u002F ── Generic functions: preserve the input type through the function ──\nfunction identity\u003CT>(value: T): T {  \u002F\u002F T is a type parameter\n    return value;\n}\nconst result = identity(\"hello\");  \u002F\u002F T is inferred as string → result: string\nconst num = identity(42);          \u002F\u002F T is inferred as number → num: number\n\n\u002F\u002F ── Generic constraints: restrict what T can be (extends) ──\nfunction getLength\u003CT extends { length: number }>(value: T): number {\n    return value.length;  \u002F\u002F T must have a `length` property\n}\ngetLength(\"hello\");  \u002F\u002F ✅ string has length\ngetLength([1, 2, 3]); \u002F\u002F ✅ array has length\ngetLength(123);       \u002F\u002F ❌ number doesn't have length\n\n\u002F\u002F ── keyof constraint: get keys of a type ──\nfunction getProperty\u003CT, K extends keyof T>(obj: T, key: K): T[K] {\n    return obj[key];  \u002F\u002F return type is T[K] (the type of the property at key K)\n}\nconst user = { name: \"Alice\", age: 30 };\ngetProperty(user, \"name\");  \u002F\u002F returns string (type of user.name)\ngetProperty(user, \"age\");   \u002F\u002F returns number (type of user.age)\ngetProperty(user, \"email\"); \u002F\u002F ❌ \"email\" is not a key of user\n\n\u002F\u002F ── Generic class: type parameter on the class ──\nclass Stack\u003CT> {\n    private items: T[] = [];\n    push(item: T): void { this.items.push(item); }\n    pop(): T | undefined { return this.items.pop(); }\n    peek(): T | undefined { return this.items[this.items.length - 1]; }\n}\nconst numberStack = new Stack\u003Cnumber>();\nnumberStack.push(1);    \u002F\u002F ✅ number\nnumberStack.push(\"a\");  \u002F\u002F ❌ string is not assignable to number\n\n\u002F\u002F ── Default type parameters ──\nfunction createArray\u003CT = string>(length: number, value: T): T[] {\n    return Array.from({ length }, () => value);\n}\ncreateArray(3, \"x\");     \u002F\u002F T=string → string[]\ncreateArray\u003Cnumber>(3, 0); \u002F\u002F T=number → number[] (explicit)\n",[30,820,821,826,858,866,870,892,914,918,923,962,976,980,994,1019,1034,1038,1043,1099,1109,1113,1134,1150,1165,1180,1184,1189,1204,1224,1258,1290,1328,1332,1354,1372,1389,1394,1400,1441,1460,1465,1486],{"__ignoreMap":28},[33,822,823],{"class":35,"line":36},[33,824,825],{"class":39},"\u002F\u002F ── Generic functions: preserve the input type through the function ──\n",[33,827,828,830,833,835,837,840,842,844,846,849,851,853,855],{"class":35,"line":43},[33,829,262],{"class":59},[33,831,832],{"class":63}," identity",[33,834,514],{"class":67},[33,836,517],{"class":63},[33,838,839],{"class":67},">(",[33,841,529],{"class":71},[33,843,75],{"class":59},[33,845,534],{"class":63},[33,847,848],{"class":67},")",[33,850,75],{"class":59},[33,852,534],{"class":63},[33,854,447],{"class":67},[33,856,857],{"class":39},"\u002F\u002F T is a type parameter\n",[33,859,860,863],{"class":35,"line":49},[33,861,862],{"class":59},"    return",[33,864,865],{"class":67}," value;\n",[33,867,868],{"class":35,"line":56},[33,869,438],{"class":67},[33,871,872,874,877,879,881,883,886,889],{"class":35,"line":96},[33,873,130],{"class":59},[33,875,876],{"class":78}," result",[33,878,140],{"class":59},[33,880,832],{"class":63},[33,882,268],{"class":67},[33,884,885],{"class":152},"\"hello\"",[33,887,888],{"class":67},");  ",[33,890,891],{"class":39},"\u002F\u002F T is inferred as string → result: string\n",[33,893,894,896,899,901,903,905,908,911],{"class":35,"line":122},[33,895,130],{"class":59},[33,897,898],{"class":78}," num",[33,900,140],{"class":59},[33,902,832],{"class":63},[33,904,268],{"class":67},[33,906,907],{"class":78},"42",[33,909,910],{"class":67},");          ",[33,912,913],{"class":39},"\u002F\u002F T is inferred as number → num: number\n",[33,915,916],{"class":35,"line":127},[33,917,53],{"emptyLinePlaceholder":52},[33,919,920],{"class":35,"line":159},[33,921,922],{"class":39},"\u002F\u002F ── Generic constraints: restrict what T can be (extends) ──\n",[33,924,925,927,930,932,934,936,938,941,943,945,948,950,952,954,956,958,960],{"class":35,"line":179},[33,926,262],{"class":59},[33,928,929],{"class":63}," getLength",[33,931,514],{"class":67},[33,933,517],{"class":63},[33,935,658],{"class":59},[33,937,68],{"class":67},[33,939,940],{"class":71},"length",[33,942,75],{"class":59},[33,944,79],{"class":78},[33,946,947],{"class":67}," }>(",[33,949,529],{"class":71},[33,951,75],{"class":59},[33,953,534],{"class":63},[33,955,848],{"class":67},[33,957,75],{"class":59},[33,959,79],{"class":78},[33,961,419],{"class":67},[33,963,964,966,969,971,973],{"class":35,"line":185},[33,965,862],{"class":59},[33,967,968],{"class":67}," value.",[33,970,940],{"class":78},[33,972,331],{"class":67},[33,974,975],{"class":39},"\u002F\u002F T must have a `length` property\n",[33,977,978],{"class":35,"line":190},[33,979,438],{"class":67},[33,981,982,985,987,989,991],{"class":35,"line":196},[33,983,984],{"class":63},"getLength",[33,986,268],{"class":67},[33,988,885],{"class":152},[33,990,888],{"class":67},[33,992,993],{"class":39},"\u002F\u002F ✅ string has length\n",[33,995,996,998,1001,1003,1005,1008,1010,1013,1016],{"class":35,"line":227},[33,997,984],{"class":63},[33,999,1000],{"class":67},"([",[33,1002,146],{"class":78},[33,1004,594],{"class":67},[33,1006,1007],{"class":78},"2",[33,1009,594],{"class":67},[33,1011,1012],{"class":78},"3",[33,1014,1015],{"class":67},"]); ",[33,1017,1018],{"class":39},"\u002F\u002F ✅ array has length\n",[33,1020,1021,1023,1025,1028,1031],{"class":35,"line":254},[33,1022,984],{"class":63},[33,1024,268],{"class":67},[33,1026,1027],{"class":78},"123",[33,1029,1030],{"class":67},");       ",[33,1032,1033],{"class":39},"\u002F\u002F ❌ number doesn't have length\n",[33,1035,1036],{"class":35,"line":259},[33,1037,53],{"emptyLinePlaceholder":52},[33,1039,1040],{"class":35,"line":286},[33,1041,1042],{"class":39},"\u002F\u002F ── keyof constraint: get keys of a type ──\n",[33,1044,1045,1047,1050,1052,1054,1056,1059,1061,1064,1066,1068,1071,1073,1075,1077,1080,1082,1085,1087,1089,1091,1094,1096],{"class":35,"line":308},[33,1046,262],{"class":59},[33,1048,1049],{"class":63}," getProperty",[33,1051,514],{"class":67},[33,1053,517],{"class":63},[33,1055,594],{"class":67},[33,1057,1058],{"class":63},"K",[33,1060,658],{"class":59},[33,1062,1063],{"class":59}," keyof",[33,1065,534],{"class":63},[33,1067,839],{"class":67},[33,1069,1070],{"class":71},"obj",[33,1072,75],{"class":59},[33,1074,534],{"class":63},[33,1076,594],{"class":67},[33,1078,1079],{"class":71},"key",[33,1081,75],{"class":59},[33,1083,1084],{"class":63}," K",[33,1086,848],{"class":67},[33,1088,75],{"class":59},[33,1090,534],{"class":63},[33,1092,1093],{"class":67},"[",[33,1095,1058],{"class":63},[33,1097,1098],{"class":67},"] {\n",[33,1100,1101,1103,1106],{"class":35,"line":313},[33,1102,862],{"class":59},[33,1104,1105],{"class":67}," obj[key];  ",[33,1107,1108],{"class":39},"\u002F\u002F return type is T[K] (the type of the property at key K)\n",[33,1110,1111],{"class":35,"line":337},[33,1112,438],{"class":67},[33,1114,1115,1117,1119,1121,1124,1126,1129,1132],{"class":35,"line":357},[33,1116,130],{"class":59},[33,1118,133],{"class":78},[33,1120,140],{"class":59},[33,1122,1123],{"class":67}," { name: ",[33,1125,153],{"class":152},[33,1127,1128],{"class":67},", age: ",[33,1130,1131],{"class":78},"30",[33,1133,156],{"class":67},[33,1135,1136,1139,1142,1145,1147],{"class":35,"line":362},[33,1137,1138],{"class":63},"getProperty",[33,1140,1141],{"class":67},"(user, ",[33,1143,1144],{"class":152},"\"name\"",[33,1146,888],{"class":67},[33,1148,1149],{"class":39},"\u002F\u002F returns string (type of user.name)\n",[33,1151,1152,1154,1156,1159,1162],{"class":35,"line":374},[33,1153,1138],{"class":63},[33,1155,1141],{"class":67},[33,1157,1158],{"class":152},"\"age\"",[33,1160,1161],{"class":67},");   ",[33,1163,1164],{"class":39},"\u002F\u002F returns number (type of user.age)\n",[33,1166,1167,1169,1171,1174,1177],{"class":35,"line":386},[33,1168,1138],{"class":63},[33,1170,1141],{"class":67},[33,1172,1173],{"class":152},"\"email\"",[33,1175,1176],{"class":67},"); ",[33,1178,1179],{"class":39},"\u002F\u002F ❌ \"email\" is not a key of user\n",[33,1181,1182],{"class":35,"line":685},[33,1183,53],{"emptyLinePlaceholder":52},[33,1185,1186],{"class":35,"line":705},[33,1187,1188],{"class":39},"\u002F\u002F ── Generic class: type parameter on the class ──\n",[33,1190,1191,1194,1197,1199,1201],{"class":35,"line":735},[33,1192,1193],{"class":59},"class",[33,1195,1196],{"class":63}," Stack",[33,1198,514],{"class":67},[33,1200,517],{"class":63},[33,1202,1203],{"class":67},"> {\n",[33,1205,1206,1209,1212,1214,1216,1219,1221],{"class":35,"line":740},[33,1207,1208],{"class":59},"    private",[33,1210,1211],{"class":71}," items",[33,1213,75],{"class":59},[33,1215,534],{"class":63},[33,1217,1218],{"class":67},"[] ",[33,1220,523],{"class":59},[33,1222,1223],{"class":67}," [];\n",[33,1225,1226,1229,1231,1234,1236,1238,1240,1242,1244,1246,1249,1252,1255],{"class":35,"line":746},[33,1227,1228],{"class":63},"    push",[33,1230,268],{"class":67},[33,1232,1233],{"class":71},"item",[33,1235,75],{"class":59},[33,1237,534],{"class":63},[33,1239,848],{"class":67},[33,1241,75],{"class":59},[33,1243,543],{"class":78},[33,1245,68],{"class":67},[33,1247,1248],{"class":78},"this",[33,1250,1251],{"class":67},".items.",[33,1253,1254],{"class":63},"push",[33,1256,1257],{"class":67},"(item); }\n",[33,1259,1260,1263,1265,1267,1269,1271,1274,1276,1279,1282,1284,1287],{"class":35,"line":774},[33,1261,1262],{"class":63},"    pop",[33,1264,668],{"class":67},[33,1266,75],{"class":59},[33,1268,534],{"class":63},[33,1270,496],{"class":59},[33,1272,1273],{"class":78}," undefined",[33,1275,68],{"class":67},[33,1277,1278],{"class":59},"return",[33,1280,1281],{"class":78}," this",[33,1283,1251],{"class":67},[33,1285,1286],{"class":63},"pop",[33,1288,1289],{"class":67},"(); }\n",[33,1291,1292,1295,1297,1299,1301,1303,1305,1307,1309,1311,1314,1316,1318,1320,1323,1325],{"class":35,"line":800},[33,1293,1294],{"class":63},"    peek",[33,1296,668],{"class":67},[33,1298,75],{"class":59},[33,1300,534],{"class":63},[33,1302,496],{"class":59},[33,1304,1273],{"class":78},[33,1306,68],{"class":67},[33,1308,1278],{"class":59},[33,1310,1281],{"class":78},[33,1312,1313],{"class":67},".items[",[33,1315,1248],{"class":78},[33,1317,1251],{"class":67},[33,1319,940],{"class":78},[33,1321,1322],{"class":59}," -",[33,1324,323],{"class":78},[33,1326,1327],{"class":67},"]; }\n",[33,1329,1330],{"class":35,"line":806},[33,1331,438],{"class":67},[33,1333,1335,1337,1340,1342,1345,1347,1349,1351],{"class":35,"line":1334},32,[33,1336,130],{"class":59},[33,1338,1339],{"class":78}," numberStack",[33,1341,140],{"class":59},[33,1343,1344],{"class":59}," new",[33,1346,1196],{"class":63},[33,1348,514],{"class":67},[33,1350,597],{"class":78},[33,1352,1353],{"class":67},">();\n",[33,1355,1357,1360,1362,1364,1366,1369],{"class":35,"line":1356},33,[33,1358,1359],{"class":67},"numberStack.",[33,1361,1254],{"class":63},[33,1363,268],{"class":67},[33,1365,146],{"class":78},[33,1367,1368],{"class":67},");    ",[33,1370,1371],{"class":39},"\u002F\u002F ✅ number\n",[33,1373,1375,1377,1379,1381,1384,1386],{"class":35,"line":1374},34,[33,1376,1359],{"class":67},[33,1378,1254],{"class":63},[33,1380,268],{"class":67},[33,1382,1383],{"class":152},"\"a\"",[33,1385,888],{"class":67},[33,1387,1388],{"class":39},"\u002F\u002F ❌ string is not assignable to number\n",[33,1390,1392],{"class":35,"line":1391},35,[33,1393,53],{"emptyLinePlaceholder":52},[33,1395,1397],{"class":35,"line":1396},36,[33,1398,1399],{"class":39},"\u002F\u002F ── Default type parameters ──\n",[33,1401,1403,1405,1408,1410,1412,1414,1416,1418,1420,1422,1424,1426,1428,1430,1432,1434,1436,1438],{"class":35,"line":1402},37,[33,1404,262],{"class":59},[33,1406,1407],{"class":63}," createArray",[33,1409,514],{"class":67},[33,1411,517],{"class":63},[33,1413,140],{"class":59},[33,1415,90],{"class":78},[33,1417,839],{"class":67},[33,1419,940],{"class":71},[33,1421,75],{"class":59},[33,1423,79],{"class":78},[33,1425,594],{"class":67},[33,1427,529],{"class":71},[33,1429,75],{"class":59},[33,1431,534],{"class":63},[33,1433,848],{"class":67},[33,1435,75],{"class":59},[33,1437,534],{"class":63},[33,1439,1440],{"class":67},"[] {\n",[33,1442,1444,1446,1449,1452,1455,1457],{"class":35,"line":1443},38,[33,1445,862],{"class":59},[33,1447,1448],{"class":67}," Array.",[33,1450,1451],{"class":63},"from",[33,1453,1454],{"class":67},"({ length }, () ",[33,1456,540],{"class":59},[33,1458,1459],{"class":67}," value);\n",[33,1461,1463],{"class":35,"line":1462},39,[33,1464,438],{"class":67},[33,1466,1468,1471,1473,1475,1477,1480,1483],{"class":35,"line":1467},40,[33,1469,1470],{"class":63},"createArray",[33,1472,268],{"class":67},[33,1474,1012],{"class":78},[33,1476,594],{"class":67},[33,1478,1479],{"class":152},"\"x\"",[33,1481,1482],{"class":67},");     ",[33,1484,1485],{"class":39},"\u002F\u002F T=string → string[]\n",[33,1487,1489,1491,1493,1495,1497,1499,1501,1504,1506],{"class":35,"line":1488},41,[33,1490,1470],{"class":63},[33,1492,514],{"class":67},[33,1494,597],{"class":78},[33,1496,839],{"class":67},[33,1498,1012],{"class":78},[33,1500,594],{"class":67},[33,1502,1503],{"class":78},"0",[33,1505,1176],{"class":67},[33,1507,1508],{"class":39},"\u002F\u002F T=number → number[] (explicit)\n",[15,1510,1512],{"id":1511},"conditional-types-and-inference","Conditional Types and Inference",[20,1514,1515],{"language":22},[24,1516,1518],{"className":26,"code":1517,"language":22,"meta":28,"style":28},"\u002F\u002F ── Conditional types: type-level if\u002Felse ──\ntype IsString\u003CT> = T extends string ? \"yes\" : \"no\";\ntype A = IsString\u003Cstring>;  \u002F\u002F \"yes\"\ntype B = IsString\u003Cnumber>;  \u002F\u002F \"no\"\n\n\u002F\u002F ── infer: extract a type from another type (within a conditional) ──\ntype ReturnType\u003CT> = T extends (...args: any[]) => infer R ? R : never;\n\u002F\u002F If T is a function, infer its return type as R; otherwise, never.\ntype F = ReturnType\u003C() => string>;  \u002F\u002F string\ntype G = ReturnType\u003C(x: number) => boolean>;  \u002F\u002F boolean\n\n\u002F\u002F ── Extract promise inner type ──\ntype Awaited2\u003CT> = T extends Promise\u003Cinfer U> ? U : T;\ntype H = Awaited2\u003CPromise\u003Cnumber>>;  \u002F\u002F number\ntype I = Awaited2\u003Cstring>;           \u002F\u002F string (not a promise → returns itself)\n\n\u002F\u002F ── Extract array element type ──\ntype ElementOf\u003CT> = T extends (infer E)[] ? E : never;\ntype J = ElementOf\u003Cstring[]>;  \u002F\u002F string\ntype K = ElementOf\u003Cnumber[]>;  \u002F\u002F number\n\n\u002F\u002F ── Extract function parameters ──\ntype FirstParam\u003CT> = T extends (first: infer P, ...rest: any[]) => any ? P : never;\ntype L = FirstParam\u003C(name: string, age: number) => void>;  \u002F\u002F string\n\n\u002F\u002F ── Distributive conditional types (union distributes) ──\ntype ToArray\u003CT> = T extends any ? T[] : never;\ntype M = ToArray\u003Cstring | number>;  \u002F\u002F string[] | number[] (distributed over the union)\n\u002F\u002F NOT (string | number)[] — each union member is processed separately.\n",[30,1519,1520,1525,1560,1581,1601,1605,1610,1664,1669,1692,1725,1729,1734,1777,1803,1824,1828,1833,1872,1892,1910,1914,1919,1977,2015,2019,2024,2057,2081],{"__ignoreMap":28},[33,1521,1522],{"class":35,"line":36},[33,1523,1524],{"class":39},"\u002F\u002F ── Conditional types: type-level if\u002Felse ──\n",[33,1526,1527,1529,1532,1534,1536,1538,1540,1542,1544,1546,1549,1552,1555,1558],{"class":35,"line":43},[33,1528,199],{"class":59},[33,1530,1531],{"class":63}," IsString",[33,1533,514],{"class":67},[33,1535,517],{"class":63},[33,1537,520],{"class":67},[33,1539,523],{"class":59},[33,1541,534],{"class":63},[33,1543,658],{"class":59},[33,1545,90],{"class":78},[33,1547,1548],{"class":59}," ?",[33,1550,1551],{"class":152}," \"yes\"",[33,1553,1554],{"class":59}," :",[33,1556,1557],{"class":152}," \"no\"",[33,1559,354],{"class":67},[33,1561,1562,1564,1567,1569,1571,1573,1575,1578],{"class":35,"line":49},[33,1563,199],{"class":59},[33,1565,1566],{"class":63}," A",[33,1568,140],{"class":59},[33,1570,1531],{"class":63},[33,1572,514],{"class":67},[33,1574,591],{"class":78},[33,1576,1577],{"class":67},">;  ",[33,1579,1580],{"class":39},"\u002F\u002F \"yes\"\n",[33,1582,1583,1585,1588,1590,1592,1594,1596,1598],{"class":35,"line":56},[33,1584,199],{"class":59},[33,1586,1587],{"class":63}," B",[33,1589,140],{"class":59},[33,1591,1531],{"class":63},[33,1593,514],{"class":67},[33,1595,597],{"class":78},[33,1597,1577],{"class":67},[33,1599,1600],{"class":39},"\u002F\u002F \"no\"\n",[33,1602,1603],{"class":35,"line":96},[33,1604,53],{"emptyLinePlaceholder":52},[33,1606,1607],{"class":35,"line":122},[33,1608,1609],{"class":39},"\u002F\u002F ── infer: extract a type from another type (within a conditional) ──\n",[33,1611,1612,1614,1617,1619,1621,1623,1625,1627,1629,1631,1634,1637,1639,1642,1645,1647,1650,1653,1655,1657,1659,1662],{"class":35,"line":127},[33,1613,199],{"class":59},[33,1615,1616],{"class":63}," ReturnType",[33,1618,514],{"class":67},[33,1620,517],{"class":63},[33,1622,520],{"class":67},[33,1624,523],{"class":59},[33,1626,534],{"class":63},[33,1628,658],{"class":59},[33,1630,526],{"class":67},[33,1632,1633],{"class":59},"...",[33,1635,1636],{"class":71},"args",[33,1638,75],{"class":59},[33,1640,1641],{"class":78}," any",[33,1643,1644],{"class":67},"[]) ",[33,1646,540],{"class":59},[33,1648,1649],{"class":59}," infer",[33,1651,1652],{"class":63}," R",[33,1654,1548],{"class":59},[33,1656,1652],{"class":63},[33,1658,1554],{"class":59},[33,1660,1661],{"class":78}," never",[33,1663,354],{"class":67},[33,1665,1666],{"class":35,"line":159},[33,1667,1668],{"class":39},"\u002F\u002F If T is a function, infer its return type as R; otherwise, never.\n",[33,1670,1671,1673,1676,1678,1680,1683,1685,1687,1689],{"class":35,"line":179},[33,1672,199],{"class":59},[33,1674,1675],{"class":63}," F",[33,1677,140],{"class":59},[33,1679,1616],{"class":63},[33,1681,1682],{"class":67},"\u003C() ",[33,1684,540],{"class":59},[33,1686,90],{"class":78},[33,1688,1577],{"class":67},[33,1690,1691],{"class":39},"\u002F\u002F string\n",[33,1693,1694,1696,1699,1701,1703,1706,1709,1711,1713,1715,1717,1720,1722],{"class":35,"line":185},[33,1695,199],{"class":59},[33,1697,1698],{"class":63}," G",[33,1700,140],{"class":59},[33,1702,1616],{"class":63},[33,1704,1705],{"class":67},"\u003C(",[33,1707,1708],{"class":71},"x",[33,1710,75],{"class":59},[33,1712,79],{"class":78},[33,1714,537],{"class":67},[33,1716,540],{"class":59},[33,1718,1719],{"class":78}," boolean",[33,1721,1577],{"class":67},[33,1723,1724],{"class":39},"\u002F\u002F boolean\n",[33,1726,1727],{"class":35,"line":190},[33,1728,53],{"emptyLinePlaceholder":52},[33,1730,1731],{"class":35,"line":196},[33,1732,1733],{"class":39},"\u002F\u002F ── Extract promise inner type ──\n",[33,1735,1736,1738,1741,1743,1745,1747,1749,1751,1753,1756,1758,1761,1764,1766,1769,1771,1773,1775],{"class":35,"line":227},[33,1737,199],{"class":59},[33,1739,1740],{"class":63}," Awaited2",[33,1742,514],{"class":67},[33,1744,517],{"class":63},[33,1746,520],{"class":67},[33,1748,523],{"class":59},[33,1750,534],{"class":63},[33,1752,658],{"class":59},[33,1754,1755],{"class":63}," Promise",[33,1757,514],{"class":67},[33,1759,1760],{"class":59},"infer",[33,1762,1763],{"class":63}," U",[33,1765,520],{"class":67},[33,1767,1768],{"class":59},"?",[33,1770,1763],{"class":63},[33,1772,1554],{"class":59},[33,1774,534],{"class":63},[33,1776,354],{"class":67},[33,1778,1779,1781,1784,1786,1788,1790,1793,1795,1797,1800],{"class":35,"line":254},[33,1780,199],{"class":59},[33,1782,1783],{"class":63}," H",[33,1785,140],{"class":59},[33,1787,1740],{"class":63},[33,1789,514],{"class":67},[33,1791,1792],{"class":63},"Promise",[33,1794,514],{"class":67},[33,1796,597],{"class":78},[33,1798,1799],{"class":67},">>;  ",[33,1801,1802],{"class":39},"\u002F\u002F number\n",[33,1804,1805,1807,1810,1812,1814,1816,1818,1821],{"class":35,"line":259},[33,1806,199],{"class":59},[33,1808,1809],{"class":63}," I",[33,1811,140],{"class":59},[33,1813,1740],{"class":63},[33,1815,514],{"class":67},[33,1817,591],{"class":78},[33,1819,1820],{"class":67},">;           ",[33,1822,1823],{"class":39},"\u002F\u002F string (not a promise → returns itself)\n",[33,1825,1826],{"class":35,"line":286},[33,1827,53],{"emptyLinePlaceholder":52},[33,1829,1830],{"class":35,"line":308},[33,1831,1832],{"class":39},"\u002F\u002F ── Extract array element type ──\n",[33,1834,1835,1837,1840,1842,1844,1846,1848,1850,1852,1854,1856,1859,1862,1864,1866,1868,1870],{"class":35,"line":313},[33,1836,199],{"class":59},[33,1838,1839],{"class":63}," ElementOf",[33,1841,514],{"class":67},[33,1843,517],{"class":63},[33,1845,520],{"class":67},[33,1847,523],{"class":59},[33,1849,534],{"class":63},[33,1851,658],{"class":59},[33,1853,526],{"class":67},[33,1855,1760],{"class":59},[33,1857,1858],{"class":63}," E",[33,1860,1861],{"class":67},")[] ",[33,1863,1768],{"class":59},[33,1865,1858],{"class":63},[33,1867,1554],{"class":59},[33,1869,1661],{"class":78},[33,1871,354],{"class":67},[33,1873,1874,1876,1879,1881,1883,1885,1887,1890],{"class":35,"line":337},[33,1875,199],{"class":59},[33,1877,1878],{"class":63}," J",[33,1880,140],{"class":59},[33,1882,1839],{"class":63},[33,1884,514],{"class":67},[33,1886,591],{"class":78},[33,1888,1889],{"class":67},"[]>;  ",[33,1891,1691],{"class":39},[33,1893,1894,1896,1898,1900,1902,1904,1906,1908],{"class":35,"line":357},[33,1895,199],{"class":59},[33,1897,1084],{"class":63},[33,1899,140],{"class":59},[33,1901,1839],{"class":63},[33,1903,514],{"class":67},[33,1905,597],{"class":78},[33,1907,1889],{"class":67},[33,1909,1802],{"class":39},[33,1911,1912],{"class":35,"line":362},[33,1913,53],{"emptyLinePlaceholder":52},[33,1915,1916],{"class":35,"line":374},[33,1917,1918],{"class":39},"\u002F\u002F ── Extract function parameters ──\n",[33,1920,1921,1923,1926,1928,1930,1932,1934,1936,1938,1940,1943,1945,1947,1950,1952,1954,1957,1959,1961,1963,1965,1967,1969,1971,1973,1975],{"class":35,"line":386},[33,1922,199],{"class":59},[33,1924,1925],{"class":63}," FirstParam",[33,1927,514],{"class":67},[33,1929,517],{"class":63},[33,1931,520],{"class":67},[33,1933,523],{"class":59},[33,1935,534],{"class":63},[33,1937,658],{"class":59},[33,1939,526],{"class":67},[33,1941,1942],{"class":71},"first",[33,1944,75],{"class":59},[33,1946,1649],{"class":59},[33,1948,1949],{"class":63}," P",[33,1951,594],{"class":67},[33,1953,1633],{"class":59},[33,1955,1956],{"class":71},"rest",[33,1958,75],{"class":59},[33,1960,1641],{"class":78},[33,1962,1644],{"class":67},[33,1964,540],{"class":59},[33,1966,1641],{"class":78},[33,1968,1548],{"class":59},[33,1970,1949],{"class":63},[33,1972,1554],{"class":59},[33,1974,1661],{"class":78},[33,1976,354],{"class":67},[33,1978,1979,1981,1984,1986,1988,1990,1992,1994,1996,1998,2001,2003,2005,2007,2009,2011,2013],{"class":35,"line":685},[33,1980,199],{"class":59},[33,1982,1983],{"class":63}," L",[33,1985,140],{"class":59},[33,1987,1925],{"class":63},[33,1989,1705],{"class":67},[33,1991,85],{"class":71},[33,1993,75],{"class":59},[33,1995,90],{"class":78},[33,1997,594],{"class":67},[33,1999,2000],{"class":71},"age",[33,2002,75],{"class":59},[33,2004,79],{"class":78},[33,2006,537],{"class":67},[33,2008,540],{"class":59},[33,2010,543],{"class":78},[33,2012,1577],{"class":67},[33,2014,1691],{"class":39},[33,2016,2017],{"class":35,"line":705},[33,2018,53],{"emptyLinePlaceholder":52},[33,2020,2021],{"class":35,"line":735},[33,2022,2023],{"class":39},"\u002F\u002F ── Distributive conditional types (union distributes) ──\n",[33,2025,2026,2028,2031,2033,2035,2037,2039,2041,2043,2045,2047,2049,2051,2053,2055],{"class":35,"line":740},[33,2027,199],{"class":59},[33,2029,2030],{"class":63}," ToArray",[33,2032,514],{"class":67},[33,2034,517],{"class":63},[33,2036,520],{"class":67},[33,2038,523],{"class":59},[33,2040,534],{"class":63},[33,2042,658],{"class":59},[33,2044,1641],{"class":78},[33,2046,1548],{"class":59},[33,2048,534],{"class":63},[33,2050,1218],{"class":67},[33,2052,75],{"class":59},[33,2054,1661],{"class":78},[33,2056,354],{"class":67},[33,2058,2059,2061,2064,2066,2068,2070,2072,2074,2076,2078],{"class":35,"line":746},[33,2060,199],{"class":59},[33,2062,2063],{"class":63}," M",[33,2065,140],{"class":59},[33,2067,2030],{"class":63},[33,2069,514],{"class":67},[33,2071,591],{"class":78},[33,2073,496],{"class":59},[33,2075,79],{"class":78},[33,2077,1577],{"class":67},[33,2079,2080],{"class":39},"\u002F\u002F string[] | number[] (distributed over the union)\n",[33,2082,2083],{"class":35,"line":774},[33,2084,2085],{"class":39},"\u002F\u002F NOT (string | number)[] — each union member is processed separately.\n",[15,2087,2089],{"id":2088},"mapped-types-and-utility-types","Mapped Types and Utility Types",[20,2091,2092],{"language":22},[24,2093,2095],{"className":26,"code":2094,"language":22,"meta":28,"style":28},"\u002F\u002F ── Mapped types: transform properties (type-level loops) ──\ntype Readonly\u003CT> = {\n    readonly [K in keyof T]: T[K];  \u002F\u002F iterate over keys, make each readonly\n};\ntype Optional\u003CT> = {\n    [K in keyof T]?: T[K];  \u002F\u002F make each property optional\n};\ntype Nullable\u003CT> = {\n    [K in keyof T]: T[K] | null;  \u002F\u002F make each property nullable\n};\n\ninterface User { id: number; name: string; email: string; }\ntype ReadonlyUser = Readonly\u003CUser>;     \u002F\u002F { readonly id: number; readonly name: string; ... }\ntype OptionalUser = Optional\u003CUser>;     \u002F\u002F { id?: number; name?: string; ... }\ntype NullableUser = Nullable\u003CUser>;     \u002F\u002F { id: number | null; name: string | null; ... }\n\n\u002F\u002F ── Key remapping (TypeScript 4.1+) ──\ntype Getters\u003CT> = {\n    [K in keyof T as `get${Capitalize\u003Cstring & K>}`]: () => T[K];\n    \u002F\u002F remap key: `getName`, `getEmail`, etc. (template literal + Capitalize)\n};\ntype UserGetters = Getters\u003CUser>;\n\u002F\u002F { getId: () => number; getName: () => string; getEmail: () => string }\n\n\u002F\u002F ── Built-in utility types ──\ntype PartialUser = Partial\u003CUser>;         \u002F\u002F all properties optional\ntype RequiredUser = Required\u003CUser>;       \u002F\u002F all properties required (remove ?)\ntype ReadonlyUser2 = Readonly\u003CUser>;      \u002F\u002F all properties readonly\ntype PickUser = Pick\u003CUser, \"id\" | \"name\">; \u002F\u002F { id: number; name: string } (select keys)\ntype OmitUser = Omit\u003CUser, \"email\">;      \u002F\u002F { id: number; name: string } (remove keys)\ntype RecordType = Record\u003Cstring, number>; \u002F\u002F { [key: string]: number } (key → value map)\ntype ReturnTypeT = ReturnType\u003C() => string>; \u002F\u002F string (function return type)\ntype ParametersT = Parameters\u003C(x: number, y: string) => void>; \u002F\u002F [number, string]\ntype AwaitedT = Awaited\u003CPromise\u003Cstring[]>>;  \u002F\u002F string[] (unwrap Promise)\ntype ExcludeT = Exclude\u003C\"a\" | \"b\" | \"c\", \"a\">;  \u002F\u002F \"b\" | \"c\" (remove from union)\ntype ExtractT = Extract\u003C\"a\" | \"b\" | \"c\", \"a\" | \"b\">;  \u002F\u002F \"a\" | \"b\" (keep from union)\ntype NonNullableT = NonNullable\u003Cstring | null | undefined>;  \u002F\u002F string (remove null\u002Fundefined)\n",[30,2096,2097,2102,2119,2152,2157,2174,2203,2207,2223,2258,2262,2266,2299,2321,2341,2361,2365,2370,2387,2439,2444,2448,2466,2471,2475,2480,2502,2524,2545,2577,2602,2627,2649,2689,2715,2750,2787],{"__ignoreMap":28},[33,2098,2099],{"class":35,"line":36},[33,2100,2101],{"class":39},"\u002F\u002F ── Mapped types: transform properties (type-level loops) ──\n",[33,2103,2104,2106,2109,2111,2113,2115,2117],{"class":35,"line":43},[33,2105,199],{"class":59},[33,2107,2108],{"class":63}," Readonly",[33,2110,514],{"class":67},[33,2112,517],{"class":63},[33,2114,520],{"class":67},[33,2116,523],{"class":59},[33,2118,419],{"class":67},[33,2120,2121,2124,2126,2128,2131,2133,2135,2138,2140,2142,2144,2146,2149],{"class":35,"line":49},[33,2122,2123],{"class":59},"    readonly",[33,2125,588],{"class":67},[33,2127,1058],{"class":63},[33,2129,2130],{"class":59}," in",[33,2132,1063],{"class":59},[33,2134,534],{"class":63},[33,2136,2137],{"class":67},"]",[33,2139,75],{"class":59},[33,2141,534],{"class":63},[33,2143,1093],{"class":67},[33,2145,1058],{"class":63},[33,2147,2148],{"class":67},"];  ",[33,2150,2151],{"class":39},"\u002F\u002F iterate over keys, make each readonly\n",[33,2153,2154],{"class":35,"line":56},[33,2155,2156],{"class":67},"};\n",[33,2158,2159,2161,2164,2166,2168,2170,2172],{"class":35,"line":96},[33,2160,199],{"class":59},[33,2162,2163],{"class":63}," Optional",[33,2165,514],{"class":67},[33,2167,517],{"class":63},[33,2169,520],{"class":67},[33,2171,523],{"class":59},[33,2173,419],{"class":67},[33,2175,2176,2179,2181,2183,2185,2187,2189,2192,2194,2196,2198,2200],{"class":35,"line":122},[33,2177,2178],{"class":67},"    [",[33,2180,1058],{"class":63},[33,2182,2130],{"class":59},[33,2184,1063],{"class":59},[33,2186,534],{"class":63},[33,2188,2137],{"class":67},[33,2190,2191],{"class":59},"?:",[33,2193,534],{"class":63},[33,2195,1093],{"class":67},[33,2197,1058],{"class":63},[33,2199,2148],{"class":67},[33,2201,2202],{"class":39},"\u002F\u002F make each property optional\n",[33,2204,2205],{"class":35,"line":127},[33,2206,2156],{"class":67},[33,2208,2209,2211,2213,2215,2217,2219,2221],{"class":35,"line":159},[33,2210,199],{"class":59},[33,2212,555],{"class":63},[33,2214,514],{"class":67},[33,2216,517],{"class":63},[33,2218,520],{"class":67},[33,2220,523],{"class":59},[33,2222,419],{"class":67},[33,2224,2225,2227,2229,2231,2233,2235,2237,2239,2241,2243,2245,2248,2251,2253,2255],{"class":35,"line":179},[33,2226,2178],{"class":67},[33,2228,1058],{"class":63},[33,2230,2130],{"class":59},[33,2232,1063],{"class":59},[33,2234,534],{"class":63},[33,2236,2137],{"class":67},[33,2238,75],{"class":59},[33,2240,534],{"class":63},[33,2242,1093],{"class":67},[33,2244,1058],{"class":63},[33,2246,2247],{"class":67},"] ",[33,2249,2250],{"class":59},"|",[33,2252,570],{"class":78},[33,2254,331],{"class":67},[33,2256,2257],{"class":39},"\u002F\u002F make each property nullable\n",[33,2259,2260],{"class":35,"line":185},[33,2261,2156],{"class":67},[33,2263,2264],{"class":35,"line":190},[33,2265,53],{"emptyLinePlaceholder":52},[33,2267,2268,2270,2272,2274,2276,2278,2280,2282,2284,2286,2288,2290,2293,2295,2297],{"class":35,"line":196},[33,2269,60],{"class":59},[33,2271,64],{"class":63},[33,2273,68],{"class":67},[33,2275,72],{"class":71},[33,2277,75],{"class":59},[33,2279,79],{"class":78},[33,2281,82],{"class":67},[33,2283,85],{"class":71},[33,2285,75],{"class":59},[33,2287,90],{"class":78},[33,2289,82],{"class":67},[33,2291,2292],{"class":71},"email",[33,2294,75],{"class":59},[33,2296,90],{"class":78},[33,2298,93],{"class":67},[33,2300,2301,2303,2306,2308,2310,2312,2315,2318],{"class":35,"line":227},[33,2302,199],{"class":59},[33,2304,2305],{"class":63}," ReadonlyUser",[33,2307,140],{"class":59},[33,2309,2108],{"class":63},[33,2311,514],{"class":67},[33,2313,2314],{"class":63},"User",[33,2316,2317],{"class":67},">;     ",[33,2319,2320],{"class":39},"\u002F\u002F { readonly id: number; readonly name: string; ... }\n",[33,2322,2323,2325,2328,2330,2332,2334,2336,2338],{"class":35,"line":254},[33,2324,199],{"class":59},[33,2326,2327],{"class":63}," OptionalUser",[33,2329,140],{"class":59},[33,2331,2163],{"class":63},[33,2333,514],{"class":67},[33,2335,2314],{"class":63},[33,2337,2317],{"class":67},[33,2339,2340],{"class":39},"\u002F\u002F { id?: number; name?: string; ... }\n",[33,2342,2343,2345,2348,2350,2352,2354,2356,2358],{"class":35,"line":259},[33,2344,199],{"class":59},[33,2346,2347],{"class":63}," NullableUser",[33,2349,140],{"class":59},[33,2351,555],{"class":63},[33,2353,514],{"class":67},[33,2355,2314],{"class":63},[33,2357,2317],{"class":67},[33,2359,2360],{"class":39},"\u002F\u002F { id: number | null; name: string | null; ... }\n",[33,2362,2363],{"class":35,"line":286},[33,2364,53],{"emptyLinePlaceholder":52},[33,2366,2367],{"class":35,"line":308},[33,2368,2369],{"class":39},"\u002F\u002F ── Key remapping (TypeScript 4.1+) ──\n",[33,2371,2372,2374,2377,2379,2381,2383,2385],{"class":35,"line":313},[33,2373,199],{"class":59},[33,2375,2376],{"class":63}," Getters",[33,2378,514],{"class":67},[33,2380,517],{"class":63},[33,2382,520],{"class":67},[33,2384,523],{"class":59},[33,2386,419],{"class":67},[33,2388,2389,2391,2393,2395,2397,2399,2401,2404,2407,2409,2411,2413,2415,2418,2421,2423,2425,2428,2430,2432,2434,2436],{"class":35,"line":337},[33,2390,2178],{"class":67},[33,2392,1058],{"class":63},[33,2394,2130],{"class":59},[33,2396,1063],{"class":59},[33,2398,534],{"class":63},[33,2400,326],{"class":59},[33,2402,2403],{"class":152}," `get${",[33,2405,2406],{"class":63},"Capitalize",[33,2408,514],{"class":152},[33,2410,591],{"class":78},[33,2412,209],{"class":59},[33,2414,1084],{"class":63},[33,2416,2417],{"class":152},">",[33,2419,2420],{"class":152},"}`",[33,2422,2137],{"class":67},[33,2424,75],{"class":59},[33,2426,2427],{"class":67}," () ",[33,2429,540],{"class":59},[33,2431,534],{"class":63},[33,2433,1093],{"class":67},[33,2435,1058],{"class":63},[33,2437,2438],{"class":67},"];\n",[33,2440,2441],{"class":35,"line":357},[33,2442,2443],{"class":39},"    \u002F\u002F remap key: `getName`, `getEmail`, etc. (template literal + Capitalize)\n",[33,2445,2446],{"class":35,"line":362},[33,2447,2156],{"class":67},[33,2449,2450,2452,2455,2457,2459,2461,2463],{"class":35,"line":374},[33,2451,199],{"class":59},[33,2453,2454],{"class":63}," UserGetters",[33,2456,140],{"class":59},[33,2458,2376],{"class":63},[33,2460,514],{"class":67},[33,2462,2314],{"class":63},[33,2464,2465],{"class":67},">;\n",[33,2467,2468],{"class":35,"line":386},[33,2469,2470],{"class":39},"\u002F\u002F { getId: () => number; getName: () => string; getEmail: () => string }\n",[33,2472,2473],{"class":35,"line":685},[33,2474,53],{"emptyLinePlaceholder":52},[33,2476,2477],{"class":35,"line":705},[33,2478,2479],{"class":39},"\u002F\u002F ── Built-in utility types ──\n",[33,2481,2482,2484,2487,2489,2492,2494,2496,2499],{"class":35,"line":735},[33,2483,199],{"class":59},[33,2485,2486],{"class":63}," PartialUser",[33,2488,140],{"class":59},[33,2490,2491],{"class":63}," Partial",[33,2493,514],{"class":67},[33,2495,2314],{"class":63},[33,2497,2498],{"class":67},">;         ",[33,2500,2501],{"class":39},"\u002F\u002F all properties optional\n",[33,2503,2504,2506,2509,2511,2514,2516,2518,2521],{"class":35,"line":740},[33,2505,199],{"class":59},[33,2507,2508],{"class":63}," RequiredUser",[33,2510,140],{"class":59},[33,2512,2513],{"class":63}," Required",[33,2515,514],{"class":67},[33,2517,2314],{"class":63},[33,2519,2520],{"class":67},">;       ",[33,2522,2523],{"class":39},"\u002F\u002F all properties required (remove ?)\n",[33,2525,2526,2528,2531,2533,2535,2537,2539,2542],{"class":35,"line":746},[33,2527,199],{"class":59},[33,2529,2530],{"class":63}," ReadonlyUser2",[33,2532,140],{"class":59},[33,2534,2108],{"class":63},[33,2536,514],{"class":67},[33,2538,2314],{"class":63},[33,2540,2541],{"class":67},">;      ",[33,2543,2544],{"class":39},"\u002F\u002F all properties readonly\n",[33,2546,2547,2549,2552,2554,2557,2559,2561,2563,2566,2568,2571,2574],{"class":35,"line":774},[33,2548,199],{"class":59},[33,2550,2551],{"class":63}," PickUser",[33,2553,140],{"class":59},[33,2555,2556],{"class":63}," Pick",[33,2558,514],{"class":67},[33,2560,2314],{"class":63},[33,2562,594],{"class":67},[33,2564,2565],{"class":152},"\"id\"",[33,2567,496],{"class":59},[33,2569,2570],{"class":152}," \"name\"",[33,2572,2573],{"class":67},">; ",[33,2575,2576],{"class":39},"\u002F\u002F { id: number; name: string } (select keys)\n",[33,2578,2579,2581,2584,2586,2589,2591,2593,2595,2597,2599],{"class":35,"line":800},[33,2580,199],{"class":59},[33,2582,2583],{"class":63}," OmitUser",[33,2585,140],{"class":59},[33,2587,2588],{"class":63}," Omit",[33,2590,514],{"class":67},[33,2592,2314],{"class":63},[33,2594,594],{"class":67},[33,2596,1173],{"class":152},[33,2598,2541],{"class":67},[33,2600,2601],{"class":39},"\u002F\u002F { id: number; name: string } (remove keys)\n",[33,2603,2604,2606,2609,2611,2614,2616,2618,2620,2622,2624],{"class":35,"line":806},[33,2605,199],{"class":59},[33,2607,2608],{"class":63}," RecordType",[33,2610,140],{"class":59},[33,2612,2613],{"class":63}," Record",[33,2615,514],{"class":67},[33,2617,591],{"class":78},[33,2619,594],{"class":67},[33,2621,597],{"class":78},[33,2623,2573],{"class":67},[33,2625,2626],{"class":39},"\u002F\u002F { [key: string]: number } (key → value map)\n",[33,2628,2629,2631,2634,2636,2638,2640,2642,2644,2646],{"class":35,"line":1334},[33,2630,199],{"class":59},[33,2632,2633],{"class":63}," ReturnTypeT",[33,2635,140],{"class":59},[33,2637,1616],{"class":63},[33,2639,1682],{"class":67},[33,2641,540],{"class":59},[33,2643,90],{"class":78},[33,2645,2573],{"class":67},[33,2647,2648],{"class":39},"\u002F\u002F string (function return type)\n",[33,2650,2651,2653,2656,2658,2661,2663,2665,2667,2669,2671,2674,2676,2678,2680,2682,2684,2686],{"class":35,"line":1356},[33,2652,199],{"class":59},[33,2654,2655],{"class":63}," ParametersT",[33,2657,140],{"class":59},[33,2659,2660],{"class":63}," Parameters",[33,2662,1705],{"class":67},[33,2664,1708],{"class":71},[33,2666,75],{"class":59},[33,2668,79],{"class":78},[33,2670,594],{"class":67},[33,2672,2673],{"class":71},"y",[33,2675,75],{"class":59},[33,2677,90],{"class":78},[33,2679,537],{"class":67},[33,2681,540],{"class":59},[33,2683,543],{"class":78},[33,2685,2573],{"class":67},[33,2687,2688],{"class":39},"\u002F\u002F [number, string]\n",[33,2690,2691,2693,2696,2698,2701,2703,2705,2707,2709,2712],{"class":35,"line":1374},[33,2692,199],{"class":59},[33,2694,2695],{"class":63}," AwaitedT",[33,2697,140],{"class":59},[33,2699,2700],{"class":63}," Awaited",[33,2702,514],{"class":67},[33,2704,1792],{"class":63},[33,2706,514],{"class":67},[33,2708,591],{"class":78},[33,2710,2711],{"class":67},"[]>>;  ",[33,2713,2714],{"class":39},"\u002F\u002F string[] (unwrap Promise)\n",[33,2716,2717,2719,2722,2724,2727,2729,2731,2733,2736,2738,2741,2743,2745,2747],{"class":35,"line":1391},[33,2718,199],{"class":59},[33,2720,2721],{"class":63}," ExcludeT",[33,2723,140],{"class":59},[33,2725,2726],{"class":63}," Exclude",[33,2728,514],{"class":67},[33,2730,1383],{"class":152},[33,2732,496],{"class":59},[33,2734,2735],{"class":152}," \"b\"",[33,2737,496],{"class":59},[33,2739,2740],{"class":152}," \"c\"",[33,2742,594],{"class":67},[33,2744,1383],{"class":152},[33,2746,1577],{"class":67},[33,2748,2749],{"class":39},"\u002F\u002F \"b\" | \"c\" (remove from union)\n",[33,2751,2752,2754,2757,2759,2762,2764,2766,2768,2770,2772,2774,2776,2778,2780,2782,2784],{"class":35,"line":1396},[33,2753,199],{"class":59},[33,2755,2756],{"class":63}," ExtractT",[33,2758,140],{"class":59},[33,2760,2761],{"class":63}," Extract",[33,2763,514],{"class":67},[33,2765,1383],{"class":152},[33,2767,496],{"class":59},[33,2769,2735],{"class":152},[33,2771,496],{"class":59},[33,2773,2740],{"class":152},[33,2775,594],{"class":67},[33,2777,1383],{"class":152},[33,2779,496],{"class":59},[33,2781,2735],{"class":152},[33,2783,1577],{"class":67},[33,2785,2786],{"class":39},"\u002F\u002F \"a\" | \"b\" (keep from union)\n",[33,2788,2789,2791,2794,2796,2799,2801,2803,2805,2807,2809,2811,2813],{"class":35,"line":1402},[33,2790,199],{"class":59},[33,2792,2793],{"class":63}," NonNullableT",[33,2795,140],{"class":59},[33,2797,2798],{"class":63}," NonNullable",[33,2800,514],{"class":67},[33,2802,591],{"class":78},[33,2804,496],{"class":59},[33,2806,570],{"class":78},[33,2808,496],{"class":59},[33,2810,1273],{"class":78},[33,2812,1577],{"class":67},[33,2814,2815],{"class":39},"\u002F\u002F string (remove null\u002Fundefined)\n",[15,2817,2819],{"id":2818},"type-narrowing-and-guards","Type Narrowing and Guards",[20,2821,2822],{"language":22},[24,2823,2825],{"className":26,"code":2824,"language":22,"meta":28,"style":28},"\u002F\u002F ── Type narrowing: refine the type within a conditional branch ──\nfunction process(value: string | number) {\n    if (typeof value === \"string\") {\n        value.toUpperCase();  \u002F\u002F narrowed to string\n    } else {\n        value.toFixed(2);  \u002F\u002F narrowed to number\n    }\n}\n\n\u002F\u002F ── instanceof narrowing (class types) ──\nfunction handleError(error: Error | string) {\n    if (error instanceof Error) {\n        error.message;  \u002F\u002F narrowed to Error\n    } else {\n        error.trim();  \u002F\u002F narrowed to string\n    }\n}\n\n\u002F\u002F ── in narrowing (property check) ──\ninterface Cat { meow(): void; }\ninterface Dog { bark(): void; }\nfunction speak(animal: Cat | Dog) {\n    if (\"meow\" in animal) {\n        animal.meow();  \u002F\u002F narrowed to Cat\n    } else {\n        animal.bark();  \u002F\u002F narrowed to Dog\n    }\n}\n\n\u002F\u002F ── Custom type guards (user-defined type predicates) ──\nfunction isString(value: unknown): value is string {  \u002F\u002F `value is string` is the predicate\n    return typeof value === \"string\";\n}\nfunction processUnknown(value: unknown) {\n    if (isString(value)) {\n        value.toUpperCase();  \u002F\u002F narrowed to string (type guard worked)\n    }\n}\n\n\u002F\u002F ── Discriminated unions (narrowing on a common property) ──\ntype Result =\n    | { status: \"success\"; data: string }\n    | { status: \"error\"; message: string };\n\nfunction handle(result: Result) {\n    if (result.status === \"success\") {\n        result.data;  \u002F\u002F narrowed to the success variant\n    } else {\n        result.message;  \u002F\u002F narrowed to the error variant\n    }\n}\n",[30,2826,2827,2832,2854,2875,2889,2899,2915,2920,2924,2928,2933,2956,2970,2978,2986,2998,3002,3006,3010,3015,3035,3053,3075,3089,3101,3109,3120,3124,3128,3132,3137,3170,3185,3189,3206,3218,3229,3233,3237,3241,3246,3256,3283,3308,3313,3332,3346,3355,3364,3373,3378],{"__ignoreMap":28},[33,2828,2829],{"class":35,"line":36},[33,2830,2831],{"class":39},"\u002F\u002F ── Type narrowing: refine the type within a conditional branch ──\n",[33,2833,2834,2836,2839,2841,2843,2845,2847,2849,2851],{"class":35,"line":43},[33,2835,262],{"class":59},[33,2837,2838],{"class":63}," process",[33,2840,268],{"class":67},[33,2842,529],{"class":71},[33,2844,75],{"class":59},[33,2846,90],{"class":78},[33,2848,496],{"class":59},[33,2850,79],{"class":78},[33,2852,2853],{"class":67},") {\n",[33,2855,2856,2859,2861,2864,2867,2870,2873],{"class":35,"line":49},[33,2857,2858],{"class":59},"    if",[33,2860,526],{"class":67},[33,2862,2863],{"class":59},"typeof",[33,2865,2866],{"class":67}," value ",[33,2868,2869],{"class":59},"===",[33,2871,2872],{"class":152}," \"string\"",[33,2874,2853],{"class":67},[33,2876,2877,2880,2883,2886],{"class":35,"line":56},[33,2878,2879],{"class":67},"        value.",[33,2881,2882],{"class":63},"toUpperCase",[33,2884,2885],{"class":67},"();  ",[33,2887,2888],{"class":39},"\u002F\u002F narrowed to string\n",[33,2890,2891,2894,2897],{"class":35,"line":96},[33,2892,2893],{"class":67},"    } ",[33,2895,2896],{"class":59},"else",[33,2898,419],{"class":67},[33,2900,2901,2903,2906,2908,2910,2912],{"class":35,"line":122},[33,2902,2879],{"class":67},[33,2904,2905],{"class":63},"toFixed",[33,2907,268],{"class":67},[33,2909,1007],{"class":78},[33,2911,888],{"class":67},[33,2913,2914],{"class":39},"\u002F\u002F narrowed to number\n",[33,2916,2917],{"class":35,"line":127},[33,2918,2919],{"class":67},"    }\n",[33,2921,2922],{"class":35,"line":159},[33,2923,438],{"class":67},[33,2925,2926],{"class":35,"line":179},[33,2927,53],{"emptyLinePlaceholder":52},[33,2929,2930],{"class":35,"line":185},[33,2931,2932],{"class":39},"\u002F\u002F ── instanceof narrowing (class types) ──\n",[33,2934,2935,2937,2940,2942,2945,2947,2950,2952,2954],{"class":35,"line":190},[33,2936,262],{"class":59},[33,2938,2939],{"class":63}," handleError",[33,2941,268],{"class":67},[33,2943,2944],{"class":71},"error",[33,2946,75],{"class":59},[33,2948,2949],{"class":63}," Error",[33,2951,496],{"class":59},[33,2953,90],{"class":78},[33,2955,2853],{"class":67},[33,2957,2958,2960,2963,2966,2968],{"class":35,"line":196},[33,2959,2858],{"class":59},[33,2961,2962],{"class":67}," (error ",[33,2964,2965],{"class":59},"instanceof",[33,2967,2949],{"class":63},[33,2969,2853],{"class":67},[33,2971,2972,2975],{"class":35,"line":227},[33,2973,2974],{"class":67},"        error.message;  ",[33,2976,2977],{"class":39},"\u002F\u002F narrowed to Error\n",[33,2979,2980,2982,2984],{"class":35,"line":254},[33,2981,2893],{"class":67},[33,2983,2896],{"class":59},[33,2985,419],{"class":67},[33,2987,2988,2991,2994,2996],{"class":35,"line":259},[33,2989,2990],{"class":67},"        error.",[33,2992,2993],{"class":63},"trim",[33,2995,2885],{"class":67},[33,2997,2888],{"class":39},[33,2999,3000],{"class":35,"line":286},[33,3001,2919],{"class":67},[33,3003,3004],{"class":35,"line":308},[33,3005,438],{"class":67},[33,3007,3008],{"class":35,"line":313},[33,3009,53],{"emptyLinePlaceholder":52},[33,3011,3012],{"class":35,"line":337},[33,3013,3014],{"class":39},"\u002F\u002F ── in narrowing (property check) ──\n",[33,3016,3017,3019,3022,3024,3027,3029,3031,3033],{"class":35,"line":357},[33,3018,60],{"class":59},[33,3020,3021],{"class":63}," Cat",[33,3023,68],{"class":67},[33,3025,3026],{"class":63},"meow",[33,3028,668],{"class":67},[33,3030,75],{"class":59},[33,3032,543],{"class":78},[33,3034,93],{"class":67},[33,3036,3037,3039,3041,3043,3045,3047,3049,3051],{"class":35,"line":362},[33,3038,60],{"class":59},[33,3040,655],{"class":63},[33,3042,68],{"class":67},[33,3044,665],{"class":63},[33,3046,668],{"class":67},[33,3048,75],{"class":59},[33,3050,543],{"class":78},[33,3052,93],{"class":67},[33,3054,3055,3057,3060,3062,3065,3067,3069,3071,3073],{"class":35,"line":374},[33,3056,262],{"class":59},[33,3058,3059],{"class":63}," speak",[33,3061,268],{"class":67},[33,3063,3064],{"class":71},"animal",[33,3066,75],{"class":59},[33,3068,3021],{"class":63},[33,3070,496],{"class":59},[33,3072,655],{"class":63},[33,3074,2853],{"class":67},[33,3076,3077,3079,3081,3084,3086],{"class":35,"line":386},[33,3078,2858],{"class":59},[33,3080,526],{"class":67},[33,3082,3083],{"class":152},"\"meow\"",[33,3085,2130],{"class":59},[33,3087,3088],{"class":67}," animal) {\n",[33,3090,3091,3094,3096,3098],{"class":35,"line":685},[33,3092,3093],{"class":67},"        animal.",[33,3095,3026],{"class":63},[33,3097,2885],{"class":67},[33,3099,3100],{"class":39},"\u002F\u002F narrowed to Cat\n",[33,3102,3103,3105,3107],{"class":35,"line":705},[33,3104,2893],{"class":67},[33,3106,2896],{"class":59},[33,3108,419],{"class":67},[33,3110,3111,3113,3115,3117],{"class":35,"line":735},[33,3112,3093],{"class":67},[33,3114,665],{"class":63},[33,3116,2885],{"class":67},[33,3118,3119],{"class":39},"\u002F\u002F narrowed to Dog\n",[33,3121,3122],{"class":35,"line":740},[33,3123,2919],{"class":67},[33,3125,3126],{"class":35,"line":746},[33,3127,438],{"class":67},[33,3129,3130],{"class":35,"line":774},[33,3131,53],{"emptyLinePlaceholder":52},[33,3133,3134],{"class":35,"line":800},[33,3135,3136],{"class":39},"\u002F\u002F ── Custom type guards (user-defined type predicates) ──\n",[33,3138,3139,3141,3144,3146,3148,3150,3153,3155,3157,3160,3163,3165,3167],{"class":35,"line":806},[33,3140,262],{"class":59},[33,3142,3143],{"class":63}," isString",[33,3145,268],{"class":67},[33,3147,529],{"class":71},[33,3149,75],{"class":59},[33,3151,3152],{"class":78}," unknown",[33,3154,848],{"class":67},[33,3156,75],{"class":59},[33,3158,3159],{"class":71}," value",[33,3161,3162],{"class":59}," is",[33,3164,90],{"class":78},[33,3166,447],{"class":67},[33,3168,3169],{"class":39},"\u002F\u002F `value is string` is the predicate\n",[33,3171,3172,3174,3177,3179,3181,3183],{"class":35,"line":1334},[33,3173,862],{"class":59},[33,3175,3176],{"class":59}," typeof",[33,3178,2866],{"class":67},[33,3180,2869],{"class":59},[33,3182,2872],{"class":152},[33,3184,354],{"class":67},[33,3186,3187],{"class":35,"line":1356},[33,3188,438],{"class":67},[33,3190,3191,3193,3196,3198,3200,3202,3204],{"class":35,"line":1374},[33,3192,262],{"class":59},[33,3194,3195],{"class":63}," processUnknown",[33,3197,268],{"class":67},[33,3199,529],{"class":71},[33,3201,75],{"class":59},[33,3203,3152],{"class":78},[33,3205,2853],{"class":67},[33,3207,3208,3210,3212,3215],{"class":35,"line":1391},[33,3209,2858],{"class":59},[33,3211,526],{"class":67},[33,3213,3214],{"class":63},"isString",[33,3216,3217],{"class":67},"(value)) {\n",[33,3219,3220,3222,3224,3226],{"class":35,"line":1396},[33,3221,2879],{"class":67},[33,3223,2882],{"class":63},[33,3225,2885],{"class":67},[33,3227,3228],{"class":39},"\u002F\u002F narrowed to string (type guard worked)\n",[33,3230,3231],{"class":35,"line":1402},[33,3232,2919],{"class":67},[33,3234,3235],{"class":35,"line":1443},[33,3236,438],{"class":67},[33,3238,3239],{"class":35,"line":1462},[33,3240,53],{"emptyLinePlaceholder":52},[33,3242,3243],{"class":35,"line":1467},[33,3244,3245],{"class":39},"\u002F\u002F ── Discriminated unions (narrowing on a common property) ──\n",[33,3247,3248,3250,3253],{"class":35,"line":1488},[33,3249,199],{"class":59},[33,3251,3252],{"class":63}," Result",[33,3254,3255],{"class":59}," =\n",[33,3257,3259,3262,3264,3267,3269,3272,3274,3277,3279,3281],{"class":35,"line":3258},42,[33,3260,3261],{"class":59},"    |",[33,3263,68],{"class":67},[33,3265,3266],{"class":71},"status",[33,3268,75],{"class":59},[33,3270,3271],{"class":152}," \"success\"",[33,3273,82],{"class":67},[33,3275,3276],{"class":71},"data",[33,3278,75],{"class":59},[33,3280,90],{"class":78},[33,3282,283],{"class":67},[33,3284,3286,3288,3290,3292,3294,3297,3299,3302,3304,3306],{"class":35,"line":3285},43,[33,3287,3261],{"class":59},[33,3289,68],{"class":67},[33,3291,3266],{"class":71},[33,3293,75],{"class":59},[33,3295,3296],{"class":152}," \"error\"",[33,3298,82],{"class":67},[33,3300,3301],{"class":71},"message",[33,3303,75],{"class":59},[33,3305,90],{"class":78},[33,3307,156],{"class":67},[33,3309,3311],{"class":35,"line":3310},44,[33,3312,53],{"emptyLinePlaceholder":52},[33,3314,3316,3318,3321,3323,3326,3328,3330],{"class":35,"line":3315},45,[33,3317,262],{"class":59},[33,3319,3320],{"class":63}," handle",[33,3322,268],{"class":67},[33,3324,3325],{"class":71},"result",[33,3327,75],{"class":59},[33,3329,3252],{"class":63},[33,3331,2853],{"class":67},[33,3333,3335,3337,3340,3342,3344],{"class":35,"line":3334},46,[33,3336,2858],{"class":59},[33,3338,3339],{"class":67}," (result.status ",[33,3341,2869],{"class":59},[33,3343,3271],{"class":152},[33,3345,2853],{"class":67},[33,3347,3349,3352],{"class":35,"line":3348},47,[33,3350,3351],{"class":67},"        result.data;  ",[33,3353,3354],{"class":39},"\u002F\u002F narrowed to the success variant\n",[33,3356,3358,3360,3362],{"class":35,"line":3357},48,[33,3359,2893],{"class":67},[33,3361,2896],{"class":59},[33,3363,419],{"class":67},[33,3365,3367,3370],{"class":35,"line":3366},49,[33,3368,3369],{"class":67},"        result.message;  ",[33,3371,3372],{"class":39},"\u002F\u002F narrowed to the error variant\n",[33,3374,3376],{"class":35,"line":3375},50,[33,3377,2919],{"class":67},[33,3379,3381],{"class":35,"line":3380},51,[33,3382,438],{"class":67},[15,3384,3386,3387,848],{"id":3385},"declaration-files-dts","Declaration Files (",[30,3388,3389],{},".d.ts",[20,3391,3392],{"language":22},[24,3393,3395],{"className":26,"code":3394,"language":22,"meta":28,"style":28},"\u002F\u002F ── Declaration files: type definitions for JavaScript libraries ──\n\u002F\u002F .d.ts files contain only types (no runtime code) — describe the shape of a JS module.\n\n\u002F\u002F ── global.d.ts: declare global types ──\ndeclare global {\n    interface Window {\n        myCustomAPI: {\n            init: () => void;\n            track: (event: string) => void;\n        };\n    }\n}\n\u002F\u002F Now `window.myCustomAPI` is typed throughout the project.\n\n\u002F\u002F ── module.d.ts: declare types for an untyped JS module ──\n\u002F\u002F untyped-lib.d.ts:\ndeclare module \"untyped-lib\" {\n    export function greet(name: string): string;\n    export const version: string;\n    export type Config = { timeout: number; retries: number };\n}\n\n\u002F\u002F ── Ambient declarations (declare without implementation) ──\ndeclare const API_URL: string;  \u002F\u002F provided by webpack DefinePlugin or Vite define\n\u002F\u002F tsconfig.json: \"compilerOptions\": { \"typeRoots\": [\".\u002Fnode_modules\u002F@types\", \".\u002Fsrc\u002Ftypes\"] }\n\n\u002F\u002F ── DefinitelyTyped (@types\u002F*) ──\n\u002F\u002F npm install --save-dev @types\u002Fexpress  → provides express.d.ts\n\u002F\u002F If a library ships its own types (package.json \"types\" field), no @types needed.\n",[30,3396,3397,3402,3407,3411,3416,3424,3433,3442,3457,3481,3486,3490,3494,3499,3503,3508,3513,3525,3552,3568,3600,3604,3608,3613,3631,3636,3640,3645,3650],{"__ignoreMap":28},[33,3398,3399],{"class":35,"line":36},[33,3400,3401],{"class":39},"\u002F\u002F ── Declaration files: type definitions for JavaScript libraries ──\n",[33,3403,3404],{"class":35,"line":43},[33,3405,3406],{"class":39},"\u002F\u002F .d.ts files contain only types (no runtime code) — describe the shape of a JS module.\n",[33,3408,3409],{"class":35,"line":49},[33,3410,53],{"emptyLinePlaceholder":52},[33,3412,3413],{"class":35,"line":56},[33,3414,3415],{"class":39},"\u002F\u002F ── global.d.ts: declare global types ──\n",[33,3417,3418,3421],{"class":35,"line":96},[33,3419,3420],{"class":59},"declare",[33,3422,3423],{"class":67}," global {\n",[33,3425,3426,3429,3431],{"class":35,"line":122},[33,3427,3428],{"class":59},"    interface",[33,3430,416],{"class":63},[33,3432,419],{"class":67},[33,3434,3435,3438,3440],{"class":35,"line":127},[33,3436,3437],{"class":71},"        myCustomAPI",[33,3439,75],{"class":59},[33,3441,419],{"class":67},[33,3443,3444,3447,3449,3451,3453,3455],{"class":35,"line":159},[33,3445,3446],{"class":63},"            init",[33,3448,75],{"class":59},[33,3450,2427],{"class":67},[33,3452,540],{"class":59},[33,3454,543],{"class":78},[33,3456,354],{"class":67},[33,3458,3459,3462,3464,3466,3469,3471,3473,3475,3477,3479],{"class":35,"line":179},[33,3460,3461],{"class":63},"            track",[33,3463,75],{"class":59},[33,3465,526],{"class":67},[33,3467,3468],{"class":71},"event",[33,3470,75],{"class":59},[33,3472,90],{"class":78},[33,3474,537],{"class":67},[33,3476,540],{"class":59},[33,3478,543],{"class":78},[33,3480,354],{"class":67},[33,3482,3483],{"class":35,"line":185},[33,3484,3485],{"class":67},"        };\n",[33,3487,3488],{"class":35,"line":190},[33,3489,2919],{"class":67},[33,3491,3492],{"class":35,"line":196},[33,3493,438],{"class":67},[33,3495,3496],{"class":35,"line":227},[33,3497,3498],{"class":39},"\u002F\u002F Now `window.myCustomAPI` is typed throughout the project.\n",[33,3500,3501],{"class":35,"line":254},[33,3502,53],{"emptyLinePlaceholder":52},[33,3504,3505],{"class":35,"line":259},[33,3506,3507],{"class":39},"\u002F\u002F ── module.d.ts: declare types for an untyped JS module ──\n",[33,3509,3510],{"class":35,"line":286},[33,3511,3512],{"class":39},"\u002F\u002F untyped-lib.d.ts:\n",[33,3514,3515,3517,3520,3523],{"class":35,"line":308},[33,3516,3420],{"class":59},[33,3518,3519],{"class":59}," module",[33,3521,3522],{"class":152}," \"untyped-lib\"",[33,3524,419],{"class":67},[33,3526,3527,3530,3533,3536,3538,3540,3542,3544,3546,3548,3550],{"class":35,"line":313},[33,3528,3529],{"class":59},"    export",[33,3531,3532],{"class":59}," function",[33,3534,3535],{"class":63}," greet",[33,3537,268],{"class":67},[33,3539,85],{"class":71},[33,3541,75],{"class":59},[33,3543,90],{"class":78},[33,3545,848],{"class":67},[33,3547,75],{"class":59},[33,3549,90],{"class":78},[33,3551,354],{"class":67},[33,3553,3554,3556,3559,3562,3564,3566],{"class":35,"line":337},[33,3555,3529],{"class":59},[33,3557,3558],{"class":59}," const",[33,3560,3561],{"class":78}," version",[33,3563,75],{"class":59},[33,3565,90],{"class":78},[33,3567,354],{"class":67},[33,3569,3570,3572,3575,3578,3580,3582,3585,3587,3589,3591,3594,3596,3598],{"class":35,"line":357},[33,3571,3529],{"class":59},[33,3573,3574],{"class":59}," type",[33,3576,3577],{"class":63}," Config",[33,3579,140],{"class":59},[33,3581,68],{"class":67},[33,3583,3584],{"class":71},"timeout",[33,3586,75],{"class":59},[33,3588,79],{"class":78},[33,3590,82],{"class":67},[33,3592,3593],{"class":71},"retries",[33,3595,75],{"class":59},[33,3597,79],{"class":78},[33,3599,156],{"class":67},[33,3601,3602],{"class":35,"line":362},[33,3603,438],{"class":67},[33,3605,3606],{"class":35,"line":374},[33,3607,53],{"emptyLinePlaceholder":52},[33,3609,3610],{"class":35,"line":386},[33,3611,3612],{"class":39},"\u002F\u002F ── Ambient declarations (declare without implementation) ──\n",[33,3614,3615,3617,3619,3622,3624,3626,3628],{"class":35,"line":685},[33,3616,3420],{"class":59},[33,3618,3558],{"class":59},[33,3620,3621],{"class":78}," API_URL",[33,3623,75],{"class":59},[33,3625,90],{"class":78},[33,3627,331],{"class":67},[33,3629,3630],{"class":39},"\u002F\u002F provided by webpack DefinePlugin or Vite define\n",[33,3632,3633],{"class":35,"line":705},[33,3634,3635],{"class":39},"\u002F\u002F tsconfig.json: \"compilerOptions\": { \"typeRoots\": [\".\u002Fnode_modules\u002F@types\", \".\u002Fsrc\u002Ftypes\"] }\n",[33,3637,3638],{"class":35,"line":735},[33,3639,53],{"emptyLinePlaceholder":52},[33,3641,3642],{"class":35,"line":740},[33,3643,3644],{"class":39},"\u002F\u002F ── DefinitelyTyped (@types\u002F*) ──\n",[33,3646,3647],{"class":35,"line":746},[33,3648,3649],{"class":39},"\u002F\u002F npm install --save-dev @types\u002Fexpress  → provides express.d.ts\n",[33,3651,3652],{"class":35,"line":774},[33,3653,3654],{"class":39},"\u002F\u002F If a library ships its own types (package.json \"types\" field), no @types needed.\n",[15,3656,3658,3661],{"id":3657},"tsconfigjson-configuration",[30,3659,3660],{},"tsconfig.json"," Configuration",[20,3663,3665],{"language":3664},"json",[24,3666,3669],{"className":3667,"code":3668,"language":3664,"meta":28,"style":28},"language-json shiki shiki-themes github-light github-dark","{\n  \"compilerOptions\": {\n    \"target\": \"ES2022\",           \u002F\u002F output JS version\n    \"module\": \"ESNext\",           \u002F\u002F module system (ESM)\n    \"moduleResolution\": \"bundler\",\u002F\u002F how modules are resolved (bundler for Vite\u002Fwebpack)\n    \"lib\": [\"ES2022\", \"DOM\"],     \u002F\u002F available type definitions\n    \"strict\": true,               \u002F\u002F enable all strict checks (recommended)\n    \"noUncheckedIndexedAccess\": true, \u002F\u002F arr[0] is T | undefined (not just T)\n    \"noImplicitReturns\": true,    \u002F\u002F error if not all code paths return\n    \"noFallthroughCasesInSwitch\": true, \u002F\u002F error on switch fall-through\n    \"exactOptionalPropertyTypes\": true, \u002F\u002F optional props can't be explicitly undefined\n    \"esModuleInterop\": true,      \u002F\u002F allow default import from CJS modules\n    \"skipLibCheck\": true,         \u002F\u002F skip type checking of .d.ts files (faster)\n    \"forceConsistentCasingInFileNames\": true,\n    \"resolveJsonModule\": true,    \u002F\u002F allow importing .json files\n    \"isolatedModules\": true,      \u002F\u002F each file is compiled independently (Vite requirement)\n    \"verbatimModuleSyntax\": true, \u002F\u002F enforce type-only imports (import type)\n    \"outDir\": \".\u002Fdist\",           \u002F\u002F output directory\n    \"rootDir\": \".\u002Fsrc\",           \u002F\u002F source root\n    \"baseUrl\": \".\",               \u002F\u002F base for path mapping\n    \"paths\": { \"@\u002F*\": [\".\u002Fsrc\u002F*\"] } \u002F\u002F path alias: import from \"@\u002F...\"\n  },\n  \"include\": [\"src\u002F**\u002F*\"],\n  \"exclude\": [\"node_modules\", \"dist\"]\n}\n",[30,3670,3671,3676,3684,3701,3716,3732,3753,3769,3783,3798,3812,3826,3841,3856,3868,3882,3896,3910,3925,3940,3955,3977,3982,3995,4013],{"__ignoreMap":28},[33,3672,3673],{"class":35,"line":36},[33,3674,3675],{"class":67},"{\n",[33,3677,3678,3681],{"class":35,"line":43},[33,3679,3680],{"class":78},"  \"compilerOptions\"",[33,3682,3683],{"class":67},": {\n",[33,3685,3686,3689,3692,3695,3698],{"class":35,"line":49},[33,3687,3688],{"class":78},"    \"target\"",[33,3690,3691],{"class":67},": ",[33,3693,3694],{"class":152},"\"ES2022\"",[33,3696,3697],{"class":67},",           ",[33,3699,3700],{"class":39},"\u002F\u002F output JS version\n",[33,3702,3703,3706,3708,3711,3713],{"class":35,"line":56},[33,3704,3705],{"class":78},"    \"module\"",[33,3707,3691],{"class":67},[33,3709,3710],{"class":152},"\"ESNext\"",[33,3712,3697],{"class":67},[33,3714,3715],{"class":39},"\u002F\u002F module system (ESM)\n",[33,3717,3718,3721,3723,3726,3729],{"class":35,"line":96},[33,3719,3720],{"class":78},"    \"moduleResolution\"",[33,3722,3691],{"class":67},[33,3724,3725],{"class":152},"\"bundler\"",[33,3727,3728],{"class":67},",",[33,3730,3731],{"class":39},"\u002F\u002F how modules are resolved (bundler for Vite\u002Fwebpack)\n",[33,3733,3734,3737,3740,3742,3744,3747,3750],{"class":35,"line":122},[33,3735,3736],{"class":78},"    \"lib\"",[33,3738,3739],{"class":67},": [",[33,3741,3694],{"class":152},[33,3743,594],{"class":67},[33,3745,3746],{"class":152},"\"DOM\"",[33,3748,3749],{"class":67},"],     ",[33,3751,3752],{"class":39},"\u002F\u002F available type definitions\n",[33,3754,3755,3758,3760,3763,3766],{"class":35,"line":127},[33,3756,3757],{"class":78},"    \"strict\"",[33,3759,3691],{"class":67},[33,3761,3762],{"class":78},"true",[33,3764,3765],{"class":67},",               ",[33,3767,3768],{"class":39},"\u002F\u002F enable all strict checks (recommended)\n",[33,3770,3771,3774,3776,3778,3780],{"class":35,"line":159},[33,3772,3773],{"class":78},"    \"noUncheckedIndexedAccess\"",[33,3775,3691],{"class":67},[33,3777,3762],{"class":78},[33,3779,594],{"class":67},[33,3781,3782],{"class":39},"\u002F\u002F arr[0] is T | undefined (not just T)\n",[33,3784,3785,3788,3790,3792,3795],{"class":35,"line":179},[33,3786,3787],{"class":78},"    \"noImplicitReturns\"",[33,3789,3691],{"class":67},[33,3791,3762],{"class":78},[33,3793,3794],{"class":67},",    ",[33,3796,3797],{"class":39},"\u002F\u002F error if not all code paths return\n",[33,3799,3800,3803,3805,3807,3809],{"class":35,"line":185},[33,3801,3802],{"class":78},"    \"noFallthroughCasesInSwitch\"",[33,3804,3691],{"class":67},[33,3806,3762],{"class":78},[33,3808,594],{"class":67},[33,3810,3811],{"class":39},"\u002F\u002F error on switch fall-through\n",[33,3813,3814,3817,3819,3821,3823],{"class":35,"line":190},[33,3815,3816],{"class":78},"    \"exactOptionalPropertyTypes\"",[33,3818,3691],{"class":67},[33,3820,3762],{"class":78},[33,3822,594],{"class":67},[33,3824,3825],{"class":39},"\u002F\u002F optional props can't be explicitly undefined\n",[33,3827,3828,3831,3833,3835,3838],{"class":35,"line":196},[33,3829,3830],{"class":78},"    \"esModuleInterop\"",[33,3832,3691],{"class":67},[33,3834,3762],{"class":78},[33,3836,3837],{"class":67},",      ",[33,3839,3840],{"class":39},"\u002F\u002F allow default import from CJS modules\n",[33,3842,3843,3846,3848,3850,3853],{"class":35,"line":227},[33,3844,3845],{"class":78},"    \"skipLibCheck\"",[33,3847,3691],{"class":67},[33,3849,3762],{"class":78},[33,3851,3852],{"class":67},",         ",[33,3854,3855],{"class":39},"\u002F\u002F skip type checking of .d.ts files (faster)\n",[33,3857,3858,3861,3863,3865],{"class":35,"line":254},[33,3859,3860],{"class":78},"    \"forceConsistentCasingInFileNames\"",[33,3862,3691],{"class":67},[33,3864,3762],{"class":78},[33,3866,3867],{"class":67},",\n",[33,3869,3870,3873,3875,3877,3879],{"class":35,"line":259},[33,3871,3872],{"class":78},"    \"resolveJsonModule\"",[33,3874,3691],{"class":67},[33,3876,3762],{"class":78},[33,3878,3794],{"class":67},[33,3880,3881],{"class":39},"\u002F\u002F allow importing .json files\n",[33,3883,3884,3887,3889,3891,3893],{"class":35,"line":286},[33,3885,3886],{"class":78},"    \"isolatedModules\"",[33,3888,3691],{"class":67},[33,3890,3762],{"class":78},[33,3892,3837],{"class":67},[33,3894,3895],{"class":39},"\u002F\u002F each file is compiled independently (Vite requirement)\n",[33,3897,3898,3901,3903,3905,3907],{"class":35,"line":308},[33,3899,3900],{"class":78},"    \"verbatimModuleSyntax\"",[33,3902,3691],{"class":67},[33,3904,3762],{"class":78},[33,3906,594],{"class":67},[33,3908,3909],{"class":39},"\u002F\u002F enforce type-only imports (import type)\n",[33,3911,3912,3915,3917,3920,3922],{"class":35,"line":313},[33,3913,3914],{"class":78},"    \"outDir\"",[33,3916,3691],{"class":67},[33,3918,3919],{"class":152},"\".\u002Fdist\"",[33,3921,3697],{"class":67},[33,3923,3924],{"class":39},"\u002F\u002F output directory\n",[33,3926,3927,3930,3932,3935,3937],{"class":35,"line":337},[33,3928,3929],{"class":78},"    \"rootDir\"",[33,3931,3691],{"class":67},[33,3933,3934],{"class":152},"\".\u002Fsrc\"",[33,3936,3697],{"class":67},[33,3938,3939],{"class":39},"\u002F\u002F source root\n",[33,3941,3942,3945,3947,3950,3952],{"class":35,"line":357},[33,3943,3944],{"class":78},"    \"baseUrl\"",[33,3946,3691],{"class":67},[33,3948,3949],{"class":152},"\".\"",[33,3951,3765],{"class":67},[33,3953,3954],{"class":39},"\u002F\u002F base for path mapping\n",[33,3956,3957,3960,3963,3966,3968,3971,3974],{"class":35,"line":362},[33,3958,3959],{"class":78},"    \"paths\"",[33,3961,3962],{"class":67},": { ",[33,3964,3965],{"class":78},"\"@\u002F*\"",[33,3967,3739],{"class":67},[33,3969,3970],{"class":152},"\".\u002Fsrc\u002F*\"",[33,3972,3973],{"class":67},"] } ",[33,3975,3976],{"class":39},"\u002F\u002F path alias: import from \"@\u002F...\"\n",[33,3978,3979],{"class":35,"line":374},[33,3980,3981],{"class":67},"  },\n",[33,3983,3984,3987,3989,3992],{"class":35,"line":386},[33,3985,3986],{"class":78},"  \"include\"",[33,3988,3739],{"class":67},[33,3990,3991],{"class":152},"\"src\u002F**\u002F*\"",[33,3993,3994],{"class":67},"],\n",[33,3996,3997,4000,4002,4005,4007,4010],{"class":35,"line":685},[33,3998,3999],{"class":78},"  \"exclude\"",[33,4001,3739],{"class":67},[33,4003,4004],{"class":152},"\"node_modules\"",[33,4006,594],{"class":67},[33,4008,4009],{"class":152},"\"dist\"",[33,4011,4012],{"class":67},"]\n",[33,4014,4015],{"class":35,"line":705},[33,4016,438],{"class":67},[15,4018,4020],{"id":4019},"tips-tricks","💡 Tips & Tricks",[20,4022,4023],{"language":22},[24,4024,4026],{"className":26,"code":4025,"language":22,"meta":28,"style":28},"\u002F\u002F ── `as const`: make everything readonly and literal ──\nconst config = { env: \"production\", port: 3000 } as const;\n\u002F\u002F type: { readonly env: \"production\"; readonly port: 3000 } (literal types, not string\u002Fnumber)\n\n\u002F\u002F ── `satisfies`: check a type without widening ──\nconst routes = {\n    home: \"\u002F\",\n    about: \"\u002Fabout\",\n} satisfies Record\u003Cstring, string>;\n\u002F\u002F `satisfies` checks the type but keeps the literal types (home: \"\u002F\", not string)\n\n\u002F\u002F ── `import type`: type-only imports (erased at runtime) ──\nimport type { User } from \".\u002Ftypes.js\";  \u002F\u002F no runtime import (just types)\nimport { getUser } from \".\u002Fapi.js\";       \u002F\u002F runtime import (value)\n\n\u002F\u002F ── `unknown` is safer than `any` (forces narrowing) ──\nfunction process(value: unknown) {\n    \u002F\u002F value.foo();  \u002F\u002F ❌ error — unknown has no properties\n    if (typeof value === \"string\") {\n        value.toUpperCase();  \u002F\u002F ✅ narrowed to string\n    }\n}\n\u002F\u002F `any` disables all checks — `unknown` forces you to narrow before use.\n\n\u002F\u002F ── Exhaustive checking (never type) ──\ntype Status = \"pending\" | \"active\" | \"inactive\";\nfunction handle(status: Status) {\n    switch (status) {\n        case \"pending\": return 1;\n        case \"active\": return 2;\n        case \"inactive\": return 3;\n        default:\n            const _exhaustive: never = status;  \u002F\u002F error if a case is missing\n            throw new Error(`unhandled: ${_exhaustive}`);\n    }\n}\n\u002F\u002F If you add \"archived\" to Status, the default branch fails (status is not never).\n",[30,4027,4028,4033,4064,4069,4073,4078,4089,4099,4109,4129,4134,4138,4143,4163,4181,4185,4190,4206,4214,4230,4241,4245,4249,4254,4258,4263,4287,4303,4311,4326,4340,4355,4363,4383,4405,4409,4413],{"__ignoreMap":28},[33,4029,4030],{"class":35,"line":36},[33,4031,4032],{"class":39},"\u002F\u002F ── `as const`: make everything readonly and literal ──\n",[33,4034,4035,4037,4040,4042,4045,4048,4051,4054,4057,4060,4062],{"class":35,"line":43},[33,4036,130],{"class":59},[33,4038,4039],{"class":78}," config",[33,4041,140],{"class":59},[33,4043,4044],{"class":67}," { env: ",[33,4046,4047],{"class":152},"\"production\"",[33,4049,4050],{"class":67},", port: ",[33,4052,4053],{"class":78},"3000",[33,4055,4056],{"class":67}," } ",[33,4058,4059],{"class":59},"as",[33,4061,3558],{"class":59},[33,4063,354],{"class":67},[33,4065,4066],{"class":35,"line":49},[33,4067,4068],{"class":39},"\u002F\u002F type: { readonly env: \"production\"; readonly port: 3000 } (literal types, not string\u002Fnumber)\n",[33,4070,4071],{"class":35,"line":56},[33,4072,53],{"emptyLinePlaceholder":52},[33,4074,4075],{"class":35,"line":96},[33,4076,4077],{"class":39},"\u002F\u002F ── `satisfies`: check a type without widening ──\n",[33,4079,4080,4082,4085,4087],{"class":35,"line":122},[33,4081,130],{"class":59},[33,4083,4084],{"class":78}," routes",[33,4086,140],{"class":59},[33,4088,419],{"class":67},[33,4090,4091,4094,4097],{"class":35,"line":127},[33,4092,4093],{"class":67},"    home: ",[33,4095,4096],{"class":152},"\"\u002F\"",[33,4098,3867],{"class":67},[33,4100,4101,4104,4107],{"class":35,"line":159},[33,4102,4103],{"class":67},"    about: ",[33,4105,4106],{"class":152},"\"\u002Fabout\"",[33,4108,3867],{"class":67},[33,4110,4111,4114,4117,4119,4121,4123,4125,4127],{"class":35,"line":179},[33,4112,4113],{"class":67},"} ",[33,4115,4116],{"class":59},"satisfies",[33,4118,2613],{"class":63},[33,4120,514],{"class":67},[33,4122,591],{"class":78},[33,4124,594],{"class":67},[33,4126,591],{"class":78},[33,4128,2465],{"class":67},[33,4130,4131],{"class":35,"line":185},[33,4132,4133],{"class":39},"\u002F\u002F `satisfies` checks the type but keeps the literal types (home: \"\u002F\", not string)\n",[33,4135,4136],{"class":35,"line":190},[33,4137,53],{"emptyLinePlaceholder":52},[33,4139,4140],{"class":35,"line":196},[33,4141,4142],{"class":39},"\u002F\u002F ── `import type`: type-only imports (erased at runtime) ──\n",[33,4144,4145,4148,4150,4153,4155,4158,4160],{"class":35,"line":227},[33,4146,4147],{"class":59},"import",[33,4149,3574],{"class":59},[33,4151,4152],{"class":67}," { User } ",[33,4154,1451],{"class":59},[33,4156,4157],{"class":152}," \".\u002Ftypes.js\"",[33,4159,331],{"class":67},[33,4161,4162],{"class":39},"\u002F\u002F no runtime import (just types)\n",[33,4164,4165,4167,4170,4172,4175,4178],{"class":35,"line":254},[33,4166,4147],{"class":59},[33,4168,4169],{"class":67}," { getUser } ",[33,4171,1451],{"class":59},[33,4173,4174],{"class":152}," \".\u002Fapi.js\"",[33,4176,4177],{"class":67},";       ",[33,4179,4180],{"class":39},"\u002F\u002F runtime import (value)\n",[33,4182,4183],{"class":35,"line":259},[33,4184,53],{"emptyLinePlaceholder":52},[33,4186,4187],{"class":35,"line":286},[33,4188,4189],{"class":39},"\u002F\u002F ── `unknown` is safer than `any` (forces narrowing) ──\n",[33,4191,4192,4194,4196,4198,4200,4202,4204],{"class":35,"line":308},[33,4193,262],{"class":59},[33,4195,2838],{"class":63},[33,4197,268],{"class":67},[33,4199,529],{"class":71},[33,4201,75],{"class":59},[33,4203,3152],{"class":78},[33,4205,2853],{"class":67},[33,4207,4208,4211],{"class":35,"line":313},[33,4209,4210],{"class":39},"    \u002F\u002F value.foo();",[33,4212,4213],{"class":39},"  \u002F\u002F ❌ error — unknown has no properties\n",[33,4215,4216,4218,4220,4222,4224,4226,4228],{"class":35,"line":337},[33,4217,2858],{"class":59},[33,4219,526],{"class":67},[33,4221,2863],{"class":59},[33,4223,2866],{"class":67},[33,4225,2869],{"class":59},[33,4227,2872],{"class":152},[33,4229,2853],{"class":67},[33,4231,4232,4234,4236,4238],{"class":35,"line":357},[33,4233,2879],{"class":67},[33,4235,2882],{"class":63},[33,4237,2885],{"class":67},[33,4239,4240],{"class":39},"\u002F\u002F ✅ narrowed to string\n",[33,4242,4243],{"class":35,"line":362},[33,4244,2919],{"class":67},[33,4246,4247],{"class":35,"line":374},[33,4248,438],{"class":67},[33,4250,4251],{"class":35,"line":386},[33,4252,4253],{"class":39},"\u002F\u002F `any` disables all checks — `unknown` forces you to narrow before use.\n",[33,4255,4256],{"class":35,"line":685},[33,4257,53],{"emptyLinePlaceholder":52},[33,4259,4260],{"class":35,"line":705},[33,4261,4262],{"class":39},"\u002F\u002F ── Exhaustive checking (never type) ──\n",[33,4264,4265,4267,4270,4272,4275,4277,4280,4282,4285],{"class":35,"line":735},[33,4266,199],{"class":59},[33,4268,4269],{"class":63}," Status",[33,4271,140],{"class":59},[33,4273,4274],{"class":152}," \"pending\"",[33,4276,496],{"class":59},[33,4278,4279],{"class":152}," \"active\"",[33,4281,496],{"class":59},[33,4283,4284],{"class":152}," \"inactive\"",[33,4286,354],{"class":67},[33,4288,4289,4291,4293,4295,4297,4299,4301],{"class":35,"line":740},[33,4290,262],{"class":59},[33,4292,3320],{"class":63},[33,4294,268],{"class":67},[33,4296,3266],{"class":71},[33,4298,75],{"class":59},[33,4300,4269],{"class":63},[33,4302,2853],{"class":67},[33,4304,4305,4308],{"class":35,"line":746},[33,4306,4307],{"class":59},"    switch",[33,4309,4310],{"class":67}," (status) {\n",[33,4312,4313,4316,4318,4320,4322,4324],{"class":35,"line":774},[33,4314,4315],{"class":59},"        case",[33,4317,4274],{"class":152},[33,4319,3691],{"class":67},[33,4321,1278],{"class":59},[33,4323,323],{"class":78},[33,4325,354],{"class":67},[33,4327,4328,4330,4332,4334,4336,4338],{"class":35,"line":800},[33,4329,4315],{"class":59},[33,4331,4279],{"class":152},[33,4333,3691],{"class":67},[33,4335,1278],{"class":59},[33,4337,347],{"class":78},[33,4339,354],{"class":67},[33,4341,4342,4344,4346,4348,4350,4353],{"class":35,"line":806},[33,4343,4315],{"class":59},[33,4345,4284],{"class":152},[33,4347,3691],{"class":67},[33,4349,1278],{"class":59},[33,4351,4352],{"class":78}," 3",[33,4354,354],{"class":67},[33,4356,4357,4360],{"class":35,"line":1334},[33,4358,4359],{"class":59},"        default",[33,4361,4362],{"class":67},":\n",[33,4364,4365,4368,4371,4373,4375,4377,4380],{"class":35,"line":1356},[33,4366,4367],{"class":59},"            const",[33,4369,4370],{"class":78}," _exhaustive",[33,4372,75],{"class":59},[33,4374,1661],{"class":78},[33,4376,140],{"class":59},[33,4378,4379],{"class":67}," status;  ",[33,4381,4382],{"class":39},"\u002F\u002F error if a case is missing\n",[33,4384,4385,4388,4390,4392,4394,4397,4400,4402],{"class":35,"line":1374},[33,4386,4387],{"class":59},"            throw",[33,4389,1344],{"class":59},[33,4391,2949],{"class":63},[33,4393,268],{"class":67},[33,4395,4396],{"class":152},"`unhandled: ${",[33,4398,4399],{"class":67},"_exhaustive",[33,4401,2420],{"class":152},[33,4403,4404],{"class":67},");\n",[33,4406,4407],{"class":35,"line":1391},[33,4408,2919],{"class":67},[33,4410,4411],{"class":35,"line":1396},[33,4412,438],{"class":67},[33,4414,4415],{"class":35,"line":1402},[33,4416,4417],{"class":39},"\u002F\u002F If you add \"archived\" to Status, the default branch fails (status is not never).\n",[15,4419,4421],{"id":4420},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[20,4423,4424],{"language":22},[24,4425,4427],{"className":26,"code":4426,"language":22,"meta":28,"style":28},"\u002F\u002F ── TypeScript types are erased at runtime (no runtime type checking) ──\nfunction isUser(value: any): value is User {\n    return typeof value?.id === \"number\" && typeof value?.name === \"string\";\n    \u002F\u002F Can't use `value instanceof User` (interface has no runtime presence).\n    \u002F\u002F Must manually check properties (structural validation).\n}\n\n\u002F\u002F ── `any` disables type checking (escape hatch — avoid) ──\n\u002F\u002F Use `unknown` instead (forces narrowing before use).\n\n\u002F\u002F ── `null` and `undefined` are different types ──\n\u002F\u002F strict: true enables strictNullChecks — null and undefined are not assignable to other types.\n\u002F\u002F string | undefined ≠ string | null ≠ string | null | undefined\n\n\u002F\u002F ── Excess property checking only applies to object literals ──\ninterface User { id: number; name: string; }\nconst user: User = { id: 1, name: \"Alice\", extra: \"x\" };  \u002F\u002F ❌ excess property\nconst obj = { id: 1, name: \"Alice\", extra: \"x\" };\nconst user2: User = obj;  \u002F\u002F ✅ no excess check (obj is not a literal — structural match)\n\n\u002F\u002F ── Type assertions don't change runtime behavior ──\nconst value: any = \"hello\";\nconst num: number = value as number;  \u002F\u002F compiles, but runtime: num is still \"hello\" (string)\n\u002F\u002F `as` only affects the compiler — no runtime conversion. Use Number(value) for conversion.\n\n\u002F\u002F ── `interface` merging can cause surprises ──\n\u002F\u002F If you declare the same interface twice, they merge (additive).\n\u002F\u002F This can accidentally augment global types (like Window) — be careful.\n",[30,4428,4429,4434,4461,4489,4494,4499,4503,4507,4512,4517,4521,4526,4531,4536,4540,4545,4569,4599,4622,4641,4645,4650,4667,4690,4695,4699,4704,4709],{"__ignoreMap":28},[33,4430,4431],{"class":35,"line":36},[33,4432,4433],{"class":39},"\u002F\u002F ── TypeScript types are erased at runtime (no runtime type checking) ──\n",[33,4435,4436,4438,4441,4443,4445,4447,4449,4451,4453,4455,4457,4459],{"class":35,"line":43},[33,4437,262],{"class":59},[33,4439,4440],{"class":63}," isUser",[33,4442,268],{"class":67},[33,4444,529],{"class":71},[33,4446,75],{"class":59},[33,4448,1641],{"class":78},[33,4450,848],{"class":67},[33,4452,75],{"class":59},[33,4454,3159],{"class":71},[33,4456,3162],{"class":59},[33,4458,64],{"class":63},[33,4460,419],{"class":67},[33,4462,4463,4465,4467,4470,4472,4475,4478,4480,4483,4485,4487],{"class":35,"line":49},[33,4464,862],{"class":59},[33,4466,3176],{"class":59},[33,4468,4469],{"class":67}," value?.id ",[33,4471,2869],{"class":59},[33,4473,4474],{"class":152}," \"number\"",[33,4476,4477],{"class":59}," &&",[33,4479,3176],{"class":59},[33,4481,4482],{"class":67}," value?.name ",[33,4484,2869],{"class":59},[33,4486,2872],{"class":152},[33,4488,354],{"class":67},[33,4490,4491],{"class":35,"line":56},[33,4492,4493],{"class":39},"    \u002F\u002F Can't use `value instanceof User` (interface has no runtime presence).\n",[33,4495,4496],{"class":35,"line":96},[33,4497,4498],{"class":39},"    \u002F\u002F Must manually check properties (structural validation).\n",[33,4500,4501],{"class":35,"line":122},[33,4502,438],{"class":67},[33,4504,4505],{"class":35,"line":127},[33,4506,53],{"emptyLinePlaceholder":52},[33,4508,4509],{"class":35,"line":159},[33,4510,4511],{"class":39},"\u002F\u002F ── `any` disables type checking (escape hatch — avoid) ──\n",[33,4513,4514],{"class":35,"line":179},[33,4515,4516],{"class":39},"\u002F\u002F Use `unknown` instead (forces narrowing before use).\n",[33,4518,4519],{"class":35,"line":185},[33,4520,53],{"emptyLinePlaceholder":52},[33,4522,4523],{"class":35,"line":190},[33,4524,4525],{"class":39},"\u002F\u002F ── `null` and `undefined` are different types ──\n",[33,4527,4528],{"class":35,"line":196},[33,4529,4530],{"class":39},"\u002F\u002F strict: true enables strictNullChecks — null and undefined are not assignable to other types.\n",[33,4532,4533],{"class":35,"line":227},[33,4534,4535],{"class":39},"\u002F\u002F string | undefined ≠ string | null ≠ string | null | undefined\n",[33,4537,4538],{"class":35,"line":254},[33,4539,53],{"emptyLinePlaceholder":52},[33,4541,4542],{"class":35,"line":259},[33,4543,4544],{"class":39},"\u002F\u002F ── Excess property checking only applies to object literals ──\n",[33,4546,4547,4549,4551,4553,4555,4557,4559,4561,4563,4565,4567],{"class":35,"line":286},[33,4548,60],{"class":59},[33,4550,64],{"class":63},[33,4552,68],{"class":67},[33,4554,72],{"class":71},[33,4556,75],{"class":59},[33,4558,79],{"class":78},[33,4560,82],{"class":67},[33,4562,85],{"class":71},[33,4564,75],{"class":59},[33,4566,90],{"class":78},[33,4568,93],{"class":67},[33,4570,4571,4573,4575,4577,4579,4581,4583,4585,4587,4589,4592,4594,4596],{"class":35,"line":308},[33,4572,130],{"class":59},[33,4574,133],{"class":78},[33,4576,75],{"class":59},[33,4578,64],{"class":63},[33,4580,140],{"class":59},[33,4582,143],{"class":67},[33,4584,146],{"class":78},[33,4586,149],{"class":67},[33,4588,153],{"class":152},[33,4590,4591],{"class":67},", extra: ",[33,4593,1479],{"class":152},[33,4595,729],{"class":67},[33,4597,4598],{"class":39},"\u002F\u002F ❌ excess property\n",[33,4600,4601,4603,4606,4608,4610,4612,4614,4616,4618,4620],{"class":35,"line":313},[33,4602,130],{"class":59},[33,4604,4605],{"class":78}," obj",[33,4607,140],{"class":59},[33,4609,143],{"class":67},[33,4611,146],{"class":78},[33,4613,149],{"class":67},[33,4615,153],{"class":152},[33,4617,4591],{"class":67},[33,4619,1479],{"class":152},[33,4621,156],{"class":67},[33,4623,4624,4626,4629,4631,4633,4635,4638],{"class":35,"line":337},[33,4625,130],{"class":59},[33,4627,4628],{"class":78}," user2",[33,4630,75],{"class":59},[33,4632,64],{"class":63},[33,4634,140],{"class":59},[33,4636,4637],{"class":67}," obj;  ",[33,4639,4640],{"class":39},"\u002F\u002F ✅ no excess check (obj is not a literal — structural match)\n",[33,4642,4643],{"class":35,"line":357},[33,4644,53],{"emptyLinePlaceholder":52},[33,4646,4647],{"class":35,"line":362},[33,4648,4649],{"class":39},"\u002F\u002F ── Type assertions don't change runtime behavior ──\n",[33,4651,4652,4654,4656,4658,4660,4662,4665],{"class":35,"line":374},[33,4653,130],{"class":59},[33,4655,3159],{"class":78},[33,4657,75],{"class":59},[33,4659,1641],{"class":78},[33,4661,140],{"class":59},[33,4663,4664],{"class":152}," \"hello\"",[33,4666,354],{"class":67},[33,4668,4669,4671,4673,4675,4677,4679,4681,4683,4685,4687],{"class":35,"line":386},[33,4670,130],{"class":59},[33,4672,898],{"class":78},[33,4674,75],{"class":59},[33,4676,79],{"class":78},[33,4678,140],{"class":59},[33,4680,2866],{"class":67},[33,4682,4059],{"class":59},[33,4684,79],{"class":78},[33,4686,331],{"class":67},[33,4688,4689],{"class":39},"\u002F\u002F compiles, but runtime: num is still \"hello\" (string)\n",[33,4691,4692],{"class":35,"line":685},[33,4693,4694],{"class":39},"\u002F\u002F `as` only affects the compiler — no runtime conversion. Use Number(value) for conversion.\n",[33,4696,4697],{"class":35,"line":705},[33,4698,53],{"emptyLinePlaceholder":52},[33,4700,4701],{"class":35,"line":735},[33,4702,4703],{"class":39},"\u002F\u002F ── `interface` merging can cause surprises ──\n",[33,4705,4706],{"class":35,"line":740},[33,4707,4708],{"class":39},"\u002F\u002F If you declare the same interface twice, they merge (additive).\n",[33,4710,4711],{"class":35,"line":746},[33,4712,4713],{"class":39},"\u002F\u002F This can accidentally augment global types (like Window) — be careful.\n",[15,4715,4717],{"id":4716},"quick-quiz","🧠 Quick Quiz",[4719,4720,4721],"p",{},"Why does this fail, and how do you fix it?",[20,4723,4724],{"language":22},[24,4725,4727],{"className":26,"code":4726,"language":22,"meta":28,"style":28},"type EventName\u003CT> = T extends `on${infer E}` ? E : never;\ntype Handler\u003CT> = (event: T) => void;\n\nfunction on\u003CT extends string>(event: T, handler: Handler\u003CEventName\u003CT>>): void {\n    \u002F\u002F ...\n}\n\non(\"onClick\", (event) => { \u002F* what is the type of `event`? *\u002F });\n",[30,4728,4729,4767,4798,4802,4852,4857,4861,4865],{"__ignoreMap":28},[33,4730,4731,4733,4736,4738,4740,4742,4744,4746,4748,4751,4753,4755,4757,4759,4761,4763,4765],{"class":35,"line":36},[33,4732,199],{"class":59},[33,4734,4735],{"class":63}," EventName",[33,4737,514],{"class":67},[33,4739,517],{"class":63},[33,4741,520],{"class":67},[33,4743,523],{"class":59},[33,4745,534],{"class":63},[33,4747,658],{"class":59},[33,4749,4750],{"class":152}," `on${",[33,4752,1760],{"class":59},[33,4754,1858],{"class":63},[33,4756,2420],{"class":152},[33,4758,1548],{"class":59},[33,4760,1858],{"class":63},[33,4762,1554],{"class":59},[33,4764,1661],{"class":78},[33,4766,354],{"class":67},[33,4768,4769,4771,4774,4776,4778,4780,4782,4784,4786,4788,4790,4792,4794,4796],{"class":35,"line":43},[33,4770,199],{"class":59},[33,4772,4773],{"class":63}," Handler",[33,4775,514],{"class":67},[33,4777,517],{"class":63},[33,4779,520],{"class":67},[33,4781,523],{"class":59},[33,4783,526],{"class":67},[33,4785,3468],{"class":71},[33,4787,75],{"class":59},[33,4789,534],{"class":63},[33,4791,537],{"class":67},[33,4793,540],{"class":59},[33,4795,543],{"class":78},[33,4797,354],{"class":67},[33,4799,4800],{"class":35,"line":49},[33,4801,53],{"emptyLinePlaceholder":52},[33,4803,4804,4806,4809,4811,4813,4815,4817,4819,4821,4823,4825,4827,4830,4832,4834,4836,4839,4841,4843,4846,4848,4850],{"class":35,"line":56},[33,4805,262],{"class":59},[33,4807,4808],{"class":63}," on",[33,4810,514],{"class":67},[33,4812,517],{"class":63},[33,4814,658],{"class":59},[33,4816,90],{"class":78},[33,4818,839],{"class":67},[33,4820,3468],{"class":71},[33,4822,75],{"class":59},[33,4824,534],{"class":63},[33,4826,594],{"class":67},[33,4828,4829],{"class":71},"handler",[33,4831,75],{"class":59},[33,4833,4773],{"class":63},[33,4835,514],{"class":67},[33,4837,4838],{"class":63},"EventName",[33,4840,514],{"class":67},[33,4842,517],{"class":63},[33,4844,4845],{"class":67},">>)",[33,4847,75],{"class":59},[33,4849,543],{"class":78},[33,4851,419],{"class":67},[33,4853,4854],{"class":35,"line":96},[33,4855,4856],{"class":39},"    \u002F\u002F ...\n",[33,4858,4859],{"class":35,"line":122},[33,4860,438],{"class":67},[33,4862,4863],{"class":35,"line":127},[33,4864,53],{"emptyLinePlaceholder":52},[33,4866,4867,4870,4872,4875,4878,4880,4882,4884,4886,4889],{"class":35,"line":159},[33,4868,4869],{"class":63},"on",[33,4871,268],{"class":67},[33,4873,4874],{"class":152},"\"onClick\"",[33,4876,4877],{"class":67},", (",[33,4879,3468],{"class":71},[33,4881,537],{"class":67},[33,4883,540],{"class":59},[33,4885,68],{"class":67},[33,4887,4888],{"class":39},"\u002F* what is the type of `event`? *\u002F",[33,4890,4891],{"class":67}," });\n",[4893,4894,4895,4899,4912,4915,4972,4978,4985,5151],"details",{},[4896,4897,4898],"summary",{},"Answer",[4719,4900,4901,4902,4904,4905,4908,4909,4911],{},"The type of ",[30,4903,3468],{}," is ",[30,4906,4907],{},"\"Click\""," — the literal string ",[30,4910,4907],{},", not a generic event object.",[4719,4913,4914],{},"Here's why:",[4916,4917,4918,4931,4941,4959],"ol",{},[4919,4920,4921,4923,4924,4926,4927,4930],"li",{},[30,4922,517],{}," is inferred as ",[30,4925,4874],{}," (the literal string, because ",[30,4928,4929],{},"T extends string"," and the argument is a string literal).",[4919,4932,4933,4936,4937,4940],{},[30,4934,4935],{},"EventName\u003C\"onClick\">"," evaluates: ",[30,4938,4939],{},"\"onClick\" extends \\","on${infer E}` ? E : never`.",[4919,4942,4943,4944,4947,4948,4874,4951,4954,4955,4958],{},"The template literal pattern ",[30,4945,4946],{},"\\","on${infer E}`",[30,4949,4950],{},"matches",[30,4952,4953],{},", so ","E",[30,4956,4957],{},"is inferred as","\"Click\"`.",[4919,4960,4961,4964,4965,4964,4968,4971],{},[30,4962,4963],{},"Handler\u003CEventName\u003C\"onClick\">>"," = ",[30,4966,4967],{},"Handler\u003C\"Click\">",[30,4969,4970],{},"(event: \"Click\") => void",".",[4719,4973,4974,4975,4977],{},"So the handler receives the literal string ",[30,4976,4907],{}," — probably not what you want.",[4719,4979,4980,4984],{},[4981,4982,4983],"strong",{},"Fix",": If you want the handler to receive an actual event object (not a string), define a proper event type:",[24,4986,4988],{"className":26,"code":4987,"language":22,"meta":28,"style":28},"interface ClickEvent { target: HTMLElement; type: \"click\"; }\ntype EventMap = { onClick: ClickEvent; onHover: { type: \"hover\" } };\n\nfunction on\u003CK extends keyof EventMap>(event: K, handler: (e: EventMap[K]) => void): void {\n    \u002F\u002F ...\n}\n\non(\"onClick\", (event) => { event.target; });  \u002F\u002F event: ClickEvent (properly typed)\n",[30,4989,4990,5018,5055,5059,5117,5121,5125,5129],{"__ignoreMap":28},[33,4991,4992,4994,4997,4999,5002,5004,5007,5009,5011,5013,5016],{"class":35,"line":36},[33,4993,60],{"class":59},[33,4995,4996],{"class":63}," ClickEvent",[33,4998,68],{"class":67},[33,5000,5001],{"class":71},"target",[33,5003,75],{"class":59},[33,5005,5006],{"class":63}," HTMLElement",[33,5008,82],{"class":67},[33,5010,199],{"class":71},[33,5012,75],{"class":59},[33,5014,5015],{"class":152}," \"click\"",[33,5017,93],{"class":67},[33,5019,5020,5022,5025,5027,5029,5032,5034,5036,5038,5041,5043,5045,5047,5049,5052],{"class":35,"line":43},[33,5021,199],{"class":59},[33,5023,5024],{"class":63}," EventMap",[33,5026,140],{"class":59},[33,5028,68],{"class":67},[33,5030,5031],{"class":71},"onClick",[33,5033,75],{"class":59},[33,5035,4996],{"class":63},[33,5037,82],{"class":67},[33,5039,5040],{"class":71},"onHover",[33,5042,75],{"class":59},[33,5044,68],{"class":67},[33,5046,199],{"class":71},[33,5048,75],{"class":59},[33,5050,5051],{"class":152}," \"hover\"",[33,5053,5054],{"class":67}," } };\n",[33,5056,5057],{"class":35,"line":49},[33,5058,53],{"emptyLinePlaceholder":52},[33,5060,5061,5063,5065,5067,5069,5071,5073,5075,5077,5079,5081,5083,5085,5087,5089,5091,5094,5096,5098,5100,5102,5105,5107,5109,5111,5113,5115],{"class":35,"line":56},[33,5062,262],{"class":59},[33,5064,4808],{"class":63},[33,5066,514],{"class":67},[33,5068,1058],{"class":63},[33,5070,658],{"class":59},[33,5072,1063],{"class":59},[33,5074,5024],{"class":63},[33,5076,839],{"class":67},[33,5078,3468],{"class":71},[33,5080,75],{"class":59},[33,5082,1084],{"class":63},[33,5084,594],{"class":67},[33,5086,4829],{"class":63},[33,5088,75],{"class":59},[33,5090,526],{"class":67},[33,5092,5093],{"class":71},"e",[33,5095,75],{"class":59},[33,5097,5024],{"class":63},[33,5099,1093],{"class":67},[33,5101,1058],{"class":63},[33,5103,5104],{"class":67},"]) ",[33,5106,540],{"class":59},[33,5108,543],{"class":78},[33,5110,848],{"class":67},[33,5112,75],{"class":59},[33,5114,543],{"class":78},[33,5116,419],{"class":67},[33,5118,5119],{"class":35,"line":96},[33,5120,4856],{"class":39},[33,5122,5123],{"class":35,"line":122},[33,5124,438],{"class":67},[33,5126,5127],{"class":35,"line":127},[33,5128,53],{"emptyLinePlaceholder":52},[33,5130,5131,5133,5135,5137,5139,5141,5143,5145,5148],{"class":35,"line":159},[33,5132,4869],{"class":63},[33,5134,268],{"class":67},[33,5136,4874],{"class":152},[33,5138,4877],{"class":67},[33,5140,3468],{"class":71},[33,5142,537],{"class":67},[33,5144,540],{"class":59},[33,5146,5147],{"class":67}," { event.target; });  ",[33,5149,5150],{"class":39},"\u002F\u002F event: ClickEvent (properly typed)\n",[4719,5152,5153,5156,5157,5159,5160,5163],{},[4981,5154,5155],{},"The lesson",": template literal types and ",[30,5158,1760],{}," extract string fragments at the type level — they produce string literal types, not runtime values. If you need proper event types, use a mapped type (",[30,5161,5162],{},"EventMap",") that maps event names to their payload types.",[5165,5166,5167],"style",{},"html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}",{"title":28,"searchDepth":43,"depth":43,"links":5169},[5170,5171,5173,5174,5175,5176,5177,5179,5181,5182,5183],{"id":17,"depth":43,"text":18},{"id":392,"depth":43,"text":5172},"type vs interface",{"id":812,"depth":43,"text":813},{"id":1511,"depth":43,"text":1512},{"id":2088,"depth":43,"text":2089},{"id":2818,"depth":43,"text":2819},{"id":3385,"depth":43,"text":5178},"Declaration Files (.d.ts)",{"id":3657,"depth":43,"text":5180},"tsconfig.json Configuration",{"id":4019,"depth":43,"text":4020},{"id":4420,"depth":43,"text":4421},{"id":4716,"depth":43,"text":4717},"Deep-dive into TypeScript: structural typing vs nominal, type vs interface, generics with constraints, conditional types and inference, mapped types, utility types, and declaration files. Code-first reference for senior engineers.","md",{},"\u002Fjs\u002F28-typescript-essentials",{"title":5,"description":5184},"js\u002F28-typescript-essentials","SyfzxtzDRTpZd9zVSqiFR-zwItkueBwSx3EFXbKfNis",1789924649572]