[{"data":1,"prerenderedAt":396},["ShallowReactive",2],{"content:\u002F2023\u002Ftypescript\u002Fts-6":3,"surround:\u002F2023\u002Ftypescript\u002Fts-6":385},{"id":4,"title":5,"body":6,"categories":353,"date":356,"description":22,"draft":357,"extension":358,"image":359,"meta":360,"navigation":362,"path":363,"permalink":359,"published":359,"readingTime":364,"recommend":359,"references":359,"seo":369,"sitemap":370,"stem":381,"tags":382,"type":383,"updated":359,"__hash__":384},"content\u002Fposts\u002F2023\u002Ftypescript\u002Fts-6.md","类型兼容与赋值",{"type":7,"value":8,"toc":336},"minimark",[9,13,17,24,51,54,57,63,68,74,91,94,99,102,107,123,126,135,138,141,146,149,152,156,162,167,170,211,214,220,223,228,234,245,248,251,256,259,262,268,275,283,289,292,296,299,321,330],[10,11,12],"h2",{"id":12},"为什么要有类型兼容",[14,15,16],"p",{},"因为实际工作中，往往无法做到类型一致",[14,18,19],{},[20,21],"img",{"alt":22,"src":23},"","\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_01.png",[14,25,26,27,31,32,35,36,35,39,42,43,46,47,50],{},"比如在上面的 JS 代码中，假设 ",[28,29,30],"code",{"code":30},"runTask"," 函数的参数只接受具有 ",[28,33,34],{"code":34},"a","、",[28,37,38],{"code":38},"b",[28,40,41],{"code":41},"c"," 这 3 个 ",[28,44,45],{"code":45},"key"," 的对象，但在一般情况下，即使我们多传一个 ",[28,48,49],{"code":49},"d","，也不会报错",[14,52,53],{},"你有的，我都有，则我能代替你；\ny 有的，x 都有，则 x 兼容 y",[10,55,56],{"id":56},"简单类型的兼容",[14,58,59],{},[60,61,62],"strong",{},"类型小的兼容类型大的",[14,64,65],{},[20,66],{"alt":22,"src":67},"\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_02.png",[69,70,71],"blockquote",{},[14,72,73],{},"注意：图中的大小圆应当是包含关系，即小圆应该在大圆内部，此处为了展示清晰将小圆挪到了外部，后面的图示亦如此",[14,75,76,77,80,81,84,85,87,88,90],{},"集合 ",[28,78,79],{"code":79},"hi"," 小于集合 ",[28,82,83],{"code":83},"A","，因此将 ",[28,86,79],{"code":79}," 赋值给 ",[28,89,34],{"code":34}," 不报错",[10,92,93],{"id":93},"普通对象的兼容",[14,95,96],{},[60,97,98],{},"属性多的兼容属性少的",[14,100,101],{},"对象属性越多，限制越多，表示的集合范围越小，所以其实还是类型小的兼容类型大的",[14,103,104],{},[20,105],{"alt":22,"src":106},"\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_03.png",[69,108,109],{},[14,110,111,112,115,116,119,120],{},"注意：对象兼容的前提是必须得存在",[60,113,114],{},"共同的属性","，此处两个对象共同的属性是 ",[28,117,118],{"code":118},"name"," 和 ",[28,121,122],{"code":122},"age",[14,124,125],{},"兼容的情况下，作为参数也不报错",[127,128,133],"pre",{"className":129,"code":131,"language":132,"meta":22},[130],"language-ts","type Person = { name: string; age: number }\nlet user = { name: 'ClariS', age: 18, id: 1, email: 'xxx@yyy.com' }\n\nlet p: Person = user \u002F\u002F 不报错\n\nconst f1 = (p: Person) => {\n  console.log(p)\n}\nf1(user) \u002F\u002F 不报错\n","ts",[28,134,131],{"__ignoreMap":22},[10,136,137],{"id":137},"接口的兼容",[14,139,140],{},"子接口兼容父接口",[14,142,143],{},[20,144],{"alt":22,"src":145},"\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_04.png",[10,147,148],{"id":148},"函数的兼容",[14,150,151],{},"函数的兼容比较复杂，需要考虑参数和返回值",[153,154,155],"h3",{"id":155},"参数个数不同",[14,157,158,159],{},"存在相同类型的参数的函数，",[60,160,161],{},"参数少的兼容参数多的",[14,163,164],{},[20,165],{"alt":22,"src":166},"\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_05.png",[14,168,169],{},"如何理解上图中的兼容关系？（图中绿色箭头代表可以兼容，红色箭头表示不能兼容）",[171,172,174,177,200],"folding",{"title":173},"如何理解上图中的代码？（图中绿色箭头代表可以兼容，红色箭头表示不能兼容）",[14,175,176],{},"主要看划线的右边参数的部分：",[178,179,180,193],"ol",{},[181,182,183,184,119,186,188,189,192],"li",{},"从上往下看，箭头全绿（",[28,185,34],{"code":34},[28,187,38],{"code":38}," 都是 ",[28,190,191],{"code":191},"number","）",[181,194,195,196,199],{},"从下往上看，存在红色的箭头（参数 ",[28,197,198],{"code":198},"s"," 没有可以兼容的参数）",[14,201,202,203,206,207,210],{},"因此 ",[28,204,205],{"code":205},"接受一个参数的函数"," 兼容  ",[28,208,209],{"code":209},"接受两个参数的函数","，反过来则不行",[14,212,213],{},"为什么容忍参数变少呢？从下例中可以窥探一二",[14,215,216],{},[20,217],{"alt":218,"src":219},"在 JS 中，少写参数是很常见的事情","\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_06.png",[153,221,222],{"id":222},"参数类型不同",[14,224,225],{},[60,226,227],{},"对参数要求少的兼容对参数要求多的",[14,229,230],{},[20,231],{"alt":232,"src":233},"和参数的兼容关系正好相反","\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_07.png",[14,235,236,237,240,241,244],{},"从前面的例子我们知道，",[28,238,239],{"code":239},"MyMouseEvent"," 是兼容 ",[28,242,243],{"code":243},"MyEvent"," 的，这里函数的兼容关系就正好反过来了。",[153,246,247],{"id":247},"返回值不同",[14,249,250],{},"不考虑参数类型的情况下，函数的兼容关系和返回值的兼容关系保持一致",[14,252,253],{},[20,254],{"alt":22,"src":255},"\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_08.png",[14,257,258],{},"思考：如果函数的参数和返回值同时存在且兼容关系相反呢？",[153,260,261],{"id":261},"实际工作中的函数",[127,263,266],{"className":264,"code":265,"language":132,"meta":22},[130],"interface Event {\n  timestamp: number;\n}\ninterface MyMouseEvent extends Event {\n  x: number;\n  y: number;\n}\nfunction listenEvent(eventType: string, handler: (n: Event) => void) {\n  \u002F* ... *\u002F\n}\n\u002F\u002F 我们希望这样用，但会报错\nlistenEvent(\"click\", (e: MyMouseEvent) => console.log(e.x + \",\" + e.y));\n\n\u002F\u002F 因此只能这样用\nlistenEvent(\"click\", (e: Event) =>\n  console.log((e as MyMouseEvent).x + \",\" + (e as MyMouseEvent).y)\n);\n\n\u002F\u002F 还可以这么用\nlistenEvent(\"click\", ((e: MyMouseEvent) => console.log(e.x + \",\" + e.y)) as (\n  e: Event\n) => void);\n\n\u002F\u002F 这个就太离谱了，也会报错\nlistenEvent(\"click\", (e: number) => console.log(e));\n",[28,267,265],{"__ignoreMap":22},[14,269,270,271,274],{},"在不关闭 TS 严格检查的情况下，可以通过设置 ",[28,272,273],{"code":273},"\"strictFunctionTypes\": false"," 来避免函数报错",[127,276,281],{"className":277,"code":279,"language":280,"meta":22},[278],"language-json","\u002F\u002F tsconfig.json\n{\n  \"compilerOptions\": {\n    \"strict\": true,\n    \"strictFunctionTypes\": false,\n    ...\n  }\n}\n","json",[28,282,279],{"__ignoreMap":22},[14,284,285],{},[20,286],{"alt":287,"src":288},"设置 \"strictFunctionTypes\": false 后","\u002Fimages\u002Ftypescript\u002Fts-6\u002Fts_6_09.png",[10,290,291],{"id":291},"特殊类型的兼容",[10,293,295],{"id":294},"顶类型top-type与底类型bottom-type","顶类型（Top Type）与底类型（Bottom Type）",[14,297,298],{},"在 TS 中，顶类型（Top Type）表示可以接受任何值的类型，而底类型（Bottom Type）表示不可能有任何值的类型。",[14,300,301,302,119,305,308,309,311,312,308,315,317,318,308],{},"顶类型通常称为通用超类型，因为它是系统中所有其他类型的超类型。TS 提供了两种顶类型：",[28,303,304],{"code":304},"any",[28,306,307],{"code":307},"unknown","。",[28,310,304],{"code":304}," 类型表示可以接受任何值，但它",[60,313,314],{},"不提供任何类型检查",[28,316,307],{"code":307}," 类型也可以接受任何值，但在使用之前",[60,319,320],{},"必须先进行类型检查",[14,322,323,324,308,327,329],{},"底类型通常称为通用子类型，因为它通常是系统中所有其他类型的子类型。TS 提供了一种底类型：",[28,325,326],{"code":326},"never",[28,328,326],{"code":326}," 类型表示不可能有任何值，它用于表示永远不会返回值的函数或抛出异常的函数的返回类型。",[127,331,334],{"className":332,"code":333,"language":132,"meta":22},[130],"\u002F\u002F Top Type 示例\nlet topType: unknown;\ntopType = 1; \u002F\u002F 可以赋任何值\ntopType = 'hello';\n\n\u002F\u002F Bottom Type 示例\nfunction throwError(): never {\n  throw new Error('Error');\n}\n",[28,335,333],{"__ignoreMap":22},{"title":22,"searchDepth":337,"depth":337,"links":338},4,[339,341,342,343,344,351,352],{"id":12,"depth":340,"text":12},2,{"id":56,"depth":340,"text":56},{"id":93,"depth":340,"text":93},{"id":137,"depth":340,"text":137},{"id":148,"depth":340,"text":148,"children":345},[346,348,349,350],{"id":155,"depth":347,"text":155},3,{"id":222,"depth":347,"text":222},{"id":247,"depth":347,"text":247},{"id":261,"depth":347,"text":261},{"id":291,"depth":340,"text":291},{"id":294,"depth":340,"text":295},[354,355],"学习笔记","TypeScript","2023-01-30",false,"md",null,{"comments":357,"slots":361},{},true,"\u002F2023\u002Ftypescript\u002Fts-6",{"text":365,"minutes":366,"time":367,"words":368},"6 min read",5.115,306900,1023,{"title":5,"description":22},{"loc":363,"images":371},[372,373,374,375,376,377,378,379,380],{"loc":23},{"loc":67},{"loc":106},{"loc":145},{"loc":166},{"loc":219},{"loc":233},{"loc":255},{"loc":288},"posts\u002F2023\u002Ftypescript\u002Fts-6",[355],"tech","sfNFAStPC4ypXGYY-e0O8GuMPD8uYJ-dPqx9R7dy_98",[386,391],{"title":387,"path":388,"stem":389,"date":390,"type":383,"children":-1},"TS 中的类型运算：交叉类型","\u002F2023\u002Ftypescript\u002Fts-5","posts\u002F2023\u002Ftypescript\u002Fts-5","2023-01-17",{"title":392,"path":393,"stem":394,"date":395,"type":383,"children":-1},"深入函数：声明、参数、返回值","\u002F2023\u002Ftypescript\u002Fts-7","posts\u002F2023\u002Ftypescript\u002Fts-7","2023-02-01",1793699839390]