Interface

TS 中的核心概念,就是把 Javascript 中的弱语言类型变成强类型,也就是值进行类型检查。在TS中,一般有两种方式:一种是直接在变量初始化的时候就声明变量的类型,或者函数传参的时候在形参那里初始化类型。另外一种就是更加灵活的 Interface(接口)

Interface 定义了变量与类型的绑定关系,检测变量声明或者参数传参的合法性,并且可以更加灵活的校验参数传参的类型和个数。

最简单普通的一个Interface

  1. interface value{
  2. name:string;
  3. }
  4. let value: value = {name:"qujun"}

接口也可以是一个函数类型

  1. //函数类型的接口
  2. interface funInter {
  3. (name : string, age: number): void;
  4. }
  5. let myInfo: funInter;
  6. myInfo = (name : string, aa:number) =>{
  7. console.log(`${name},hi`)
  8. }
  9. myInfo('qu', 18)

当函数的参数为一个对象时 可以对参数进行额外的属性检查

  1. interface inter {
  2. name? : string;
  3. age? : number;
  4. }
  5. const myInfo2 = function(myinfo:inter):void{ /**code*/ }
  6. myInfo2({name1:'qujun', age :18}); 会有如下提示
  7. myInfo2({name1:'qujun', age :18} as inter); // 不会有错误提示

image.png
上面说明了name1 不在inter 接口的定义当中,as inter 相当于做了一次类型断言,绕开了检测

或者修改 interface 让它可以添加任意数量的其他属性

  1. interface inter {
  2. name? : string;
  3. age? : number;
  4. [propName: string]:any; // propName 必须为string 或 number(索引签名参数)
  5. }

上面的第四行 [propName: string]:any; 代码声明了一个 索引签名。
索引签名 :表示该接口下的参数以索引的类型返回对应类型的值

  1. interface arrInter {
  2. [index:number]:string //索引返回的值是string
  3. }
  4. interface objInter {
  5. [index:string]:Number; //索引返回的值是number
  6. level:Number; //参数的类型必须要跟索引返回值的类型一致
  7. age:Number;
  8. }
  9. let arr: arrInter = ["hello","world"]
  10. let obj: objInter = {level:20,age:18}
  11. let val:String = arr[0] //数字索引
  12. let val1:any = obj["name"] //字符串索引

可以给索引签名加上只读属性,意味着无法以索引的方式重新赋值

  1. interface arrInter {
  2. readonly [index:number]:String
  3. }
  4. // 跟上面代码一致..
  5. arr[1] = '你好'
  6. //**ts会提示错误 :类型“arrInter”中的索引签名仅允许读取**
  7. arr = ["ni","hao"] //重新赋值是允许的

class Type

顾名思义 该接口是为类定义的一个类型集合 使用 implements 实现

  1. interface classInter {
  2. name:String;
  3. age:Number;
  4. }
  5. class myInfo implements classInter {
  6. name:String;
  7. age: Number;
  8. constructor(name:String, age: Number){
  9. this.age = age
  10. this.name = name
  11. }
  12. }

如果interface 下是new 出来是类型时, 意味着它是静态类型。class 类 在使用 implements 生成一个构造函数时,ts会报错。

  1. interface constructorInter {
  2. new(name: string, age: string)
  3. }
  4. class myInfo implements constructorInter {
  5. name: string;
  6. age: number;
  7. constructor(name: string, age: number) {
  8. }
  9. }
  10. /*报错信息
  11. 类“myInfo”错误实现接口“constructorInter”。
  12. 类型“myInfo”提供的内容与签名“new (name: string, age: string): any”不匹配。ts(2420)
  13. */

原因是 当一个类实现了一个接口时 只会检查它的实例部分, constructor 存在于静态部分 ,所以不会检查, 需要经过如下调整

  1. interface constructorInter {
  2. new(name: string, age: number)
  3. }
  4. class myInfo {
  5. name: string;
  6. age: number;
  7. constructor(name: string, age: number) {
  8. }
  9. }
  10. const createInstance = function (cons: constructorInter, name: string, age: number) {
  11. return new cons(name, age)
  12. }
  13. createInstance(myInfo, 'qujun', 18)

接口继承

跟类一样,接口也可以进行继承

  1. interface interSuper {
  2. name: string;
  3. }
  4. interface inter extends interSuper {
  5. age: number
  6. }
  7. let info = <inter>{}
  8. info.name = 'qujun';
  9. info.age = 18;

也可以继承多个接口

  1. interface interName {
  2. name: string;
  3. }
  4. interface interAge {
  5. age: number;
  6. }
  7. interface inter extends interName, interAge {
  8. level: number
  9. }
  10. let info = <inter>{}
  11. info.name = 'qujun';
  12. info.age = 18;
  13. info.level = 66;

interface 也可以作为函数的返回值使用

  1. interface interInfo {
  2. name: string;
  3. age: number;
  4. }
  5. function myInfo():interInfo {
  6. let info = <interInfo>{} //表示声明一个具有interInfo接口的空对象
  7. info.name ="qujun";
  8. info.age = 18
  9. return info;
  10. }

最后总结一下 Interface 可以为那些结构定义类型

  • 普通对象
  1. interface value{
  2. name:string;
  3. }
  • 函数对象
  1. interface funInter {
  2. (name : string, age: number): void;
  3. }
  • 索引签名
  1. interface arrInter {
  2. [index:number]:string
  3. }
  • 实例对象
  1. interface constructorInter {
  2. new(name: string, age: string)
  3. }

有关 type 的 一些用法

  1. type str = string;
  2. type strResolve = () => string;
  3. type strOrResolve = str | strResolve;
  4. const fn = (n:strOrResolve) => {
  5. if(typeof n == 'string'){
  6. return n
  7. }else{
  8. return n()
  9. }
  10. }
  11. fn('str')
  12. const strFn = () => {return 'hello world'}
  13. fn(strFn)
  1. type str<T extends string> = T; // 声明一个
  2. function MyFn(name:str<string>){
  3. return name
  4. }
  5. MyFn('qujun')
  1. type Tvalue<T> = {value:T}
  2. const fn1 = (param : Tvalue<string>) => {
  3. // 只对参数负责,并不对函数的返回值负责
  4. return param.value.split['']
  5. }
  6. fn1({value:'qujun'})
  1. type Tree<T> = {
  2. value: T;
  3. left?: Tree<T>;
  4. right?: Tree<T>;
  5. };
  6. const fn2 = (tree: Tree<string>) => {
  7. return tree.value;
  8. };
  9. const mockTree = {
  10. value: "0",
  11. left: { value: "01" },
  12. right: { value: "02" },
  13. };
  14. fn2(mockTree);