TypeScript -- ts接口

本文详细介绍了TypeScript的接口概念,包括可选属性、只读属性、任意属性、函数类型接口、索引类型、类类型、接口继承和混合类型。通过实例代码展示了如何定义和使用接口,以及接口在描述对象形状和行为抽象中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一节,我们简单的介绍ts的基础数据类型,那么接下来我们来介绍ts的接口。

TS的接口

接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。

JS中是没有接口的概念的,在 TypeScript 中,我们使用接口interface来定义接口。
在ts中,接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对对象的形状进行描述。
我们先来看一个简单的代码,来认识一下接口。

interface Person {
    name: string,
    age: number
}

function sayHello(person: Person) {
    return `Hello! I am ${person.name}, ${person.age} years old.`;
}

let  p1: Person = {
    name: "cyl",
    age: 21
}

console.log(sayHello(p1));

我们定义了一个简单的接口,用来对Person对象的形状进行描述。我们在调用sayHello函数时,多给一些属性,或者属性数据类型错误都是不行的。
赋值的时候,变量的形状必须和接口的形状保持一致。

可选属性

有时我们希望不要完全匹配一个形状,那么可以用可选属性。

interface Person {
    name: string,
    age?: number
}

function sayHello(person: Person) {
    return `Hello! I am ${person.name}`;
}

let  p1: Person = {
    name: "cyl"
}

console.log(sayHello(p1));

我们在age的:前面添加一个?表示这是一个可选属性,可以不用给。

只读属性

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

interface Person {
    readonly id: string,
    name: string,
    age?: number
}

let p: Person = {
    id: '1',
    name: "jake",
    age: 16
}

p.id = "2";

我们在id属性前面加上readonly那么id属性就变成一个只读属性,对其进行修改会报错的。
在这里插入图片描述
constreadonly的区别,如果你想限定某个变量不允许其发生改变,那么你应该使用const。如果你想限定一个对象的某个属性不允许发生改变,那么你应该使用readonly

任意属性

首先,我们先看一段ts代码

interface Person {
    name?: string,
    age: number
}

function sayHello(person: Person) {
    return `Hello! I am ${person.name}, ${person.age} years old.`;
}

console.log(sayHello({nam: "tom", age: 16}))

不难发现,这段代码在写的时候编译器就会提示报错。
在这里插入图片描述

但是有时候,我们难免传递了一些不重要的参数 ,但是不想一个一个的去兼容它们,这个时候就需要任意属性了。

interface Person {
    name?: string,
    age: number,
    [propName: string]: any
}

在这里插入图片描述
没有问题了。

函数类型接口
直接看代码吧,对于函数类型接口,我们只需要定义参数类型和返回值类型

interface SearchStr {
    (source: string, subString: string): boolean
}

let mySearch: SearchStr = function (sou: string, sub: string) {
    let index = sou.indexOf(sub);
    return index > -1;
}

索引类型
ts支持俩种类型的索引签名,如下:

interface NumberArray {
    [index: number]: string
}
const arr1: NumberArray = ["bob", "alice"];
console.log(arr1[0]);

interface StringArray {
    [index: string]: string
}
const arr2: StringArray = {
    "name": "bob",
    "age": "16"
}
console.log(arr2['name']);

一种以数字为下标,一种以字符串为下标。
当你声明一个索引签名时,所有明确的成员都必须符合索引签名

// ok
interface Foo {
  [key: string]: number;
  x: number;
  y: number;
}

// Error
interface Bar {
  [key: string]: number;
  x: number;
  y: string; // Error: y 属性必须为 number 类型
}

当然你可以在同一个接口使用俩种索引类型
string 类型的索引签名比 number 类型的索引签名更严格。这是故意设计,它允许你有如下类型

interface ArrStr {
  [key: string]: string | number; // 必须包括所用成员类型
  [index: number]: string; // 字符串索引类型的子级

  // example
  length: number;
}

当然索引签名也是可以设置为只读的,通过添加readonly来实现。

上面主要是介绍了接口对于对象的形状进行描述,接下来介绍接口的另一个功能对于属性和行为的抽象

类类型
我们直接来看代码吧!

interface Person {
    name: string,
    age: number,
    speak()
}
class Student implements Person {
    name: string
    age: number

    constructor(n: string, a: number) {
        this.name = n;
        this.age = a;
    }
    speak() {
        console.log(`I am ${this.name}, ${this.age} years old.`)
    }
}

const s = new Student("tom", 21);
s.speak();

我们定义了一个接口,里面含有name,age俩个属性然后一个speak方法,然后我们又声明了一个Student类使用implements关键字去实现了这个接口。PS: 对于TS的类,我会在下篇博客学习,不着急。
当一个类使用implements关键字去实现接口时,那么对于接口里面定义的属性,方法(非可选的)都必须实现,不然就会报错。
简单的说就是,接口只是声明了这些方法和属性,实现类必须要去实现它。
我想你应该了解了一点了,那么我在深入一点。
在TS中,类上面存在俩种不同的部分,一种被称为实例部分属,另一种被称为静态部分。
假如你之前使用过其他面向对象编程语言如c++,c#等,那么你肯定知道static关键字。如果你不清楚,也没有关系,你熟悉JS即可。
你可以这样来理解,类的实例部分就是当类被实例化的时候才会被初始化的属性,而类的静态部分存在于类本身上面而不是类的实例上

class Student {
    name: string
    age: number
    
    static id: string = "12138";

    constructor(n: string, a: number) {
        this.name = n;
        this.age = a;
    }
    speak() {
        console.log(`I am ${this.name} , ${this.age} years old.`)
    }
}

console.log(Student.id);

我们看一下上面代码,其中id就是静态部分,我们不需要实例化Student即new Student(...)就可以访问。

好了,回归到接口上面来,我们上面定义的接口是作用于实例部分的,name age speak()都是Student实例部分。那么如何定义静态部分的。
在此之前,我们需要知道构造函数constructor是属于静态部分的,我们来看如下代码。


interface PersonConstructor { //定义一个构造器接口
    new (name: string, age: number)
}

interface PersonAction { //一个包括speak方法的普通接口
    speak()
}

//定义一个工厂函数,用于生成一个对象
//ctor类必须实现PersonAction接口
function createPerson(ctor: PersonConstructor, name: string, age: number) : PersonAction {
    return new ctor(name, age);
}

//实现接口的 学生类
class Student implements PersonAction {
    name: string
    age: number

    static type: string = "student";

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    speak () {
        console.log(`I am a student.`)
    }
}

//实现接口的老师类
class Teacher implements PersonAction {
    name: string
    age: number

    static type: string = "teacher";

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    speak () {
        console.log(`I am a teacher.`)
    }
}


const s1 = createPerson(Student, "小明", 15);
const t1 = createPerson(Teacher, "小王", 25);
s1.speak();
t1.speak();


我们定义了一个构造器接口用来限定传入的类的构造器的形状,并且用它生成一个实例。

接口的继承
接口和类一样,都是可以继承的,我们使用extends关键字来实现这一点。

interface Color {
    color: string
}
interface Size {
    size: number
}

interface Rectangle extends Color, Size {

}

const s = {} as Rectangle;
s.color = "red";
s.size = 20;

Rectangle 接口继承了Color, Size接口,那么一个以Rectangle 为形状的对象 是可以有color,size属性的。

混合类型
这个其实非常简单,就是一个接口里面含有多种类型的属性。

interface Person {
    name: string,

    speak(): void,

    eat(food: string): void,
}

这就是一个混合类型的接口。

接口继承类
什么叫接口继承类?简单的说就是一个接口它继承了一个类,这个接口就会拥有这个的类的实例部分的成员,但是不包括其实现。

class Person {
    name: string
    age: number

    static type: string = "student";

    constructor () {}

    speak() {}
}

interface S extends Person {

}

const s = {} as S;

在这里插入图片描述
为了验证是否继承了其实现,看如下代码

class Person {
    name: string
    age: number

    static type: string = "student";

    constructor () {}

    speak() { console.log(666) }
}

interface S extends Person {

}

const s = {} as S;

s.speak();

然后编译,运行 发现
在这里插入图片描述
ts的类

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值