关于 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 关键字,但它不会在运行时创建类继承关系,而是在编译时进行类型检查。

相关推荐
LuciferHuang1 小时前
震惊!三万star开源项目竟有致命Bug?
前端·javascript·debug
GISer_Jing1 小时前
前端实习总结——案例与大纲
前端·javascript
天天进步20151 小时前
前端工程化:Webpack从入门到精通
前端·webpack·node.js
姑苏洛言2 小时前
编写产品需求文档:黄历日历小程序
前端·javascript·后端
知识分享小能手3 小时前
Vue3 学习教程,从入门到精通,使用 VSCode 开发 Vue3 的详细指南(3)
前端·javascript·vue.js·学习·前端框架·vue·vue3
姑苏洛言3 小时前
搭建一款结合传统黄历功能的日历小程序
前端·javascript·后端
你的人类朋友4 小时前
🤔什么时候用BFF架构?
前端·javascript·后端
知识分享小能手4 小时前
Bootstrap 5学习教程,从入门到精通,Bootstrap 5 表单验证语法知识点及案例代码(34)
前端·javascript·学习·typescript·bootstrap·html·css3
一只小灿灿5 小时前
前端计算机视觉:使用 OpenCV.js 在浏览器中实现图像处理
前端·opencv·计算机视觉