TypeScript基础-接口、函数

227 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情
本篇是最基础的,有了解的可以越过。

接口

接口是对一堆属性或者方法的类型的声明,这些都应该是抽象的,需要由具体的类去实现。

常用的接口定义

interface Role {}
class Teacher {}

interface Person { 
  readonly id: string; //只读属性 
  name: string;
  weight?: number;  // 可选属性
  eat: () => void; // 方法
  say: (info: string) => string; // 方法
  company: { // 对象
    name: string;
  },
  role: Role;
  teach: Teacher; // 类类型,和下面要说的`接口继承类`意思差不多
  // 索引签名, 索引前面不能重复
  [propName: number]: number; // 数字索引签名
  [propName: string]: any; // 字符串索引签名, 类型必须可以或者包含接受所有其他属性的类型,如any
}
// 接口继承接口
interface Student extends Person {
    learn: () => void
}

interface PersonConstructor {
    new (name: string): Person;
}

函数类型接口:

interface GetPerson {
    (id: number): string;
}
const getPerson: GetPerson = function(id: number) {
  return '1';
}

接口继承类: 接口继承类中定义的所有属性和方法(包括修饰符修饰的成员,不包括构造函数),只是继承其成员不包含实现。

class Person {
  private name: string;
  age:number = 18;
  constructor(_name: string) {
    this.name = _name;
  }
  say(msg: string):string {
      return msg
  };
}

interface Teacher extends Person {
  teach: () => void;
}

补充:构造函数怎么在接口中定义,这里面我们先要理解一个类实现了某个接口,ts做类型检查时其实是对类的实例按接口中定义的属性检查,并不是对类。如下代码中其实就相当于是函数类接口,前面加了一个new关键字,但会值刚好是类的实例类型。

// new 定义类的类型,设置它的构造函数相关信息的类型
interface GetPerson {
    new (id: number): Person; 
}
const person = new Person(1);
// 一般用在将类重新付给一个变量时。
const getPerson: GetPerson = Person;
const person1 = new getPerson(1);

函数

默认参数=:函数调用的时候没有给某个参数传值,可以是使用函数参数定义时等号后面的默认值。

// 默认参数放在等号后面,默认参数和可选参数不同同时用在一个参数上。
function getTotal(value1: number, value2: number = 0): number {
    return value1 + value2;
}
getTotal(1) //1 正确
getTotal(1, 1); //2 正确
getTotal(1, undefined) //1 正确
getTotal(1, null) // 错误 null不能复制给value2: number | undefined

可选参数?: 调用函数的时候可以不传某些参数。

// 可选参数必须写在必填参数后面, 不包含默认参数。
function getTotal(value: number, value2?: number): number {
    if (value2) {
        return value + value2;
    }
    return value;
}
getTotal(1); //正确
getTotal(1, 2); //正确
getTotal(1, 2, 3); //错误,不能传递多余的参数

剩余参数...:在定义函数时,参数的个数不知道有多少个的时候可以使用剩余参数,相当于js以前使用的arguments。

// 剩余参数只能放到所有参数的最后面,且只能定义一个
function getTotal(value: number, ...values: number[]) {
    let total = value;
    for (let index = 0; index < values.length; index++) {
        total = total + values[index];  
    }
    return total;
}
let total = getTotal(1, 2, 3);

重载:一般用于处理逻辑基本一样,只是传递的参数类型不同或者个数不同,返回的结果类型也不同的场景。

interface Aa {
  a: string,
  c: {
      d: string
  }
}
const obj: Aa = { a: '22', c: { d: '3' } };
// 定义重载时重载的每个getValue中的参数个数要一样,不需要的参数也要用定义。
function getValue(x: number, b: number): number;
function getValue(x: Aa, a?: number): Aa;
function getValue(x: number | Aa, y: any): Aa | number { 
    // return 0; // 开发时尽量要严格按照传参的不同返回对应的类型数据,不然就如最后的console会报错,ts不会检查出来
    if (typeof x === 'number') {
        return 0;
    } else {
        return x;
    }
}
const data1: Aa = getValue(obj);
console.log(data1.c.d); 

箭头函数=>:和普通函数的区别主要在方法内的this指向不一致,箭头函数指向定义该函数的上下文环境上。

let getTotal: (value: number) => number;
getTotal = (value: number): number => {
  return value;
}