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

相关推荐
心在飞扬31 分钟前
ReRank重排序提升RAG系统效果
前端·后端
心在飞扬36 分钟前
RAPTOR 递归文档树优化策略
前端·后端
前端Hardy1 小时前
别再无脑用 `JSON.parse()` 了!这个安全漏洞你可能每天都在触发
前端·javascript·vue.js
前端Hardy1 小时前
别再让 `console.log` 上线了!它正在悄悄拖垮你的生产系统
前端·javascript·vue.js
青青家的小灰灰1 小时前
从入门到精通:Vue3 ref vs reactive 最佳实践与底层原理
前端·vue.js·面试
OpenTiny社区1 小时前
我的新同事是个AI:支持skill后,它用TinyVue搭项目还挺溜!
前端·vue.js·ai编程
心在飞扬1 小时前
MultiVector 多向量检索
前端·后端
用户39051332192881 小时前
async 函数返回的 Promise 状态何时变为 resolved
前端
李剑一2 小时前
大屏天气展示太普通?视觉升级!用 Canvas 做动态天气遮罩,雷阵雨效果直接封神
前端·vue.js·canvas
Lee川2 小时前
现代Web开发中的CSS继承、Flexbox布局与LocalStorage交互:从文档解析到实践应用
前端·css