likes
comments
collection
share

typeScript 接口(interface)及其与类型别名(type)的区别

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

接口在typeScript中是用来定义对象的类型,对于没有其他语言基础,又刚入门typeScript的同学,可能刚开始觉得接口概念很简单,深入之后又觉得揉杂,本文作者结合自己的学习体验来介绍TypeScript中接口的基本概念及其使用方法。

1.接口基本概念

接口在ts中使用interface来定义,首先看一个最简单示例:

最简单的例子

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

let tom: Person = {
    name: 'Tom',
    age: 25
};

这个例子定义了一个接口Person,接着定义了一个变量tom,他的类型是Person,约束了tom的形状必须和接口Person保持一致。如果变量tom中多一些属性,少一些属性,都是不可以的。

可选属性

当存在某些属性,我们希望灵活生成的对象灵活匹配的时候,可以使用可选属性?:

interface Person {
    name: string;
    age?: number; // 可选属性
}

let tom: Person = {
    name: 'Tom',
    age: 25
};
let lee: Person = {
    name: 'Lee'
}

任意属性

有时候我们希望一个接口允许有任意的属性,可以使用任意属性[propName: string]

interface Person {
    name: string;
    age?: number;
    [propName: string]: string | number | undefined; // 任意属性
}

let tom: Person = {
    name: 'Tom',
    age: 25,
    gender: 'male'
};

注意:一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集

只读属性

某些字段只希望在对象创建的时候被赋值,那么可以用 readonly 定义只读属性:

interface Person {
    readonly id: number;
    name: string;
    age?: number;
    [propName: string]: any;
}

let tom: Person = {
    id: 89757,
    name: 'Tom',
    gender: 'male'
};

比如上图中的readonly,如果通过tom.id = xx的方式去修改,则会报错。

注意 只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候

2.接口的使用

普通对象类型

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

let tom: Person = {
    name: 'Tom',
    age: 25
};

函数类型

interface SearchFunc { 
    (source: string, subString: string): boolean; 
}

let mySearch: SearchFunc;
mySearch = function(src, sub) {
    let result = src.search(sub)
}

可索引类型

比如数组也可以使用接口去定义类型,但是不推荐这么使用

interface StringArray { 
    [index: number]: string; 
}
let myArray: StringArray;
myArray = ["Bob", "Fred"];

混合类型

一个对象可以同时作为函数和对象使用,并带有额外的属性

interface Counter { 
    (start: number): string; 
    interval: number; 
    reset(): void; 
} 
function getCounter(): Counter { 
    let counter = <Counter>function (start: number) { }; 
    counter.interval = 123; 
    counter.reset = function () { }; 
    return counter; 
} 
let c = getCounter(); 
c(10); 
c.reset(); 
c.interval = 5.0;
  • 类与接口的几个问题

接口继承接口

interface Shape {
    color: string
}
interface Heigh {
    height: number
}
interface Square extends Shape,Heigh {
    width: number
}

// let mySquare: Square = {}
let mySquare = <Square>{}
mySquare.color = 'ss'
mySquare.width = 12
mySquare.height = 22

类实现接口

interface Alarm {
    alert(): void;
}

class Door {
}

class SecurityDoor extends Door implements Alarm {
    alert() {
        console.log('SecurityDoor alert');
    }
}

class Car implements Alarm {
    alert() {
        console.log('Car alert');
    }
}

接口继承类

class Point {
    x: number;
    y: number;
    constructor(x: number, y: number) {
        this.x = x;
        this.y = y;
    }
}

interface Point3d extends Point {
    z: number;
}

let point3d: Point3d = {x: 1, y: 2, z: 3};

为什么 TypeScript 会支持接口继承类呢?

实际上,当我们在声明 class Point 时,除了会创建一个名为 Point 的类之外,同时也创建了一个名为 Point 的类型(实例的类型)。

所以我们既可以将 Point 当做一个类来用(使用 new Point 创建它的实例), 也可以将 Point 当做一个类型来用(使用 : Point 表示参数的类型):

  • 声明 Point 类时创建的 Point 类型只包含其中的实例属性和实例方法

接口的合并

interface User {
    name: string
}
interface User {
    age: number
}
会合并成为一个接口
interface User {
    name: string
    age: number
}

3.interface与type的异同点

初学interface与type时,总会搞混这两个概念,很多功能两者都可以实现,这里再区分一下两者的异同:

  • interface 接口,主要的作用是定义对象、函数等的结构类型;
  • type 类型别名,可以用来给类型起一个新名字;

相同点:

都可以描述对象和函数

  • interface
interface myObj {
    name: string
    age: number
}
interface myFunc {
    (name: string): void
}
  • type
type myObj = {
    name: string,
    age: number
}
type myFunc = {
    (name: string): void
}

都允许扩展

  • interface
interface Area {
    width: number
    height: number
}
interface Picture extends Area {
    color: string
}
  • type
type Area = {
    width: number
    height: number
}
type Picture = Area & { color: string }

不同点

  • type 可以声明基本类型别名,联合类型字符串字面量,元组,获取实例类型
type Name = string;
type NameResolver = () => string;
type NameOrResolver = Name | NameResolver;
function getName(n: NameOrResolver): Name {
    if (typeof n === 'string') {
        return n;
    } else {
        return n();
    }
}

type PetList = [string, number]

type normalColor = 'red' | 'green' | 'black'


// 获取实例类型
type myObj = {
    name: string,
    age: number
}
let mineObj: myObj = {
    name: '2w',
    age: 12
}
type anotherObj = typeof mineObj
  • interface 可以声明合并
interface User {
    name: string
}
interface User {
    age: number
}
会合并成为一个接口
interface User {
    name: string
    age: number
}
转载自:https://juejin.cn/post/7147575342163738638
评论
请登录