【TypeScript】TypeScript 联合类型、接口、类

发布于:2025-02-10 ⋅ 阅读:(127) ⋅ 点赞:(0)

目录

联合类型(Union Types)

联合类型数组

接口

定义接口

实现接口

接口中的索引签名

联合类型和接口

接口和数组

接口继承

单接口继承

多接口继承

TypeScript 类

创建实例化对象

类的继承

关键字extends

实例化子类对象

继承类的方法重写

使用super关键字

static 静态成员

instanceof 运算符

访问控制修饰符

类和接口


联合类型(Union Types)

联合类型允许一个变量可以是几种类型之一。使用管道符(|)分隔每个类型,赋值时可以根据设置的类型来赋值。

注意:只能赋值指定的类型,如果赋值其它类型就会报错。

创建联合类型的语言格式如下

Type1|Type2|Type3 
let value: string | number;

value = "Hello, World!"; // 正确,类型为 string
value = 123;             // 正确,类型为 number
// value = true;          // 错误,类型不是 string 或 number

联合类型数组

        虽然联合类型主要用于单个变量,但也可以用于数组元素,表示数组中的元素可以是多种类型之一。

示例

let mixedArray: (string | number)[];

mixedArray = ["Hello", 123, "TypeScript"]; // 正确
// mixedArray = [true, false];             // 错误,类型不是 string 或 number

接口

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

定义接口

interface Person {
    name: string;
    age: number;
    greet(): void;
}

实现接口

 一个类可以通过implements关键字来实现一个接口,从而确保该类具备接口中定义的所有属性和方法。

class Employee implements Person {
    name: string;
    age: number;
    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
    greet() {
      console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
    }
}

let emp = new Employee("John Doe", 30);
emp.greet(); 
// 输出: Hello, my name is John Doe and I am 30 years old.

接口中的索引签名

索引签名允许你在接口中定义一个对象的属性键和值的类型。索引签名可以是数字或字符串,用于描述对象中可能存在的任意键和值

interface StringIndexedObject {
    [key: string]: any;
}

let obj: StringIndexedObject = {a: 1, b: 'hello', c: true};

联合类型和接口

联合类型和接口可以一起使用,以提供更强大的类型检查功能。例如,你可以创建一个接口,其属性可以是联合类型

interface User {
    id: number;
    name: string;
    data: string | number | boolean;
}

let user: User = {
    id: 1,
    name: 'John Doe',
    data: 'Some string data'
};

user.data = 123; // 正确,类型为 number
user.data = true; // 正确,类型为 boolean

接口和数组

接口中我们可以将数组的索引值和元素设置为不同类型,索引值可以是数字或字符串

interface NumberArray {
    [index: number]: number;
}

let numArray: NumberArray = [1, 2, 3, 4];

接口继承

接口继承就是说接口可以通过其他接口来扩展自己。

Typescript 允许接口继承多个接口。

继承使用关键字 extends。

单接口继承

interface Animal {
    name: string;
    eat(): void;
}

interface Dog extends Animal {
    bark(): void;
}

class DogImpl implements Dog {
    name: string;
    constructor(name: string) {
        this.name = name;
    }
    eat() {
        console.log(`${this.name} is eating.`);
    }
    bark() {
        console.log(`${this.name} is barking.`);
    }
}

多接口继承

(TypeScript不支持传统意义上的多继承,但可以通过组合多个接口来实现类似效果):

虽然TypeScript不支持类直接多继承,但你可以通过让类实现多个接口来达到类似的效果。

interface Flyable {
    fly(): void;
}

interface Swimmable {
    swim(): void;
}

interface SuperCreature extends Flyable, Swimmable { }

class Dragon implements SuperCreature {
    fly() {
        console.log('Dragon is flying.');
    }
    swim() {
        console.log('Dragon is swimming.');
    }
}

在这个例子中,SuperCreature接口通过继承FlyableSwimmable接口,定义了一个同时具备飞行和游泳能力的超级生物。然后,Dragon类实现了这个超级接口。

TypeScript 类

TypeScript 是面向对象的 JavaScript。

类描述了所创建的对象共同的属性和方法。

TypeScript 支持面向对象的所有特性,比如 类、接口等。

TypeScript 类定义方式如下:

class className { 
    // 类的属性和方法定义在这里
    constructor(parameters) {
        // 构造函数,用于初始化对象
    }
    
    // 类的方法
    methodName() {
        // 方法实现
    }
}

定义类的关键字为 class,后面紧跟类名,类可以包含以下几个模块(类的数据成员):

  • 字段 − 字段是类里面声明的变量。字段表示对象的有关数据。

  • 构造函数 − 类实例化时调用,可以为类的对象分配内存。

  • 方法 − 方法为对象要执行的操作。

创建实例化对象

我们使用 new 关键字来实例化类的对象,语法格式如下:

var object_name = new class_name([ arguments ])

类实例化时会调用构造函数,例如:

var obj = new Car("Engine 1")

类中的字段属性和方法可以使用 . 号来访问:

// 访问属性
obj.field_name 

// 访问方法
obj.function_name()

类的继承

TypeScript 支持继承类,即我们可以在创建类的时候继承一个已存在的类,这个已存在的类称为父类,继承它的类称为子类。

关键字extends

类继承使用关键字 extends,子类除了不能继承父类的私有成员(方法和属性)和构造函数,其他的都可以继承。

class ElectricCar extends Car {
    battery: number;

    constructor(engine: string, battery: number) {
        super(engine); // 调用父类的构造函数
        this.battery = battery;
    }

    chargeBattery(): void {
        console.log(`Battery ${this.battery} kWh is charging.`);
    }
}

TypeScript 一次只能继承一个类,不支持继承多个类,但 TypeScript 支持多重继承(A 继承 B,B 继承 C)。

语法格式如下:

class child_class_name extends parent_class_name

实例化子类对象

var myElectricCar = new ElectricCar("Electric V8", 100);
myElectricCar.startEngine(); // 输出: Engine Electric V8 started.
myElectricCar.chargeBattery(); // 输出: Battery 100 kWh is charging.

继承类的方法重写

类继承后,子类可以对父类的方法重新定义,这个过程称之为方法的重写

其中 super 关键字是对父类的直接引用,该关键字可以引用父类的属性和方法

class SportsCar extends Car {
    topSpeed: number;

    constructor(engine: string, topSpeed: number) {
        super(engine);
        this.topSpeed = topSpeed;
    }

    // 重写父类的方法
    startEngine(): void {
        console.log(`Revving up engine ${this.engine} to top speed 
${this.topSpeed} mph!`);
    }
}

实例化并重写方法

var mySportsCar = new SportsCar("Turbo V6", 200);
mySportsCar.startEngine(); 
// 输出: Revving up engine Turbo V6 to top speed 200 mph!

使用super关键字

super关键字用于调用父类的构造函数和方法

class LuxuryCar extends Car {
    interior: string;

    constructor(engine: string, interior: string) {
        super(engine); // 调用父类的构造函数
        this.interior = interior;
    }

    describeCar(): void {
        super.startEngine(); // 调用父类的方法
        console.log(`This luxury car has a ${this.interior} interior.`);
    }
}

实例化并调用

var myLuxuryCar = new LuxuryCar("V12", "leather");
myLuxuryCar.describeCar();
// 输出:
// Engine V12 started.
// This luxury car has a leather interior.

static 静态成员

static 关键字用于定义类的数据成员(属性和方法)为静态的,静态成员可以直接通过类名调用

class CarFactory {
    static buildCar(engine: string): Car {
        return new Car(engine);
    }
}

调用静态成员

var anotherCar = CarFactory.buildCar("Inline 6");
anotherCar.startEngine(); 
// 输出: Engine Inline 6 started.

instanceof 运算符

instanceof 运算符用于判断对象是否是指定的类型,如果是返回 true,否则返回 false

console.log(myCar instanceof Car); // true
console.log(myElectricCar instanceof ElectricCar); // true
console.log(myElectricCar instanceof Car); 
// true,因为 ElectricCar 继承自 Car

访问控制修饰符

TypeScript 中,可以使用访问控制符来保护对类、变量、方法和构造方法的访问。TypeScript 支持 3 种不同的访问权限。

  • public(默认) : 公有,可以在任何地方被访问。

  • protected : 受保护,可以被其自身以及其子类访问。

  • private : 私有,只能被其定义所在的类访问。

class Person {
    public name: string;
    private age: number; // 私有成员,不能在类外部访问
    protected health: number; // 受保护成员,只能在类及其子类中访问

    constructor(name: string, age: number, health: number) {
        this.name = name;
        this.age = age;
        this.health = health;
    }
}

var person = new Person("Alice", 30, 100);
console.log(person.name); // Alice
// console.log(person.age); // 错误:age 是私有的

类和接口

类可以实现接口,使用关键字 implements,并将 interest 字段作为类的属性使用

interface Drivable {
    drive(): void;
}

class Motorcycle implements Drivable {
    drive(): void {
        console.log("Driving the motorcycle!");
    }
}

实例化并调用接口方法

var myMotorcycle = new Motorcycle();
myMotorcycle.drive(); // 输出: Driving the motorcycle!

完整示例

interface Drivable {
    drive(): void;
}

class Car implements Drivable {
    engine: string;

    constructor(engine: string) {
        this.engine = engine;
    }

    drive(): void {
        console.log(`Driving the car with ${this.engine} engine.`);
    }
}

class ElectricCar extends Car {
    battery: number;

    constructor(engine: string, battery: number) {
        super(engine);
        this.battery = battery;
    }

    charge(): void {
        console.log(`Charging the battery with ${this.battery} kWh.`);
    }
}

var myCar = new Car("V8");
myCar.drive(); // 输出: Driving the car with V8 engine.

var myElectricCar = new ElectricCar("Electric V8", 100);
myElectricCar.drive(); // 输出: Driving the car with Electric V8 engine.
myElectricCar.charge(); // 输出: Charging the battery with 100 kWh.

码字不易,各位大佬点点赞呗


网站公告

今日签到

点亮在社区的每一天
去签到