政安晨【TypeScript高级用法】(二):泛型与命名空间

TypeScript的泛型允许我们在定义函数、类和接口时使用参数化类型,使得这些实体可以适应不同类型的数据。泛型可以增加代码的重用性和灵活性。

同时,TypeScript的命名空间提供了一种在全局命名空间中组织代码的方式,可以避免全局变量污染和命名冲突。命名空间使用namespace关键字定义,可以包含变量、函数、类和接口等。

通过使用泛型和命名空间,我们可以更好地组织和重用代码,提高了TypeScript的可扩展性和可维护性。

政安晨的个人主页政安晨

欢迎 👍点赞✍评论⭐收藏

收录专栏: AI虚拟世界大讲堂

希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正!


TypeScript 泛型

泛型(Generics)是一种编程语言特性,允许在定义函数、类、接口等时使用占位符来表示类型,而不是具体的类型。

泛型是一种在编写可重用、灵活且类型安全的代码时非常有用的功能。

使用泛型的主要目的是为了处理不特定类型的数据,使得代码可以适用于多种数据类型而不失去类型检查。

泛型的优势包括:

  • 代码重用: 可以编写与特定类型无关的通用代码,提高代码的复用性。

  • 类型安全: 在编译时进行类型检查,避免在运行时出现类型错误。

  • 抽象性: 允许编写更抽象和通用的代码,适应不同的数据类型和数据结构。

泛型标识符

在泛型中,通常使用一些约定俗成的标识符,比如常见的 T(表示 Type)、UV 等,但实际上你可以使用任何标识符。

T: 代表 "Type",是最常见的泛型类型参数名

function identity<T>(arg: T): T 
{
    return arg;
}

K, V: 用于表示键(Key)和值(Value)的泛型类型参数。

interface KeyValuePair<K, V> 
{
    key: K;
    value: V;
}

E: 用于表示数组元素的泛型类型参数。

function printArray<E>(arr: E[]): void 
{
    arr.forEach(item => console.log(item));
}

R: 用于表示函数返回值的泛型类型参数。

function getResult<R>(value: R): R 
{
    return value;
}

U, V: 通常用于表示第二、第三个泛型类型参数。

function combine<U, V>(first: U, second: V): string 
{
    return `${first} ${second}`;
}

这些标识符是约定俗成的,实际上你可以选择任何符合标识符规范的名称。关键是使得代码易读和易于理解,所以建议在泛型类型参数上使用描述性的名称,以便于理解其用途。

泛型函数(Generic Functions)

使用泛型来创建一个可以处理不同类型的函数:

function identity<T>(arg: T): T 
{
    return arg;
}

// 使用泛型函数
let result = identity<string>("Hello");
console.log(result); // 输出: Hello

let numberResult = identity<number>(42);
console.log(numberResult); // 输出: 42

解析: 以上例子中,identity 是一个泛型函数,使用 <T> 表示泛型类型。它接受一个参数 arg 和返回值都是泛型类型 T。在使用时,可以通过尖括号 <> 明确指定泛型类型。第一个调用指定了 string 类型,第二个调用指定了 number 类型。

泛型接口(Generic Interfaces)

可以使用泛型来定义接口,使接口的成员能够使用任意类型:

// 基本语法
interface Pair<T, U> 
{
    first: T;
    second: U;
}

// 使用泛型接口
let pair: Pair<string, number> = { first: "hello", second: 42 };
console.log(pair); // 输出: { first: 'hello', second: 42 }

解析: 这里定义了一个泛型接口 Pair,它有两个类型参数 T 和 U。然后,使用这个泛型接口创建了一个对象 pair,其中 first 是字符串类型,second 是数字类型。

泛型类(Generic Classes)

泛型也可以应用于类的实例变量和方法:

// 基本语法
class Box<T> 
{
    private value: T;

    constructor(value: T) 
    {
        this.value = value;
    }

    getValue(): T 
    {
        return this.value;
    }
}

// 使用泛型类
let stringBox = new Box<string>("TypeScript");
console.log(stringBox.getValue()); // 输出: TypeScript

泛型约束(Generic Constraints)

有时候你想限制泛型的类型范围,可以使用泛型约束:

// 基本语法
interface Lengthwise 
{
    length: number;
}

function logLength<T extends Lengthwise>(arg: T): void 
{
    console.log(arg.length);
}

// 正确的使用
logLength("hello"); // 输出: 5

// 错误的使用,因为数字没有 length 属性
logLength(42); // 错误

解析: 在这个例子中,定义了一个泛型函数 logLength,它接受一个类型为 T 的参数,但有一个约束条件,即 T 必须实现 Lengthwise 接口,该接口要求有 length 属性。因此,可以正确调用 logLength("hello"),但不能调用 logLength(42),因为数字没有 length 属性。

泛型与默认值

可以给泛型设置默认值,使得在不指定类型参数时能够使用默认类型:

// 基本语法
function defaultValue<T = string>(arg: T): T 
{
    return arg;
}

// 使用带默认值的泛型函数
let result1 = defaultValue("hello"); // 推断为 string 类型
let result2 = defaultValue(42);      // 推断为 number 类型

说明: 这个例子展示了带有默认值的泛型函数。函数 defaultValue 接受一个泛型参数 T,并给它设置了默认类型为 string。在使用时,如果没有显式指定类型,会使用默认类型。在例子中,第一个调用中 result1 推断为 string 类型,第二个调用中 result2 推断为 number 类型。

TypeScript 命名空间

命名空间一个最明确的目的就是解决重名问题。

假设这样一种情况,当一个班上有两个名叫小明的学生时,为了明确区分它们,我们在使用名字之外,不得不使用一些额外的信息,比如他们的姓(王小明,李小明),或者他们父母的名字等等。

命名空间定义了标识符的可见范围,一个标识符可在多个命名空间中定义,它在不同命名空间中的含义是互不相干的。这样,在一个新的命名空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他命名空间中。

TypeScript 中命名空间使用 namespace 来定义,语法格式如下:

namespace SomeNameSpaceName 
{ 
   export interface ISomeInterfaceName {      }  
   export class SomeClassName {      }  
}

以上定义了一个命名空间 SomeNameSpaceName,如果我们需要在外部可以调用 SomeNameSpaceName 中的类和接口,则需要在类和接口添加 export 关键字。

要在另外一个命名空间调用语法格式为:

SomeNameSpaceName.SomeClassName;

如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:

/// <reference path = "SomeFileName.ts" />

以下实例演示了命名空间的使用,定义在不同文件中:

IShape.ts 文件代码:

namespace Drawing 
{ 
    export interface IShape 
    { 
        draw(); 
    }
}

Circle.ts 文件代码:

/// <reference path = "IShape.ts" /> 
namespace Drawing 
{ 
    export class Circle implements IShape 
    { 
        public draw() 
        { 
            console.log("Circle is drawn"); 
        }  
    }
}

Triangle.ts 文件代码:

/// <reference path = "IShape.ts" /> 
namespace Drawing 
{ 
    export class Triangle implements IShape 
    { 
        public draw() 
        { 
            console.log("Triangle is drawn"); 
        } 
    } 
}

TestShape.ts 文件代码:

/// <reference path = "IShape.ts" />   
/// <reference path = "Circle.ts" /> 
/// <reference path = "Triangle.ts" />  
function drawAllShapes(shape:Drawing.IShape) 
{ 
    shape.draw(); 
} 
drawAllShapes(new Drawing.Circle());
drawAllShapes(new Drawing.Triangle());

嵌套命名空间

命名空间支持嵌套,即你可以将命名空间定义在另外一个命名空间里头。

namespace namespace_name1 
{ 
    export namespace namespace_name2 
    {
        export class class_name {    } 
    } 
}

成员的访问使用点号 . 来实现,如下实例:

Invoice.ts 文件代码:

namespace Zachen 
{ 
    export namespace invoiceApp 
    { 
        export class Invoice 
        { 
            public calculateDiscount(price: number) 
            { 
                return price * .40; 
            } 
        } 
    } 
}

InvoiceTest.ts 文件代码:

/// <reference path = "Invoice.ts" />
var invoice = new Runoob.invoiceApp.Invoice(); 
console.log(invoice.calculateDiscount(500));

结论

通过泛型和命名空间,确实可以更好地组织和重用代码,提高了TypeScript的可扩展性和可维护性。以便在如Cocos这样的引擎中以更高效的方式开发项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/429439.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

项目打包时报错 There are test failures.

报错原因是 test测试类有问题 我们可直接选择跳过测试类打包 如下 此时再次打包就成功了

高级软件开发知识点

流程 算法题简历上项目用到技术、流程、遇到问题HR 准备 常考的题型和回答思路刷100算法题&#xff0c;理解其思想&#xff0c;不要死记最近一家公司所负责的业务和项目&#xff1a; 项目背景、演进之路&#xff0c;有哪个阶段&#xff0c;每个阶段主要做什么项目中技术选型…

vue2和vue3的区别介绍

Vue.js 是一个流行的前端JavaScript框架&#xff0c;用于构建用户界面和单页应用程序。自从Vue.js首次发布以来&#xff0c;它就因其简洁的API、灵活的架构和易于上手的特点而受到了广泛的欢迎。Vue.js的第二个主要版本&#xff08;Vue 2&#xff09;发布于2016年&#xff0c;而…

AutoGPT实现原理

AutoGPT是一种利用GPT-4模型的自动化任务处理系统&#xff0c;其主要特点包括任务分配、多模型协作、互联网访问和文件读写能力以及上下文联动记忆性。其核心思想是通过零样本学习&#xff08;Zero Shot Learning&#xff09;让GPT-4理解人类设定的角色和目标&#xff0c;并通过…

正则表达式在QT开发中的应用

一.正则表达式在QT开发中的使用&#xff1a; 1.模式匹配与验证&#xff1a;正则表达式最基本的作用就是进行模式匹配&#xff0c;它可以用来查找、识别或验证一个字符串是否符合某个特定的模式。例如&#xff0c;在表单验证中&#xff0c;可以使用正则表达式来检查用户输入的邮…

微擎安装,卡在“安装微擎”界面

进入install.php&#xff0c;点击【在线安装】 下一步配置数据库&#xff0c;开始安装系统 然后显示进度条&#xff0c;进度条一闪而过 然后就没有进度条显示了&#xff0c;一直卡在这里 第一次等了好久&#xff0c; 删除目录下的文件&#xff0c;重装还是这样 再重启服务器&…

C语言数组作为函数参数

有两种情形&#xff1b; 一种是数组元素作为函数实参&#xff1b;一种是数组名作为函数参数&#xff1b; 新建一个VC6单文档工程&#xff1b; void printshz(int , CDC* , int , int ); double getav(int a[5]); ...... void CShzcshView::OnDraw(CDC* pDC) {CShzcshDoc* pDo…

electron+vue3全家桶+vite项目搭建【29】封装窗口工具类【3】控制窗口定向移动

文章目录 引入实现效果思路声明通用的定位对象主进程模块渲染进程测试效果 引入 demo项目地址 窗口工具类系列文章&#xff1a; 封装窗口工具类【1】雏形 封装窗口工具类【2】窗口组&#xff0c;维护窗口关系 封装窗口工具类【3】控制窗口定向移动 很多时候&#xff0c;我们想…

python识别并控制操作已打开的浏览器进行自动化测试

前提&#xff1a;已安装python和selenium 一、将浏览器以debugger模式打开 打开方法&#xff1a; 1.右击浏览器&#xff0c;选择属性&#xff1a; 2.在目标中加上 --remote-debugging-port9222 --user-data-dir"C:\selenum\AutomationProfile" 二、识别代码 from…

npm、cnpm、pnpm使用详细

简介&#xff1a; npm&#xff1a;npm&#xff08;Node Package Manager&#xff09;是Node.js的包管理工具&#xff0c;用于安装、更新、卸载Node.js的模块和包。它提供了一个命令行界面&#xff0c;使得开发者可以轻松地管理项目依赖。npm 是 nodejs 中的一部分&#xff0c;…

[linux] 使用 kprobe 观察 tcp 拥塞窗口的变化

tcp 中拥塞窗口用来做拥塞控制。 在发送侧&#xff0c;要发送数据的时候会基于拥塞窗口进行判断&#xff0c;当前这个包还能不能发送出去。 tcp 发包函数是 tcp_write_xmit()&#xff0c;在这个函数中调用 tcp_cwnd_test() 来判断当前拥塞窗口让不让发包。从 tcp_cwnd_test() 函…

【推荐算法系列十八】:DSSM 召回算法

参考 推荐系统中 DSSM 双塔模型汇总&#xff08;二更&#xff09; DSSM 和 YouTubeDNN 都是比较经典的 U2I 模型。 U2I 召回 U2I 召回也就是 User-to-Item 召回&#xff0c;它基于用户的历史行为以及用户的一些个人信息&#xff0c;对系统中的候选物品进行筛选&#xff0c;挑…

C++ Primer Plus Sixth Edition - 下载电子书与源代码

C Primer Plus Sixth Edition - 下载电子书与源代码 1. C Primer Plus, 6th Edition1.1. Download the source code files1.2. 下载源代码文件 2. C Primer Plus, Sixth Edition (PDF)3. Table of ContentsReferences 1. C Primer Plus, 6th Edition C Primer Plus, 6th Editi…

Spring事件监听机制

前言 Spring 的事件监听机制&#xff0c;采用了观察者的设计模式。一套完整的事件监听流程是这样的&#xff0c;首先定义事件类&#xff0c;即ApplicationEvent的子类&#xff0c;它包含事件发生的时间戳timestamp和产生事件的来源source&#xff0c;以及自定义的其它事件属性…

IDEA运行大项目启动卡顿问题

我打开了很多项目&#xff0c;然后又启动了一个大型项目时&#xff0c;启动到一半&#xff0c;弹出一个窗口&#xff0c;告诉我idea内存不够&#xff0c;怎么解决这个问题&#xff1f; 1、先把多余的项目关掉&#xff0c;再启动这个大项目&#xff0c; 2、如果还是不行就去修改…

OpenDDS之QosXml库编译(Windows + VS2019)

目录 1、需求背景2、基础环境3、编译xercesc3.1、下载xercesc3.2、编译xercesc 4、编译ACE_XML_Utils4.1、生成XML_Utils解决方案4.2、编译XML_Utils 5、编译QOS_XML_XSC_Handlerd5.1、生成QOS_XML_XSC_Handlerd解决方案5.2、编译QOS_XML_XSC_Handlerd 6、测试例子6.1、生成dum…

vue3 ts setup 组合式API 使用教程

vue3中新增了组合式API&#xff0c;本文讲解组合式API setup 的使用 关于setup 的出现和 vue3 js setup 的使用&#xff0c;笔者已经在2022年的文章中说明&#xff0c;这里不再赘述&#xff0c;需要的朋友可以阅读&#xff1a;《vue3 setup 使用教程》 官网文档&#xff1a;h…

[C语言]——C语言数据类型和变量

目录 一.数据类型介绍 1.字符型 2.整型 3.浮点型 4.布尔类型 5.各种数据类型的长度 5.1sizeof操作符 5.2数据类型长度 5.3sizeof中表达式不计算 二.signed 和 unsigned 三.数据类型的取值范围 四.变量 1.变量的创建 2.变量的分类 一.数据类型介绍 C语⾔提供了丰富…

排序——堆排序

本节继续复习排序算法。这次复习排序算法中的堆排序。 堆排序属于选择排序。 目录 什么是堆&#xff1f; 堆排序 堆排序的思想 堆排代码 向下调整算法 堆排整体 什么是堆&#xff1f; 在复习堆排序之前&#xff0c; 首先我们需要回顾一下什么是堆 。 堆的本质其实是一个数…

VScode---php环境搭建

文章目录 1.下载php Dehug;php server2.下载php环境3.配置环境变量5.配置php.ini文件6.设置vscode6.测试遇到的问题 1.下载php Dehug;php server 2.下载php环境 下载地址&#xff1a;https://www.php.net/downloads.php 3.配置环境变量 C:\Users\hacker>php -v PHP 8.3.3 (…