[{"data":1,"prerenderedAt":398},["ShallowReactive",2],{"content:\u002F2023\u002Ftypescript\u002Fts-14":3,"surround:\u002F2023\u002Ftypescript\u002Fts-14":387},{"id":4,"title":5,"body":6,"categories":364,"date":367,"description":29,"draft":368,"extension":369,"image":370,"meta":371,"navigation":373,"path":374,"permalink":370,"published":370,"readingTime":375,"recommend":370,"references":370,"seo":380,"sitemap":381,"stem":382,"tags":383,"type":385,"updated":370,"__hash__":386},"content\u002Fposts\u002F2023\u002Ftypescript\u002Fts-14.md","浅尝类型体操",{"type":7,"value":8,"toc":337},"minimark",[9,13,18,22,33,37,43,46,52,55,62,65,71,85,88,102,105,111,118,122,128,168,171,177,180,184,190,194,200,204,210,213,219,223,229,232,236,242,249,255,261,265,271,275,281,285,288,291,294,305,311,315,321,324,328,334],[10,11,12],"h2",{"id":12},"基本原理",[14,15,17],"h3",{"id":16},"ifa-b","if(A \u003C= B)",[19,20,21],"p",{},"if(A \u003C= B) true else false",[23,24,30],"pre",{"className":25,"code":27,"language":28,"meta":29},[26],"language-ts","type A = 1;\ntype B = 1 | 2;\ntype Result = A extends B ? true : false; \u002F\u002F true\n","ts","",[31,32,27],"code",{"__ignoreMap":29},[14,34,36],{"id":35},"ifa-b-and-c-d","if(A \u003C= B) and (C \u003C= D)",[23,38,41],{"className":39,"code":40,"language":28,"meta":29},[26],"type A = 1;\ntype B = 1 | 2;\ntype C = 3;\ntype D = 3 | 4;\ntype Result = A extends B\n  ? C extends D\n    ? 'true, true'\n    : 'true, false'\n  : C extends D\n  ? 'false, true'\n  : 'false, false'; \u002F\u002F \"true, true\"\n",[31,42,40],{"__ignoreMap":29},[14,44,45],{"id":45},"空元组",[23,47,50],{"className":48,"code":49,"language":28,"meta":29},[26],"type A = [];\ntype IsEmptyArray\u003CArr extends unknown[]> = Arr['length'] extends 0\n  ? true\n  : false;\ntype Result = IsEmptyArray\u003CA>; \u002F\u002F true\n",[31,51,49],{"__ignoreMap":29},[19,53,54],{},"元组与数组的区别是：数组长度没有限制，而元组长度有限制；",[19,56,57,58],{},"可以理解为：元组就是",[59,60,61],"strong",{},"长度固定的数组",[14,63,64],{"id":64},"非空元组",[23,66,69],{"className":67,"code":68,"language":28,"meta":29},[26],"type A = [1];\ntype NotEmpty\u003CArr extends unknown[]> = Arr extends [...infer X, infer Last]\n  ? true\n  : false;\ntype Result = NotEmpty\u003CA>; \u002F\u002F true\n",[31,70,68],{"__ignoreMap":29},[19,72,73,76,77,80,81,84],{},[31,74,75],{"code":75},"[...infer X, infer Last]"," 表示至少存在一个元素的数组，那么 ",[31,78,79],{"code":79},"Arr extends [...infer X, infer Last]"," 表示的意思是：",[31,82,83],{"code":83},"Arr"," 是否属于（包含于）一个非空数组",[19,86,87],{},"判断是否为非空元组的两种方法：",[89,90,91,97],"ol",{},[92,93,94],"li",{},[31,95,96],{"code":96},"array['length'] !== 0",[92,98,99],{},[31,100,101],{"code":101},"array extends [...infer X, infer Rest] === true ",[14,103,104],{"id":104},"递归",[23,106,109],{"className":107,"code":108,"language":28,"meta":29},[26],"type A = ['Ich', '☆', 'liebe', '☆', 'dich'];\ntype Reverse\u003CArr extends unknown[]> = Arr extends [...infer Rest, infer Last]\n  ? [Last, ...Reverse\u003CRest>]\n  : Arr;\ntype Result = Reverse\u003CA>; \u002F\u002F [\"dich\", \"☆\", \"liebe\", \"☆\", \"Ich\"]\n",[31,110,108],{"__ignoreMap":29},[112,113,115],"alert",{"type":114},"warning",[19,116,117],{},"注意：递归是有层数限制的",[14,119,121],{"id":120},"模式匹配-infer-引用","模式匹配 + infer 引用",[23,123,126],{"className":124,"code":125,"language":28,"meta":29},[26],"type Tuple = ['Ich', '☆', 'liebe', '☆', 'dich'];\ntype Result1 = Tuple extends [infer First, ...infer Rest] ? First : never; \u002F\u002F \"Ich\"\ntype Result2 = Tuple extends [infer First, ...infer Rest] ? Rest : never; \u002F\u002F [\"☆\", \"liebe\", \"☆\", \"dich\"]\n",[31,127,125],{"__ignoreMap":29},[129,130,131,145,151],"ul",{},[92,132,133,136,137,140,141,144],{},[31,134,135],{"code":135},"inter"," 出现在",[59,138,139],{},"条件类型","中，通常与 ",[31,142,143],{"code":143},"extends"," 关键字一起使用",[92,146,147,150],{},[31,148,149],{"code":149},"infer"," 显示地声明了一个新的泛型变量，用于表示待推断的类型",[92,152,153,154,156,157,159,160,163,164,167],{},"当一个类型无法通过简单的方式访问到时, 我们可以使用 ",[31,155,149],{"code":149}," 关键字来实现对其的快速访问；换言之，使用 ",[31,158,149],{"code":149}," 往往是因为后面需要用到对应的变量，比如上述的 ",[31,161,162],{"code":162},"First"," 和 ",[31,165,166],{"code":166},"Rest","，表示做一个引用（个人理解）",[19,169,170],{},"不写引用，直接写类型也是可以的",[23,172,175],{"className":173,"code":174,"language":28,"meta":29},[26],"type Tuple = ['Ich', '☆', 'liebe', '☆', 'dich'];\ntype Result1 = Tuple extends [infer First, ...string[]] ? First : never; \u002F\u002F \"Ich\"\ntype Result2 = Tuple extends ['Ich', ...infer Rest] ? Rest : never; \u002F\u002F [\"☆\", \"liebe\", \"☆\", \"dich\"]\n",[31,176,174],{"__ignoreMap":29},[10,178,179],{"id":179},"元组体操",[14,181,183],{"id":182},"_1-1-2","[1] => [1, 2]",[23,185,188],{"className":186,"code":187,"language":28,"meta":29},[26],"type A = [1];\ntype B = [...A, 2]; \u002F\u002F [1, 2]\n",[31,189,187],{"__ignoreMap":29},[14,191,193],{"id":192},"_1-2-3-4-1-2-3-4","[1, 2] [3, 4] => [1, 2, 3, 4]",[23,195,198],{"className":196,"code":197,"language":28,"meta":29},[26],"type B = [1, 2];\ntype C = [3, 4];\ntype D = [...B, ...C]; \u002F\u002F [1, 2, 3, 4]\n",[31,199,197],{"__ignoreMap":29},[14,201,203],{"id":202},"_1-2-3-4-4","[1, 2, 3, 4] => 4",[23,205,208],{"className":206,"code":207,"language":28,"meta":29},[26],"type D = [1, 2, 3, 4];\n\u002F\u002F 注意 1,2,3,4 都是类型，不是值\ntype Last\u003CT> = T extends [...items: unknown[], last: infer X] ? X : never;\ntype E = Last\u003CD>;\n\u002F\u002F   ^--- E = 4 注意这里的 4 是类型，不是值\n",[31,209,207],{"__ignoreMap":29},[19,211,212],{},"这里顺便提一下错误的写法",[23,214,217],{"className":215,"code":216,"language":28,"meta":29},[26],"type D = [1, 2, 3, 4];\n\u002F\u002F 注意 1,2,3,4 都是类型，不是值\ntype Last\u003CT extends unknown[]> = T[T[\"length\"] - 1]\n\u002F\u002F TS 并没有提供 - 1 操作\ntype E = Last\u003CD>\n",[31,218,216],{"__ignoreMap":29},[14,220,222],{"id":221},"_1-2-3-4-1-2-3","[1, 2, 3, 4] => [1, 2, 3]",[23,224,227],{"className":225,"code":226,"language":28,"meta":29},[26],"type D = [1, 2, 3, 4];\n\u002F\u002F 注意 1,2,3,4 都是类型，不是值\ntype NoLast\u003CT> = T extends [...infer X, unknown] ? X : never;\ntype E = NoLast\u003CD>;\n\u002F\u002F   ^--- E = [1,2,3] 注意是类型，不是值\n",[31,228,226],{"__ignoreMap":29},[10,230,231],{"id":231},"字符串体操",[14,233,235],{"id":234},"a-a","'a' => 'A'",[23,237,240],{"className":238,"code":239,"language":28,"meta":29},[26],"type A = 'vivy';\ntype B = Capitalize\u003CA>;\n\u002F\u002F   ^-- type B = \"Vivy\"\ntype C = 'Ich' | '☆' | 'liebe' | '☆' | 'dich';\ntype X = Capitalize\u003CC>;\n\u002F\u002F   ^-- type X = \"Ich\" | \"☆\" | \"Liebe\" | \"Dich\"\n",[31,241,239],{"__ignoreMap":29},[19,243,244,245,248],{},"对联合类型使用 ",[31,246,247],{"code":247},"Capitalize"," 依旧遵循前面讲的分配率，即对每个类型单独进行大写操作后再合并起来",[23,250,253],{"className":251,"code":252,"language":28,"meta":29},[26],"\u002F**\n * 全变成大写\n *\u002F\ntype Uppercase\u003CS extends string> = intrinsic;\n\u002F**\n * 全变成小写\n *\u002F\ntype Lowercase\u003CS extends string> = intrinsic;\n\u002F**\n * 首字母大写\n *\u002F\ntype Capitalize\u003CS extends string> = intrinsic;\n\u002F**\n *首字母小写\n *\u002F\ntype Uncapitalize\u003CS extends string> = intrinsic;\n",[31,254,252],{"__ignoreMap":29},[19,256,257,260],{},[31,258,259],{"code":259},"intrinsic"," 表示是 TS 内置的泛型",[14,262,264],{"id":263},"a-b-ab","'a' 'b' => 'ab'",[23,266,269],{"className":267,"code":268,"language":28,"meta":29},[26],"type A = 'Ich';\ntype B = '☆';\ntype C = 'liebe';\ntype D = '☆';\ntype E = 'dich';\ntype X = `${A} ${B} ${C} ${D} ${E}`;\n\u002F\u002F   ^-- type X = \"Ich ☆ liebe ☆ dich\"\n",[31,270,268],{"__ignoreMap":29},[14,272,274],{"id":273},"ab-a","'ab' => 'a'",[23,276,279],{"className":277,"code":278,"language":28,"meta":29},[26],"type A = \"Ich ☆ liebe ☆ dich\"\ntype First\u003CT> = T extends `${infer F}${string}` ? F : never\ntype Result = First\u003CA>\n\u002F\u002F     ^-- \"I\"\n",[31,280,278],{"__ignoreMap":29},[14,282,284],{"id":283},"ab-b","'ab' => 'b'",[19,286,287],{},"字符串模式匹配的缺陷：只能获取到字符串中的第一个字符，获取不到最后一个字符",[19,289,290],{},"那么如何才能做到获取最后一个字符呢？",[19,292,293],{},"这里给出思路：",[89,295,296,299,302],{},[92,297,298],{},"我们可以获取元组的最后一项",[92,300,301],{},"字符串可以转为元组",[92,303,304],{},"我们可以获取字符串的最后一项",[23,306,309],{"className":307,"code":308,"language":28,"meta":29},[26],"type LastOfTuple\u003CT extends unknown[]> = T extends [...infer _, infer Last]\n  ? Last\n  : never;\ntype StringToTuple\u003CS extends string> = S extends `${infer First}${infer Rest}`\n  ? [First, ...StringToTuple\u003CRest>]\n  : [];\ntype LastOfString\u003CT extends string> = LastOfTuple\u003CStringToTuple\u003CT>>;\ntype Result = LastOfString\u003C'Ich ☆ liebe ☆ dich'>;\n\u002F\u002F     ^-- \"h\"\n\n",[31,310,308],{"__ignoreMap":29},[14,312,314],{"id":313},"string-联合类型","string => 联合类型",[23,316,319],{"className":317,"code":318,"language":28,"meta":29},[26],"type StringToUnion\u003CS extends string> = S extends `${infer First}${infer Rest}`\n  ? First | StringToUnion\u003CRest>\n  : never;\ntype Result = StringToUnion\u003C'Ich☆liebe☆dich'>;\n\u002F\u002F type Result = \"I\" | \"c\" | \"h\" | \"☆\" | \"l\" | \"i\" | \"e\" | \"b\" | \"d\"\n",[31,320,318],{"__ignoreMap":29},[19,322,323],{},"注意：联合类型自动去重了",[14,325,327],{"id":326},"string-元组","string => 元组",[23,329,332],{"className":330,"code":331,"language":28,"meta":29},[26],"type StringToTuple\u003CS extends string> = S extends `${infer First}${infer Rest}`\n  ? [First, ...StringToTuple\u003CRest>]\n  : [];\ntype Result = StringToTuple\u003C'Ich☆liebe☆dich'>;\n\u002F\u002F type Result = [\"I\", \"c\", \"h\", \"☆\", \"l\", \"i\", \"e\", \"b\", \"e\", \"☆\", \"d\", \"i\", \"c\", \"h\"]\n",[31,333,331],{"__ignoreMap":29},[19,335,336],{},"注意：元组没有去重",{"title":29,"searchDepth":338,"depth":338,"links":339},4,[340,350,356],{"id":12,"depth":341,"text":12,"children":342},2,[343,345,346,347,348,349],{"id":16,"depth":344,"text":17},3,{"id":35,"depth":344,"text":36},{"id":45,"depth":344,"text":45},{"id":64,"depth":344,"text":64},{"id":104,"depth":344,"text":104},{"id":120,"depth":344,"text":121},{"id":179,"depth":341,"text":179,"children":351},[352,353,354,355],{"id":182,"depth":344,"text":183},{"id":192,"depth":344,"text":193},{"id":202,"depth":344,"text":203},{"id":221,"depth":344,"text":222},{"id":231,"depth":341,"text":231,"children":357},[358,359,360,361,362,363],{"id":234,"depth":344,"text":235},{"id":263,"depth":344,"text":264},{"id":273,"depth":344,"text":274},{"id":283,"depth":344,"text":284},{"id":313,"depth":344,"text":314},{"id":326,"depth":344,"text":327},[365,366],"学习笔记","TypeScript","2023-02-22",false,"md",null,{"comments":368,"slots":372},{},true,"\u002F2023\u002Ftypescript\u002Fts-14",{"text":376,"minutes":377,"time":378,"words":379},"6 min read",5.89,353400,1178,{"title":5,"description":29},{"loc":374},"posts\u002F2023\u002Ftypescript\u002Fts-14",[366,384,149],"类型体操","tech","S5xaIR5LiPy5sxewGb3nd815GDyeASceA4x4UhYqrEc",[388,393],{"title":389,"path":390,"stem":391,"date":392,"type":385,"children":-1},"面向对象之 class（下）","\u002F2023\u002Ftypescript\u002Fts-13","posts\u002F2023\u002Ftypescript\u002Fts-13","2023-02-17",{"title":394,"path":395,"stem":396,"date":397,"type":385,"children":-1},"script 标签的 defer 与 async 属性（转载）","\u002F2023\u002Fasync-and-defer","posts\u002F2023\u002Fasync-and-defer","2023-03-17",1793699838407]