娱乐圈惊天内幕:明星那些不为人知的“暗黑”面孔

核心内容摘要

探索别样风情:当神秘的黑色邂逅娇小的性感
stream69XXXC0m最新资源:解锁无限可能,开启你的数字娱乐新纪元!

91福利网:打开数字时代的宝藏之门,满足你所有想象

TypeScript学习-

接口Interface各位前端工友们上一章咱们给函数定了“工作规矩”搞定了输入输出的类型约束。

但随着业务变复杂咱们会遇到越来越多“复杂结构体”——比如API返回的用户信息、组件接收的Props、前后端约定的数据格式这些结构要是靠零散的类型标注来约束不仅代码冗余还容易出现不一致的问题。

这一章咱们就解锁TS的“结构化约束神器”——接口Interface。

如果说基础类型、复合类型是“零件规格”函数类型是“执行手册”那接口就是“总契约书”专门用来统一复杂结构的规则让所有关联代码都按同一套标准来既规范又好维护。

咱们还会吃透它和type的区别避免用错场景。

接口的基本定义给复杂结构立“契约”接口的核心作用的是“描述对象的结构”——明确规定一个对象必须有哪些属性、属性是什么类型就像一份契约只要某个对象符合契约里的规则就可以被认定为“符合该接口类型”。

这也是TS“鸭子类型”的核心体现只要长得像结构匹配就认为是同一类不用强制继承。

基本语法用interface关键字后面跟接口名首字母大写规范花括号里定义属性和类型// 定义一个Person接口约定对象必须有namestring和agenumber属性interfacePerson{name:string;age:number;}// 符合接口契约的对象类型匹配可直接赋值constuser:Person{name:张三,age:25};// 违反契约的错误示例// const wrongUser: Person {// name: 李四 // 报错缺少age属性// // age: 26 // 报错age类型应为number// };小提醒接口本身不生成任何JS代码编译后会被移除它只是TS用来做类型校验的“虚拟契约”仅在开发阶段生效不影响运行时性能。

接口的特性让契约更灵活、更严谨基础接口只能约束固定属性实际开发中需要应对“可选属性”“只读属性”“动态属性”等场景接口的三大特性就能搞定这些需求让契约既不僵化又不失约束性。

可选属性契约里的“非必填项”和函数的可选参数类似用?标记属性表示该属性“可有可无”适合对象属性不固定的场景比如用户的手机号、邮箱。

interfacePerson{name:string;age:number;phone?:string;// 可选属性可传可不传email?:string;}// 合法省略可选属性constuser1:Person{name:张三,age:25};// 合法包含部分可选属性constuser2:Person{name:李四,age:26,phone:13800138000};避坑点访问可选属性时仍需判断是否为undefined避免运行时错误和对象的可选属性逻辑一致。

只读属性契约里的“不可修改项”用readonly标记属性表示该属性仅能在对象初始化时赋值后续无法修改适合ID、创建时间等固定属性。

interfacePerson{readonlyid:number;// 只读属性初始化后不可改name:string;age:number;}constuser:Person{id:1001,name:张三,age:25};user.name张小三;// 可修改普通属性// user.id 1002; // 报错只读属性不能修改和只读数组、对象只读属性呼应只读仅限制“属性本身的赋值”如果属性值是引用类型比如对象、数组内部元素仍可修改。

索引签名应对“动态属性”的契约有些场景下对象的属性名不固定比如根据后端返回动态生成的键值对这时用“索引签名”就能约束动态属性的键和值的类型避免乱加属性。

语法[key: 键类型]: 值类型键类型通常是string或numberJS对象键本质是字符串数字键会自动转字符串。

// 索引签名键为string类型值为string类型interfaceDynamicObj{[key:string]:string;// 固定属性需兼容索引签名类型值必须是stringname:string;}constobj:DynamicObj{name:张三,gender:男,// 动态属性符合索引签名address:北京// 动态属性符合索引签名};// 错误示例值类型不符合索引签名// obj.age 25; // 报错age值为number预期string实用场景后端返回的“键值对字典”、表单的动态字段等用索引签名能精准约束同时兼容固定属性。

接口继承契约的“升级与复用”和面向对象的继承逻辑一致接口可以通过extends关键字继承其他接口实现“契约规则的复用与扩展”——子接口会包含父接口的所有属性再新增自己的属性不用重复定义。

// 父接口基础用户契约interfacePerson{name:string;age:number;}// 子接口学生契约继承Person并新增grade属性interfaceStudentextendsPerson{grade:number;// 学生专属属性}// 符合Student契约需包含Person的所有属性Student的属性conststudent:Student{name:王五,age:18,grade:12};// 错误示例缺少父接口属性// const wrongStudent: Student { name: 赵六, grade: 11 }; // 报错缺少age属性进阶用法接口支持多继承用逗号分隔多个父接口一次性复用多个契约的规则interfaceHasId{readonlyid:number;}interfaceHasName{name:string;}// 多继承同时继承HasId和HasNameinterfaceUserextendsHasId,HasName{age:number;}constuser:User{id:1001,name:张三,age:25};

接口与类型别名type到底该用谁前几章咱们用type定义过函数类型、对象类型这一章又学了接口很多新手会混淆两者——它们都能描述对象结构到底该怎么选核心结论接口适合定义“对象/函数的结构契约”type适合定义“类型组合联合、交叉、基础类型别名”具体区别咱们逐一拆解扩展性不同接口支持“声明合并”多次定义同一接口会自动合并属性适合后续扩展。

interface Person { name: string; } interface Person { age: number; } // 合并属性 const user: Person { name: 张三, age: 25 }; // 合法type一旦定义无法修改也不能合并类型是固定的。

type Person { name: string; }; // type Person { age: number; }; // 报错重复定义适用场景不同接口专门用于描述对象、函数的结构支持继承语义更清晰适合作为“契约”如API结构、组件Props。

type适用范围更广可定义基础类型别名type Num number、联合类型type NumOrStr number | string、交叉类型还能描述对象但不支持合并和继承可通过交叉类型模拟。

函数类型描述差异接口用函数签名描述适合作为“函数契约”单独导出。

interface AddFn { (a: number, b: number): number; }type写法更简洁适合临时定义函数类型。

type AddFn (a: number, b: number) number;

总结建议日常开发中定义API结构、组件Props、对象/函数契约时优先用接口需要定义联合类型、交叉类型、基础类型别名时用type。

两者不冲突可根据场景搭配使用。

函数接口给函数立“契约”除了描述对象接口也能描述函数的结构——本质和type定义函数类型一致只是用接口的语法来约束函数的参数和返回值适合作为“可复用的函数契约”。

// 定义函数接口接收两个number返回numberinterfaceAddFn{(a:number,b:number):number;}// 符合接口契约的函数constadd:AddFn(a,b)ab;constsum:AddFnfunction(a,b){returnab;};// 错误示例违反契约// const wrongAdd: AddFn (a, b) ${a b}; // 报错返回值应为number实用场景当多个函数需要遵循同一套参数/返回值规则时如回调函数集群、工具函数集合用函数接口比重复写type更规范也更易扩展。

实践接口的高频实战场景接口的价值最终体现在实战中咱们聚焦前端最常用的两个场景——约束API返回数据、约束组件Props手把手演示如何用接口落地。

场景1约束API返回数据结构前后端对接时用接口约定返回数据格式避免因后端字段变化、类型不一致导致的bug同时获得完整的代码提示。

// 约定用户列表API的返回结构interfaceUser{readonlyid:number;name:string;age:number;phone?:string;address?:{province:string;city:string;};}// API返回结果接口interfaceUserListResponse{code:number;message:string;data:User[];// 数据是User类型的数组}// 模拟API请求functionfetchUserList():PromiseUserListResponse{returnnewPromise((resolve){setTimeout((){resolve({code:200,message:success,data:[{id:1001,name:张三,age:25,address:{province:北京,city:北京}},{id:1002,name:李四,age:26,phone:13800138000}]});},

;});}// 调用API数据类型清晰有完整提示fetchUserList().then(res{res.data.forEach(user{console.log(user.name,user.address?.city);// 地址可选需判断});});场景2约束React组件PropsReact组件接收的Props用接口约束能避免传错参数、漏传参数同时编辑器会提供Props提示提升开发效率。

importReactfromreact;// 定义组件Props接口interfaceButtonProps{text:string;// 按钮文本必选type?:primary|default|danger;// 按钮类型可选限定值onClick:(e:React.MouseEventHTMLButtonElement)void;// 点击回调disabled?:boolean;// 是否禁用}// 按钮组件Props类型约束为ButtonPropsconstButton(props:ButtonProps){const{text,typedefault,onClick,disabledfalse}props;return(button className{btn btn-${type}}onClick{onClick}disabled{disabled}{text}/button);};// 使用组件Props自动校验有代码提示constApp(){return(divButton text提交typeprimaryonClick{(e)console.log(点击提交,e)}/Button text取消disabled{true}onClick{()console.log(点击取消)}//div);};

本章小结接口是“结构化约束的灵魂”这一章咱们吃透了接口的核心用法从基本定义、特性、继承到与type的区别、实战场景核心逻辑可以

总结为接口的本质是“可复用、可扩展的结构化契约”它不关心对象的具体实现只关心“结构是否匹配”鸭子类型完美解决了复杂结构的统一约束问题。

新手容易踩的坑一是忽略索引签名与固定属性的类型兼容二是混淆接口和type的适用场景滥用type定义对象结构三是忘记接口声明合并的特性重复定义接口。

记住“契约优先用接口类型组合用type”的原则就能少走弯路。

下一章咱们要进入面向对象的范畴学习TS中的类Class结合接口实现更严谨的面向对象编程让代码的封装性、复用性更上一层楼。

咱们下一章见

无需安装9.1直接进入网页-无需安装9.1直接进入网页应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123