[{"data":1,"prerenderedAt":378},["ShallowReactive",2],{"content:\u002F2023\u002Ftypescript\u002Fts-7":3,"surround:\u002F2023\u002Ftypescript\u002Fts-7":367},{"id":4,"title":5,"body":6,"categories":343,"date":346,"description":28,"draft":347,"extension":348,"image":349,"meta":350,"navigation":352,"path":353,"permalink":349,"published":349,"readingTime":354,"recommend":349,"references":349,"seo":359,"sitemap":360,"stem":361,"tags":362,"type":365,"updated":349,"__hash__":366},"content\u002Fposts\u002F2023\u002Ftypescript\u002Fts-7.md","深入函数：声明、参数、返回值",{"type":7,"value":8,"toc":315},"minimark",[9,13,17,21,32,38,44,48,54,58,64,67,73,76,82,85,88,94,112,115,122,128,134,140,147,153,156,162,168,171,175,181,184,190,193,199,202,208,211,217,220,223,236,242,248,254,257,263,270,276,279,282,288,291,297,300,306,309],[10,11,12],"h2",{"id":12},"深入对象语法",[14,15,16],"h3",{"id":16},"描述对象的属性",[18,19,20],"p",{},"使用接口描述对象",[22,23,29],"pre",{"className":24,"code":26,"language":27,"meta":28},[25],"language-ts","type Person = {\n  name: string\n}\n\n\u002F\u002F 或者\ninterface Person {\n  name: string\n}\n","ts","",[30,31,26],"code",{"__ignoreMap":28},[18,33,34,37],{},[30,35,36],{"code":36},"Person"," 的子集为",[22,39,42],{"className":40,"code":41,"language":27,"meta":28},[25],"type Children =\n  | { name: string, age: string }\n  | { name: string, age: number }\n  | { name: string, age: boolean }\n  | { name: string, age: null }\n  | { name: string, age: undefined }\n  | { name: string, age: object }\n  | { name: string, gender: string }\n  | { name: string, gender: number }\n\u002F\u002F 以下省略一万行\n",[30,43,41],{"__ignoreMap":28},[14,45,47],{"id":46},"索引签名index-signature","索引签名（Index Signature）",[22,49,52],{"className":50,"code":51,"language":27,"meta":28},[25],"type Hash = {\n  [k: string]: unknown\n  length: number\n}\ntype List = {\n  [k: number]: unknown\n  length: number\n}\n",[30,53,51],{"__ignoreMap":28},[14,55,57],{"id":56},"映射类型mapped-type","映射类型（Mapped Type）",[22,59,62],{"className":60,"code":61,"language":27,"meta":28},[25],"type Hash = {\n  [k in string]: unknown\n}\ntype List = {\n  [k in number]: unknown\n}\n",[30,63,61],{"__ignoreMap":28},[18,65,66],{},"映射类型多用于泛型",[22,68,71],{"className":69,"code":70,"language":27,"meta":28},[25],"type Readonly\u003CT> = {\n  readonly [K in keyof T]: T[K];\n};\n",[30,72,70],{"__ignoreMap":28},[18,74,75],{},"需要注意的是，如果使用了映射类型，对象中就不能再有其他属性了，这点与索引签名有所不同",[22,77,80],{"className":78,"code":79,"language":27,"meta":28},[25],"type Hash = {\n  [k in string]: unknown\n  length: number\n  \u002F\u002F ^-- A mapped type may not declare properties or methods.\n}\n",[30,81,79],{"__ignoreMap":28},[14,83,84],{"id":84},"可选属性",[18,86,87],{},"可选属性的含义是该属性可以不存在",[22,89,92],{"className":90,"code":91,"language":27,"meta":28},[25],"interface InputProps {\n  defaultValue?: string;\n  value?: boolean;\n  onChange?: () => void;\n}\n",[30,93,91],{"__ignoreMap":28},[18,95,96,99,100,103,104,107,108,111],{},[30,97,98],{"code":98},"value?: boolean"," 可近似的理解成 ",[30,101,102],{"code":102},"value: boolean | undefined","，但是在声明对象属性时，",[30,105,106],{"code":106},"value?"," 可以不写，而 ",[30,109,110],{"code":110},"value"," 必须写",[14,113,114],{"id":114},"只读属性",[18,116,117,118,121],{},"有时候我们希望对象中的一些字段只能在创建的时候被赋值，那么可以用 ",[30,119,120],{"code":120},"readonly"," 定义只读属性",[22,123,126],{"className":124,"code":125,"language":27,"meta":28},[25],"interface User {\n  readonly id: number;\n  readonly name: string;\n  readonly scores: number[];\n  age?: number;\n}\nconst u: User = {\n  id: 1,\n  name: 'ClariS',\n  scores: [87, 65],\n};\n",[30,127,125],{"__ignoreMap":28},[18,129,130,131,133],{},"使用 ",[30,132,120],{"code":120}," 定义的属性初始化后不能被重新赋值",[22,135,138],{"className":136,"code":137,"language":27,"meta":28},[25],"u.id = 2;\n\u002F\u002F ^-- Cannot assign to 'id' because it is a read-only property.ts\nu.scores = [100, 65]\n\u002F\u002F ^-- Cannot assign to 'scores' because it is a read-only property.ts\n",[30,139,137],{"__ignoreMap":28},[18,141,142,143,146],{},"但是并没有对 ",[30,144,145],{"code":145},"scores"," 内部的属性做只读约束（只读约束只在第一层）",[22,148,151],{"className":149,"code":150,"language":27,"meta":28},[25],"u.scores[0] = 100;\n\u002F\u002F 不报错\n",[30,152,150],{"__ignoreMap":28},[10,154,155],{"id":155},"深入函数语法",[18,157,158],{},[159,160,161],"strong",{},"对象的语法全都适用于函数",[22,163,166],{"className":164,"code":165,"language":27,"meta":28},[25],"type F = {\n  (a: number, b: number): number;\n  readonly count?: number[];\n};\n\nconst fn: F = (x, y) => x + y;\nfn.count[0] = 1;\n",[30,167,165],{"__ignoreMap":28},[14,169,170],{"id":170},"声明函数的四种方式",[172,173,174],"h4",{"id":174},"先写类型再赋值",[22,176,179],{"className":177,"code":178,"language":27,"meta":28},[25],"type F1 = (a: number, b: number) => number;\nconst f1: F1 = (a, b) => a + b;\n",[30,180,178],{"__ignoreMap":28},[172,182,183],{"id":183},"箭头函数",[22,185,188],{"className":186,"code":187,"language":27,"meta":28},[25],"const f2 = (a: number, b: number): number => {\n  return a + b;\n};\ntype F2 = typeof f2;\n",[30,189,187],{"__ignoreMap":28},[172,191,192],{"id":192},"普通函数",[22,194,197],{"className":195,"code":196,"language":27,"meta":28},[25],"function f3(this: unknown, a: number, b: number): number {\n  return a + b;\n}\ntype F3 = typeof f3;\n",[30,198,196],{"__ignoreMap":28},[172,200,201],{"id":201},"匿名普通函数",[22,203,206],{"className":204,"code":205,"language":27,"meta":28},[25],"const f4 = function (this: unknown, a: number, b: number): number {\n  return a + b;\n};\ntype F4 = typeof f4;\n",[30,207,205],{"__ignoreMap":28},[172,209,210],{"id":210},"构造函数",[22,212,215],{"className":213,"code":214,"language":27,"meta":28},[25],"const f5 = new Function('a', 'b', 'return a + b');\ntype F5 = typeof f5;\n",[30,216,214],{"__ignoreMap":28},[18,218,219],{},"几乎没人会这么写吧 （思考）",[14,221,222],{"id":222},"类型谓词",[18,224,225,226,231,232,235],{},"之前在",[227,228,230],"a",{"href":229},"\u002F2023\u002Ftypescript\u002Fts-4#%E4%BD%BF%E7%94%A8%E7%B1%BB%E5%9E%8B%E8%B0%93%E8%AF%8D-is","联合类型","中讲过，可以使用类型谓词 ",[30,233,234],{"code":234},"is"," 来收窄类型，当时只简单提了一下不推荐使用箭头函数，这里说一下为什么",[22,237,240],{"className":238,"code":239,"language":27,"meta":28},[25],"type Person = { name: string }\ntype Animal = {}\n\nfunction isPerson(x: Person | Animal): x is Person {\n  return 'name' in x\n}\n\nfunction fn(a: Person | Animal) {\n  if (isPerson(a)) {\n    a \u002F\u002F Person\n  }\n}\n",[30,241,239],{"__ignoreMap":28},[18,243,244,245],{},"可以使用箭头函数实现 ",[30,246,247],{"code":247},"isPerson",[22,249,252],{"className":250,"code":251,"language":27,"meta":28},[25],"const isPerson = (x: Person | Animal): x is Person => 'name' in x\n",[30,253,251],{"__ignoreMap":28},[18,255,256],{},"但需要注意的是，如果使用的是箭头函数，不能先写类型再赋值",[22,258,261],{"className":259,"code":260,"language":27,"meta":28},[25],"type A = (x: Person | Animal) => x is Person\nconst isPerson: A = x => 'name' in x\n\u002F\u002F       ^--- Type '(x: Person | Animal) => boolean' is not assignable to type 'A'\n",[30,262,260],{"__ignoreMap":28},[18,264,265,266,269],{},"在右边加上 ",[30,267,268],{"code":268},"x is Person"," 就不报错了",[22,271,274],{"className":272,"code":273,"language":27,"meta":28},[25],"type A = (x: Person | Animal) => x is Person\nconst isPerson: A = (x): x is Person => 'name' in x\n",[30,275,273],{"__ignoreMap":28},[14,277,278],{"id":278},"参数相关语法",[172,280,281],{"id":281},"可选参数",[22,283,286],{"className":284,"code":285,"language":27,"meta":28},[25],"function addEventListener(eventType: string, fn: unknown, useCapture?: boolean) {\n  if (useCapture === undefined) {\n    useCapture = false\n  }\n  \u002F\u002F 浏览器实现\n  console.log(eventType, fn, useCapture)\n}\n\naddEventListener('click', () => 1)\n",[30,287,285],{"__ignoreMap":28},[172,289,290],{"id":290},"参数默认值",[22,292,295],{"className":293,"code":294,"language":27,"meta":28},[25],"function addEventListener(eventType: string, fn: unknown, useCapture = false) {\n  \u002F\u002F 浏览器实现\n  console.log(eventType, fn, useCapture)\n}\n\naddEventListener('click', () => 1)\n",[30,296,294],{"__ignoreMap":28},[172,298,299],{"id":299},"参数也可以是函数",[22,301,304],{"className":302,"code":303,"language":27,"meta":28},[25],"function addEventListener(\n  eventType: string,\n  fn: (this: HTMLElement, e: Event) => void,\n  useCapture = false\n) {\n  \u002F\u002F 浏览器实现，这里只提供伪代码\n  const element = {} as HTMLElement;\n  const event = {} as Event;\n  fn.call(element, event);\n  console.log(eventType, fn, useCapture);\n}\n\naddEventListener('click', () => 1);\n",[30,305,303],{"__ignoreMap":28},[172,307,308],{"id":308},"返回值也可以是函数",[22,310,313],{"className":311,"code":312,"language":27,"meta":28},[25],"const add = (a: number, b: number) => a + b\ntype CreateAdd = (x: number) => (y: number) => number\nconst createAdd: CreateAdd = a => b => a + b\n\nadd(6, 14)\ncreateAdd(6)(14)\n",[30,314,312],{"__ignoreMap":28},{"title":28,"searchDepth":316,"depth":316,"links":317},4,[318,327],{"id":12,"depth":319,"text":12,"children":320},2,[321,323,324,325,326],{"id":16,"depth":322,"text":16},3,{"id":46,"depth":322,"text":47},{"id":56,"depth":322,"text":57},{"id":84,"depth":322,"text":84},{"id":114,"depth":322,"text":114},{"id":155,"depth":319,"text":155,"children":328},[329,336,337],{"id":170,"depth":322,"text":170,"children":330},[331,332,333,334,335],{"id":174,"depth":316,"text":174},{"id":183,"depth":316,"text":183},{"id":192,"depth":316,"text":192},{"id":201,"depth":316,"text":201},{"id":210,"depth":316,"text":210},{"id":222,"depth":322,"text":222},{"id":278,"depth":322,"text":278,"children":338},[339,340,341,342],{"id":281,"depth":316,"text":281},{"id":290,"depth":316,"text":290},{"id":299,"depth":316,"text":299},{"id":308,"depth":316,"text":308},[344,345],"学习笔记","TypeScript","2023-02-01",false,"md",null,{"comments":347,"slots":351},{},true,"\u002F2023\u002Ftypescript\u002Fts-7",{"text":355,"minutes":356,"time":357,"words":358},"6 min read",5.055,303300,1011,{"title":5,"description":28},{"loc":353},"posts\u002F2023\u002Ftypescript\u002Fts-7",[345,363,364],"映射类型","索引签名","tech","OaSU1c2Rb1YdjYRTzrcPNCDoFSm7TR61iOaZIH5LCR8",[368,373],{"title":369,"path":370,"stem":371,"date":372,"type":365,"children":-1},"类型兼容与赋值","\u002F2023\u002Ftypescript\u002Fts-6","posts\u002F2023\u002Ftypescript\u002Fts-6","2023-01-30",{"title":374,"path":375,"stem":376,"date":377,"type":365,"children":-1},"深入函数：函数重载、this 和 as const","\u002F2023\u002Ftypescript\u002Fts-8","posts\u002F2023\u002Ftypescript\u002Fts-8","2023-02-03",1793699839381]