带你读《现代TypeScript高级教程》十二、类型兼容:结构化类型(1)

简介: 带你读《现代TypeScript高级教程》十二、类型兼容:结构化类型(1)

十二、类型兼容:结构化类型

TypeScript 是一种基于 JavaScript 的静态类型语言,它为 JavaScript 添加了类型系统,并提供了强大的类型检查和自动补全功能。

 

TypeScript 的类型系统有一个非常重要的特性,那就是 "鸭子类型"(Duck Typing)或 "结构化类型"(Structural Typing)(文章会以"鸭子类型"(Duck Typing)作为简称)。这种特性有时会让人感到惊讶,但它是 TypeScript 增强 JavaScript 开发体验的重要方式之一。

 

鸭子类型的概念来自一个古老的英语成语:“如果它走起路来像一只鸭子,叫起来也像一只鸭子,那么它就是一只鸭子。”在 TypeScript(或更一般地说,静态类型语言)的上下文中,鸭子类型意味着一个对象的类型不是由它继承或实现的具体类别决定的,而是由它具有的结构决定的。

 

本文将全面深入地探讨 TypeScript 中的鸭子类型,以及如何在实际的开发中应用和利用鸭子类型。

1. 鸭子类型:定义和示例

鸭子类型的概念来自一个古老的英语成语:“如果它走起路来像一只鸭子,叫起来也像一只鸭子,那么它就是一只鸭子。”在 TypeScript(或更一般地说,静态类型语言)的上下文中,鸭子类型意味着一个对象的类型不是由它继承或实现的具体类别决定的,而是由它具有的结构决定的。

 

这是一个简单的鸭子类型示例:

 

interface Duck {
    walk: () => void;
    quack: () => void;}
function doDuckThings(duck: Duck) {
    duck.walk();
    duck.quack();}
const myDuck = {
    walk: () => console.log('Walking like a duck'),
    quack: () => console.log('Quacking like a duck'),
    swim: () => console.log('Swimming like a duck')};
doDuckThings(myDuck); // OK

 

在这个例子中,我们定义了一个 Duck 接口和一个 doDuckThings 函数,这个函数需要一个 Duck 类型的参数。然后我们创建了一个 myDuck 对象,它有 walkquack swim 这三个方法。尽管 myDuck 并没有显式地声明它实现了 Duck 接口,但是由于 myDuck 的结构满足了 Duck 接口的要求(即 myDuck walk quack 这两个方法),我们可以将 myDuck 作为参数传递给 doDuckThings 函数。

 

这就是鸭子类型的基本概念:只要一个对象的结构满足了接口的要求,我们就可以把这个对象看作是这个接口的实例,而不管这个对象的实际类型是什么。

2. 鸭子类型的优点

鸭子类型有许多优点,特别是在编写更灵活和更通用的代码方面。

1 代码的灵活性

鸭子类型增加了代码的灵活性。我们可以创建和使用满足特定接口的任何对象,而不必担心它们的具体类型。这使得我们可以更容易地编写通用的代码,因为我们的代码只依赖于对象的结构,而不是对象的具体类型。

2 代码的复用

鸭子类型有助于代码的复用。由于我们的函数和方法只依赖于对象的结构,我们可以在不同的上下文中重用这些函数和方法,只要传入的对象满足所需的结构。

例如,我们可以写一个函数,它接受一个具有 toString 方法的任何对象,然后返回这个对象的字符串表示。由于几乎所有的 JavaScript 对象都有 toString 方法,我们可以在许多不同的上下文中重用这个函数。

function toString(obj: { toString: () => string }) {
    return obj.toString();}
console.log(toString(123)); // "123"console.log(toString([1, 2, 3])); // "1,2,3"console.log(toString({ a: 1, b: 2 })); // "[object Object]"

3 与 JavaScript 的互操作性

鸭子类型提高了 TypeScript 与 JavaScript 的互操作性。由于 JavaScript 是一种动态类型语言,我们经常需要处理的对象可能没有明确的类型。鸭子类型使我们能够在 TypeScript 中安全地处理这些对象,只要它们的结构满足我们的需求。

 

例如,我们可能从一个 JavaScript 库获取一个对象,这个对象有一个 forEach 方法。我们不关心这个对象的具体类型,我们只关心它是否有 forEach 方法。使用鸭子类型,我们可以定义一个接口来描述这个对象的结构,然后在 TypeScript 中安全地使用这个对象。

 

interface Iterable {
    forEach: (callback: (item: any) => void) => void;}
function processItems(iterable: Iterable) {
    iterable.forEach(item => console.log(item));}
const jsArray = [1, 2, 3]; // From a JavaScript libraryprocessItems(jsArray); // OK

 

带你读《现代TypeScript高级教程》十二、类型兼容:结构化类型(2)https://developer.aliyun.com/article/1348480?groupCode=tech_library

相关文章
|
1天前
|
JavaScript 开发者
在 Babel 插件中使用 TypeScript 类型
【10月更文挑战第23天】可以在 Babel 插件中更有效地使用 TypeScript 类型,提高插件的开发效率和质量,减少潜在的类型错误。同时,也有助于提升代码的可理解性和可维护性,使插件的功能更易于扩展和升级。
|
13天前
|
JavaScript 前端开发
TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第11天】TypeScript【类型别名、泛型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
14天前
|
JavaScript 前端开发 Java
TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第10天】TypeScript【接口】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
16天前
|
JavaScript 前端开发 安全
TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
【10月更文挑战第9天】TypeScript【基础类型】超简洁教程!再也不用看臭又长的TypeScript文档了!
|
1天前
|
JavaScript 前端开发 安全
TypeScript进阶:类型系统与高级类型的应用
【10月更文挑战第25天】TypeScript作为JavaScript的超集,其类型系统是其核心特性之一。本文通过代码示例介绍了TypeScript的基本数据类型、联合类型、交叉类型、泛型和条件类型等高级类型的应用。这些特性不仅提高了代码的可读性和可维护性,还帮助开发者构建更健壮的应用程序。
5 0
|
18天前
|
JavaScript 索引
TypeScript(TS)安装指南与基础教程学习全攻略(二)
TypeScript(TS)安装指南与基础教程学习全攻略(二)
46 0
|
2月前
|
JavaScript
typeScript进阶(9)_type类型别名
本文介绍了TypeScript中类型别名的概念和用法。类型别名使用`type`关键字定义,可以为现有类型起一个新的名字,使代码更加清晰易懂。文章通过具体示例展示了如何定义类型别名以及如何在函数中使用类型别名。
36 1
typeScript进阶(9)_type类型别名
|
18天前
|
JavaScript 前端开发 安全
深入理解TypeScript:增强JavaScript的类型安全性
【10月更文挑战第8天】深入理解TypeScript:增强JavaScript的类型安全性
32 0
|
18天前
|
JavaScript 前端开发 开发者
深入理解TypeScript:类型系统与实用技巧
【10月更文挑战第8天】深入理解TypeScript:类型系统与实用技巧
|
2月前
|
JavaScript
typeScript基础(5)_对象的类型-interfaces接口
本文介绍了TypeScript中接口(interfaces)的基本概念和用法,包括如何定义接口、接口的简单使用、自定义属性、以及如何使用`readonly`关键字定义只读属性。接口在TypeScript中是定义对象形状的重要方式,可以规定对象的必有属性、可选属性、自定义属性和只读属性。
38 1