TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)

本文主要是介绍TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

泛型1

泛型2

声明合并

命名空间

 模块1

模块2

声明文件简介


泛型1

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性 

首先,我们来实现一个函数 createArray

function createArray(length: number, value: any): Array<any> {let result = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;
}
createArray(3, 'x'); // ['x', 'x', 'x']

这段代码编译不会报错,但是一个显而易见的缺陷是,它并没有准确的定义返回值的类型
Array<any> 允许数组的每一项都为任意类型。但是我们预期的是,数组中每一项都应该是输入的 value 的类型
这时候,泛型就派上用场了

function createArray<T>(length: number, value: T): Array<T> {let result: T[] = [];for (let i = 0; i < length; i++) {result[i] = value;}return result;
}
createArray<string>(3, 'x'); // ['x', 'x','x']

泛型2

 多个类型参数

function swap<T, U>(v1:T,v2:U) {console.log(v1,v2)
}
swap(10,20);

泛型约束

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法

function loggingLength<T>(arg: T){// Property 'length' does not exist on type 'T'console.log(arg.length);
}

这时,我们可以对泛型进行约束,只允许这个函数传入那些包含 length 属性的变量。这就是泛型约束

interface Length {length: number;
}
function loggingIdentity<T extends Length> (arg: T){console.log(arg.length);
}
loggingIdentity("Hello")

声明合并

如果定义了两个相同名字的函数、接口或类,那么它们会合并成一个类型 

函数的合并

我们可以使用重载定义多个函数类型

function reverse(x: number): number;
function reverse(x: string): string;
function reverse(x: number | string): number | string {if (typeof x === 'number') {return Number(x.toString().split('').reverse().join(''));} else if (typeof x === 'string') {return x.split('').reverse().join('');}
}

接口的合并

接口中的属性在合并时会简单的合并到一个接口中

interface Alarm {price: number;
}
interface Alarm {weight: number;
}

相当于:

interface Alarm {price: number;weight: number;
}

注意,合并的属性的类型必须是唯一的:

interface Alarm {price: number;
}
interface Alarm {price: number;  // 虽然重复了,但是类型都是 `number`,所以不会报错weight: number;
}

interface Alarm {price: number;
}
interface Alarm {price: string;  // 类型不一致,会报错weight: number;
}

命名空间

 在真实的应用场景中,当在一个文件中代码量过多,不容易阅读和维护的时候,我们可以通过命名空间的方式将一个文件分离为多个文件
我们来观察下面这个例子:

interface Animal{name:string
}
class Cat implements Animal{name: stringconstructor(name:string){this.name = name;}sayHi(){console.log(this.name)}
}
class Dog implements Animal{name: stringconstructor(name:string){this.name = name}sayHello(){console.log(this.name)}
}
const c = new Cat("猫")
c.sayHi()
const d = new Dog("狗")
d.sayHello()

当应用变得越来越大时,我们需要将代码分离到不同的文件中以便于维护

// Animal.ts
namespace AnimalInfo{export interface Animal{name:string}
}
// Cat.ts
namespace AnimalInfo{export class Cat implements Animal{name: stringconstructor(name:string){this.name = name;}sayHi(){console.log(this.name)}}
}
// Dog.ts
namespace AnimalInfo{export class Dog implements Animal{name: stringconstructor(name:string){this.name = name}sayHello(){console.log(this.name)}}
}
// index.ts
const c = new AnimalInfo.Cat("猫")
c.sayHi()
const d = new AnimalInfo.Dog("狗")
d.sayHello()

多文件编译

当涉及到多文件时,我们必须确保所有编译后的代码都被加载了。
我们有两种方式

方式一

把所有的输入文件编译为一个输出文件,需要使用 --outFile 标记

tsc --outFile demo.js .\Animal.ts .\Cat.ts .\Dog.ts .\index.ts

方式二

我们可以编译每一个文件(默认方式),那么每个源文件都会对应生成一个 JavaScript 文件。 然后,在页面上通过 <script> 标签把所有生成的 JavaScript 文件按正确的顺序引进来 

<script src="./Animal.js"></script>
<script src="./Cat.js"></script>
<script src="./Dog.js"></script>
<script src="./index.js"></script>

 模块1

从 ECMAScript 2015 开始,JavaScript 引入了模块的概念。TypeScript 也沿用这个概念
模块在其自身的作用域里执行,而不是在全局作用域里;这意味着定义在一个模块里的变量,函数,类等等在模块外部是不可见的,除非你明确地使用 export 形式之一导出它们。 相反,如果想使用其它模块导出的变量,函数,类,接口等的时候,你必须要导入它们,可以使用 import 形式之一 

interface Animal{ name:string
}
class Cat implements Animal{name: stringconstructor(name:string){this.name = name;}sayHi(){console.log(this.name)}
}
class Dog implements Animal{name: stringconstructor(name:string){this.name = name}sayHello(){console.log(this.name)}
}
const c = new Cat("猫")
c.sayHi()
const d = new Dog("狗")
d.sayHello()

 我们用模块化的形式实现

// Animal.ts
export interface Animal{name:string
}
// Cat.ts
import { Animal } from "./Animal"
export class Cat implements Animal{name: stringconstructor(name:string){this.name = name;}sayHi(){console.log(this.name)}
}
// Dog.ts
import { Animal } from "./Animal"
export class Dog implements Animal{name: stringconstructor(name:string){this.name = name}sayHello(){console.log(this.name)}
}
// index.ts
import { Cat } from "./Cat"
import { Dog } from "./Dog"
const c = new Cat("猫")
c.sayHi()
const d = new Dog("狗")
d.sayHello()

模块2

模块化的优势不言而喻,换句话说,如果一个语言无法支持模块化,那么他就无法做大型应用程序的开发
接下来我们在来了解一些模块的其他知识 

 别名

当导入的名字特别长,或者不容易写的时候,可以使用别名

import { Animal as AL } from "./Animal"
export class Cat implements AL{name: stringconstructor(name:string){this.name = name;}sayHi(){console.log(this.name)}
}

 默认导出

每个模块都可以有一个 default 导出。 默认导出使用 default 关键字标记;并且一个模块只能够有一个 default 导出

export default interface Animal{name:string
}
import Animal from "./Animal"
export class Cat implements Animal{name: stringconstructor(name:string){this.name = name;}sayHi(){console.log(this.name)}
}

导入整个模块

当导出的对象特别多,需要导入的也很多,这个时候,可以使用导入整个模块的方式 

export interface Animal{name:string
}
export interface AnimalInfo{age:number
}

import * as AN from "./Animal"
export class Cat implements AN.Animal,AN.AnimalInfo{name: stringage:numberconstructor(name:string,age:number){this.name = name;this.age = age}sayHi(){console.log(this.name,this.age)}
}

声明文件简介

 typescript中以 .d.ts 为后缀的文件被称为声明文件当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能

声明文件分为三种类型
1、typescript内置声明文件
2、第三方声明文件
3、自定义声明文件

什么是声明语句 

假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过 <script> 标签引入 jQuery,然后就可以使用全局变量 $ jQuery 了 

$('#foo');
// or
jQuery('#foo');

但是在 ts 中,编译器并不知道 $ jQuery 是什么东西

jQuery('#foo');
// ERROR: Cannot find name 'jQuery'.

这时,我们需要使用 declare var 来定义它的类型

declare var jQuery: (selector: string) => any;
jQuery('#foo');

declare var 并没有真的定义一个变量,只是定义了全局变量 jQuery 的类型,仅仅会用于编译时的检查

什么是声明文件

通常我们会把声明语句放到一个单独的文件( jQuery.d.ts )中,这就是声明文件 

//jQuery.d.ts
declare var jQuery: (selector: string) => any;
// index.ts
jQuery('#foo');

温馨提示
声明文件必需以 .d.ts 为后缀

这篇关于TypeScript【泛型1、泛型2、声明合并、命名空间 、模块1、模块2、声明文件简介】(五)-全面详解(学习总结---从入门到深化)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/517546

相关文章

关于C++中的虚拟继承的一些总结(虚拟继承,覆盖,派生,隐藏)

1.为什么要引入虚拟继承 虚拟继承是多重继承中特有的概念。虚拟基类是为解决多重继承而出现的。如:类D继承自类B1、B2,而类B1、B2都继承自类A,因此在类D中两次出现类A中的变量和函数。为了节省内存空间,可以将B1、B2对A的继承定义为虚拟继承,而A就成了虚拟基类。实现的代码如下: class A class B1:public virtual A; class B2:pu

51单片机学习记录———定时器

文章目录 前言一、定时器介绍二、STC89C52定时器资源三、定时器框图四、定时器模式五、定时器相关寄存器六、定时器练习 前言 一个学习嵌入式的小白~ 有问题评论区或私信指出~ 提示:以下是本篇文章正文内容,下面案例可供参考 一、定时器介绍 定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成。 定时器作用: 1.用于计数系统,可

轻量级在线服装3D定制引擎Myway简介

我写的面向web元宇宙轻量级系列引擎中的另外一个,在线3D定制引擎Myway 3D。 用于在线商品定制,比如个性化服装的定制、日常用品(如杯子)、家装(被套)等物品的在线定制。 特性列表: 可更换衣服款式,按需定制更换模型可实时更改材质颜色可实时添加文本,并可实时修改大小、颜色和角度,支持自定义字体可实时添加艺术图标,并可实时修改大小、颜色和角度,支持翻转、各种对齐可更改衣服图案,按需求定制

问题:第一次世界大战的起止时间是 #其他#学习方法#微信

问题:第一次世界大战的起止时间是 A.1913 ~1918 年 B.1913 ~1918 年 C.1914 ~1918 年 D.1914 ~1919 年 参考答案如图所示

揭秘未来艺术:AI绘画工具全面介绍

📑前言 随着科技的飞速发展,人工智能(AI)已经逐渐渗透到我们生活的方方面面。在艺术创作领域,AI技术同样展现出了其独特的魅力。今天,我们就来一起探索这个神秘而引人入胜的领域,深入了解AI绘画工具的奥秘及其为艺术创作带来的革命性变革。 一、AI绘画工具的崛起 1.1 颠覆传统绘画模式 在过去,绘画是艺术家们通过手中的画笔,蘸取颜料,在画布上自由挥洒的创造性过程。然而,随着AI绘画工

[word] word设置上标快捷键 #学习方法#其他#媒体

word设置上标快捷键 办公中,少不了使用word,这个是大家必备的软件,今天给大家分享word设置上标快捷键,希望在办公中能帮到您! 1、添加上标 在录入一些公式,或者是化学产品时,需要添加上标内容,按下快捷键Ctrl+shift++就能将需要的内容设置为上标符号。 word设置上标快捷键的方法就是以上内容了,需要的小伙伴都可以试一试呢!

AssetBundle学习笔记

AssetBundle是unity自定义的资源格式,通过调用引擎的资源打包接口对资源进行打包成.assetbundle格式的资源包。本文介绍了AssetBundle的生成,使用,加载,卸载以及Unity资源更新的一个基本步骤。 目录 1.定义: 2.AssetBundle的生成: 1)设置AssetBundle包的属性——通过编辑器界面 补充:分组策略 2)调用引擎接口API

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

C++必修:模版的入门到实践

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ 🎈🎈养成好习惯,先赞后看哦~🎈🎈 所属专栏:C++学习 贝蒂的主页:Betty’s blog 1. 泛型编程 首先让我们来思考一个问题,如何实现一个交换函数? void swap(int& x, int& y){int tmp = x;x = y;y = tmp;} 相信大家很快就能写出上面这段代码,但是如果要求这个交换函数支持字符型