关于 typescript 中 extends 的理解

typescript extends 关键字的基本用法

1. 泛型约束

在泛型中,extends 用于约束类型参数必须是某个类型或其子类型。这是 TypeScript 中一种使用 extends 的常见方式。

例子:泛型中的 extends

scala 复制代码
type MyType<T extends number> = { value: T };

let numType: MyType<number> = { value: 42 };  // 正确
// let strType: MyType<string> = { value: "hello" };  // 错误,因为 string 不符合 extends number 约束

例子:条件类型中的 extends

typescript 复制代码
type MyConditionalType<T> = T extends string ? number : boolean;
let result1: MyConditionalType<string> = 42; // number
let result2: MyConditionalType<boolean> = true; // boolean

2. 接口继承

在接口中,extends 用于声明一个接口继承另一个接口。这样,新的接口将包含父接口的成员,并可以添加额外的成员。

typescript 复制代码
interface Animal {
  name: string;
  makeSound(): void;
}

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

const myDog: Dog = {
  name: 'Buddy',
  makeSound() {
    console.log(this.name + ' makes a sound');
  },
  bark() {
    console.log(this.name + ' barks');
  }
};

在这个例子中,Dog 接口通过 extends 继承了 Animal 接口的属性和方法。

需要注意的是,在 TypeScript 中的 extends 主要用于类型系统中的约束和声明继承关系,并不会在运行时创建真正的类继承关系。 TypeScript 的继承更多地关注于类型的静态检查,而不是在运行时创建对象之间的实际继承链。

extends 用于约束类型参数必须是某个类型或其子类型

这句话是什么意思呢?我来解释一下:

当在 TypeScript 中使用 extends 关键字作为类型参数的约束时,意味着该类型必须是指定类型或该类型的子类型。让我们通过一个例子来说明:

typescript 复制代码
// 定义一个基础类型
interface Animal {
    name: string;
}

// 通过扩展基础类型创建一个子类型
interface Dog extends Animal {
    breed: string;
}

// 泛型类型,约束类型参数必须是 Animal 或其子类型
type MyType<T extends Animal> = {
    animalData: T;
    sound(): void;
};

// 使用一个子类型
const dogData: Dog = { name: 'Buddy', breed: 'Labrador' };

// 使用具有子类型的泛型类型
const myDogType: MyType<Dog> = {
    animalData: dogData,
    sound() {
        console.log(`${dogData.name} 会叫`);
    }
};

myDogType.sound(); // 输出 "Buddy 会叫"

在这个例子中:

  • Animal 是一个基础类型。
  • DogAnimal 的子类型,因为它扩展了 Animal
  • MyType 是一个泛型类型,它接受类型参数 T,该参数必须是 Animal 或其子类型。

当我们使用 MyType<Dog> 时,我们在说 TDogDog 的子类型。这是有效的,因为 DogAnimal 的子类型,满足了约束条件。

因此,在这个例子中,子类型是指任何扩展或继承指定基础类型(在这里是 Animal)的类型。

typescript 中的 extends 和 js 中class 的extends 有什么区别?

虽然 TypeScript 中的 extends 关键字与 JavaScript 中的 classextends 关键字在表面上看起来相似,但它们实际上有不同的用途和含义。

TypeScript 中的 extends

在 TypeScript 中,extends 用于类型系统中的泛型和条件类型。在泛型中,extends 用于约束一个类型参数必须是某个类型或其子类型。在条件类型中,extends 用于进行条件判断,根据某个条件选择不同的类型。

例子:泛型中的 extends

scala 复制代码
type MyType<T extends number> = { value: T };
let numType: MyType<number> = { value: 42 }; // 正确
// let strType: MyType<string> = { value: "hello" }; // 错误,因为 string 不符合 extends number 约束

例子:条件类型中的 extends

typescript 复制代码
type MyConditionalType<T> = T extends string ? number : boolean;
let result1: MyConditionalType<string> = 42; // number
let result2: MyConditionalType<boolean> = true; // boolean

JavaScript 中的 extends

在 JavaScript 中的 class 关键字的 extends 用于实现类的继承。子类继承父类的属性和方法,并且可以添加自己的属性和方法。

例子:JavaScript 中的类继承

javascript 复制代码
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + ' makes a sound');
  }
}

class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks');
  }
}

const myDog = new Dog('Buddy');
myDog.speak(); // 输出 "Buddy barks"

在这个例子中,Dog 类继承自 Animal 类,使用了 extends 关键字。

总结:

  • TypeScript 中的 extends 主要用于泛型约束和条件类型,是用于类型系统的。
  • JavaScript 中的 extends 用于类继承,是用于实现面向对象的类继承的。

虽然与 JavaScript 中的 classextends 有些相似之处,但在 TypeScript 中的 extends 不涉及实际的运行时继承

什么是运行时继承呢?

运行时继承指的是在程序实际运行时,一个对象能够继承另一个对象的属性和方法。这是面向对象编程中的一个概念,其中一个类(或构造函数)的实例能够继承另一个类的实例的特性。在传统的面向对象语言中,如Java、C++、Python等,继承是在运行时创建对象之间的实际关联和共享属性与方法。

具体来说,当一个类继承另一个类时,它获得了父类的属性和方法,并且可以通过运行时创建的对象来访问和调用这些继承的成员。这样的继承关系在程序执行时动态地影响着对象之间的关系。

在JavaScript中,classextends 关键字可以用于实现运行时继承。以下是一个简单的例子:

javascript 复制代码
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(this.name + ' makes a sound');
  }
}

class Dog extends Animal {
  bark() {
    console.log(this.name + ' barks');
  }
}

const myDog = new Dog('Buddy');
myDog.speak(); // 输出 "Buddy makes a sound"
myDog.bark();  // 输出 "Buddy barks"

在这个例子中,Dog 类继承了 Animal 类,创建 myDog 对象后,myDog 实例既有 Dog 类的 bark 方法,也有 Animal 类的 speak 方法。这是典型的运行时继承。

相比之下,TypeScript 中的 extends 关键字主要用于静态类型检查,不会在实际运行时创建对象之间的真正继承链。TypeScript 中的继承更关注于在编译阶段进行类型检查,以确保代码的类型安全性。所以,虽然 TypeScript 提供了 extends 关键字,但它不会在运行时创建类继承关系,而是在编译时进行类型检查。

相关推荐
四岁半儿2 小时前
常用css
前端·css
你的人类朋友3 小时前
说说git的变基
前端·git·后端
姑苏洛言3 小时前
网页作品惊艳亮相!这个浪浪山小妖怪网站太治愈了!
前端
字节逆旅3 小时前
nvm 安装pnpm的异常解决
前端·npm
Jerry3 小时前
Compose 从 View 系统迁移
前端
GIS之路4 小时前
2025年 两院院士 增选有效候选人名单公布
前端
四岁半儿4 小时前
vue,H5车牌弹框定制键盘包括新能源车牌
前端·vue.js
烛阴4 小时前
告别繁琐的类型注解:TypeScript 类型推断完全指南
前端·javascript·typescript
gnip4 小时前
工程项目中.env 文件原理
前端·javascript
JefferyXZF4 小时前
Next.js Server Actions 详解: 无缝衔接前后端的革命性技术(八)
前端·全栈·next.js