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

相关推荐
蜡台3 分钟前
Uniapp 开发H5 页面跳转拦截
前端·javascript·uni-app
IT爱学堂8 分钟前
Three.js可视化企业实战WEBGL课,2023年全新WEB 3D THREEJS技术
前端·javascript·webgl
网安蟹佬霸23 分钟前
WebAssembly安全攻防实战:从WASM逆向到漏洞利用
前端·安全·自动化·区块链·智能合约·wasm
Su米苏41 分钟前
关于@vue-office/excel 渲染异常滚动失去内容
前端·vue.js·excel
灯澜忆梦43 分钟前
【基于GO的Web开发10】gin获取HTML-Form表单提交参数
前端·后端·golang·html·gin
撑伞的鱼99371 小时前
2026年前端AI编程工具评测:Figma 还原、组件复用、跨文件联动三项对比
前端·ai编程·figma·效率工具·ai编程工具
码视野1 小时前
基于 Vue3 + Element Plus 的【微短剧剧本智能创作与分镜生产协同系统】设计与实现(含PRD/三端源码/大屏)
前端·人工智能·vue3
zzzzzz3102 小时前
36K stars 的“酷炫组件”,到底该怎么用才不显得用力过猛?
前端·react.js·动效
2401_894915535 小时前
GEO 优化源码全解析:从搜索引擎到 AI 引擎的底层改写逻辑
java·服务器·前端·数据库·人工智能·分布式·搜索引擎
Profile排查笔记10 小时前
指纹浏览器哪个好?从 Profile、代理、权限和自动化能力判断是否适合
前端·人工智能·后端·自动化