深入理解Typescript系列-接口

690 阅读3分钟

这是我参与 8 月更文挑战的第 13 天,活动详情查看: 8月更文挑战

前言

在上篇文章中,我们谈及了TS的类型系统,以及它的能帮助我们解决什么问题。而接口,作为一种重要的类型约束方式,这篇文章,我们会展开来谈谈接口。接口简单来说就是规定一些 “事”,在后台中,接口指的是双方规定的 API,在 TS 里接口一般指这个变量拥有什么东西。

初探

我们先来对一个函数做一个参数约定

    function test(args: { title: string }) {
        return args.title;
    }
    test({ title: 'x' }) // x

类型检查器会查看test的调用参数,并检查参数是否符合约定规范,为一个对象,包含一个sting类型title字段,如果不符合,则会在检查阶段跑出错误。

interface

有时候,我们的参数多,我们也希望接口可以进行代码复用,那么就可以这么写

    interface Args {
        title: string;
        body: string;
    }
    function test(args: Args) {
        return args.title;
    }
    function test2(args: Args) {
        return args.body;
    }

函数的参数会逐个进行检查,要求对应位置上的参数类型是兼容的。 如果你不想指定类型,TypeScript的类型系统会推断出参数类型,因为函数直接赋值给了函数类型变量。 函数的返回值类型是通过其返回值推断出来的(此例是 false和true)。 如果让这个函数返回数字或字符串,类型检查器会警告我们函数的返回值类型与接口中的定义不匹配。

可选参数、动态参数

在上述接口定义中,属性是必须的,不能多也不能少,在一些情况下,我们希望有些参数是可选的,甚至是动态的,那么我们可以改造成这样:

    interface Args {
        title: string;
        body: string;
        x?: number; // 可选属性
        [y: string]: any; // 动态属性
    }
    function test(args: Args) {
        return args.title;
    }
    function test2(args: Args) {
        return args.body;
    }

函数返回类型

为了使用接口表示函数类型,我们需要给接口定义一个调用签名。 它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。

这样定义后,我们可以像使用其它接口一样使用这个函数类型的接口。

    interface SearchFunc {
        (source: string, subString: string): boolean;
    }
    let mySearch: SearchFunc;
    mySearch = function(source: string, subString: string) {
        let result = source.search(subString);
        return result > -1;
    }

接口编程

有些时候,我们会在一个实例初始化的时候做一些事情,这时候,interface可以用class来实现

    class Cat {
        name: string;
        color: string;
        constructor(name: number, color: number) {
            this.name = name;
            this.color = color;
        }
    }
    function cloneCat(cat: Cat): Cat {
        return new Cat(cat.name, cat.color)
    }

接口继承

和类一样,接口也可以相互继承。

    interface Shape {
        color: string;
    }

    interface Square extends Shape {
        sideLength: number;
    }

小结

接口的定义分为了三种:interface、type和class,class是可编程的interface,type则是可以声明基础类型。

如果不清楚什么时候用interface/type,能用 interface 实现,就用 interface , 如果不能就用 type 。