likes
comments
collection
share

TypeScript(四)对象和接口

作者站长头像
站长
· 阅读数 6

对象

对象是包含一组键值对的实例,值可以是标量、函数、数组、对象等。对象类型的最简单声明方法,就是使用大括号表示对象,在大括号内部声明每个属性和方法的类型。

const person: { name: string; age: number } = {
  name: "rinvay",
  age: 18,
};

typeinterface 关键字也可以声明对象类型。

type Person1 = {
  name: string;
  age: number;
};

interface Person2 {
  name: string;
  age: number;
}

const p1: Person1 = { name: "rinvay", age: 24 };
const p2: Person2 = { name: "rinvay", age: 24 };

可选属性

在属性后面加一个 ? 来表示该属性是可选的。

type Person = {
  name: string;
  age?: number;
};

const p2: Person = { name: "树街猫" };

const p1: Person = { name: "rinvay", age: 24 };

只读属性

属性名前面加上 readonly 关键字,表示这个属性是只读的,不可修改。

type Person = {
  readonly name: string;
  age?: number;
};

const p1: Person = { name: "rinvay", age: 24 };

p1.age = 2;
p1.name = "树街猫"; // error 无法为“name”赋值,因为它是只读属性

多个未知属性

通常外部 API 接口返回的对象,无法事前知道该对象会有多少属性,这时 ts 允许采用属性名表达式的写法来描述类型。

type T = {
  [s: string]: string | number;
};

const p1: T = { name: "rinvay", age: 24 };

解构赋值

解构赋值的类型写法,跟为对象声明类型是一样的。

type T = {
  x: string;
  y?: number;
};
const p1: T = { x: "rinvay", y: 24 };

const { x, y }: T = p1;

接口 interface

interface 是对象的模板,是一系列方法的声明,需要由具体的类去实现。

interface IPerson {
    firstName: string
    lastName: string
    getName: () => string
}

const p1: IPerson = {
    firstName: 'Tom',
    lastName: 'Hanks',
    getName: function () {
        return `${this.firstName} ${this.lastName}`
    },
}

在上面的例子中,定义了一个接口类型 Person,它拥有三个属性 firstNamelastNamegetName。任何实现这个接口的对象,都必须拥有与之对应类型的三个属性。p1 实现了接口 Person 的属性和方法。

interface 可以表示对象的各种语法。

interface Rect {
    x: number
    y: number
    z?: number // 可选参数
}

interface Person {
    readonly name: string // 只读属性
    age: number
}

// 定义接口参数
interface Params {
    [name: string]: string | number
}
const data: Params = { name: 'rinvay', age: 18 }

interface IArray {
    [index: number]: string
}
const words = ['A', 'B', 'C']

// 函数
interface F {
    fn(x: number): number
}

interface F1 {
    fn: (x: number) => number
}

// 函数重载
interface F2 {
    fn(): number
    fn(x: number): number
    fn(x: number, y: number): number
}

继承

接口继承就是说接口可以通过其他接口来扩展自己,ts 允许接口继承多个接口。

继承 interface。

使用关键字 extends,可以继承单接口和多个接口。

interface Person {
    age: number
}
// 单个接口继承
interface Musician extends Person {
    instrument: string
}

interface ParentA {
    v1: number
}
interface ParentB {
    v2: number
}
// 多个接口继承
interface Child extends ParentA, ParentB {}
继承 type

interface 同样可以使用关键字 extends继承 type 声明的对象类型

type Person = {
    age: number
}
interface Musician extends Person {
    instrument: string
}
继承 class

interface 也可以继承 class

class Shape {
    area: number
}

interface A extends Shape {
    getArea: () => number
}

const area: A = {
    area: 100,
    getArea: function () {
        return this.area
    },
}

上面示例中,A继承了 Shape,因此 A 有了Shape的属性 area 和自己的属性getArea。实现 A 接口的对象area就需要实现这些属性。

interface 与 type 的区别

(1)type 能够表示非对象类型,而 interface 只能表示对象类型。

type bizData = string | number | boolean

(2)interface 可以继承其他对象类型,type 不支持继承,只能通过 & 运算符来重新定一个类型。

type Person = {
    age: number
}

type Musician = Person & {
    instrument: string
}

interface Musician extends Person {
    instrument: string
}

(3)同名 interface 会自动合并,同名 type 则会报错。 interface 不允许与 type 同名。

type Person = {
    age: number
}

interface Person {
    name: string // error 标识符“Person”重复。
}

(4)interface 不能包含属性映射([prop in keyof A]表示依次得到类型 Point 的所有属性名,然后将每个属性的类型改成Point[Key],即为 number。)。

interface Point {
  x: number;
  y: number;
}

type Point1 = {
  [Key in keyof Point]: Point[Key];
};

interface Point2 {
    [Key in keyof Point]: Point[Key]; // error 应为声明或语句
};

(5)this 关键字只能用于 interface

interface F {
    add(num: number): this
}

type F = {
    add(num: number): this // error "this" 类型仅在类或接口的非静态成员中可用。
}