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: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}
class Dog implements Animal{
  name: string
  constructor(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: string
    constructor(name:string){
      this.name = name;
   }
    sayHi(){
      console.log(this.name)
   }
 }
}
// Dog.ts
namespace AnimalInfo{
  export class Dog implements Animal{
    name: string
    constructor(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: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}
class Dog implements Animal{
  name: string
  constructor(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: string
  constructor(name:string){
    this.name = name;
 }
  sayHi(){
    console.log(this.name)
 }
}
// Dog.ts
import { Animal } from "./Animal"
export class Dog implements Animal{
  name: string
  constructor(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: string
  constructor(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: string
  constructor(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: string
  age:number
  constructor(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 为后缀

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

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

相关文章

小黑南京归来,参加部里的公务员培训,有点儿社死认识了好多小伙伴的leetcode之旅13. 罗马数字转整数

小黑代码 class Solution:def romanToInt(self, s: str) -> int:chars [M, CM, D, CD, C, XC, L, XL, X, IX, V, IV,I]nums [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]map_ dict((k, v) for k,v in zip(chars, nums))# 字符串长度n len(s)# 结果变量res …

安装Redis+Redis设置成windows下的服务+windows无法启动Redis服务,报错误1067:进程意外终止,解决方法

&#xff08;一&#xff09;安装Redis 官网地址&#xff1a;Redis 不过Redis 的官网不提供 Windows 版本的下载&#xff0c;可以从Github上下载&#xff0c;Windows版本的下载地址&#xff1a; https://github.com/microsoftarchive/redis/releases/ 无需安装&#xff0c;直…

2828. 判别首字母缩略词

2828. 判别首字母缩略词 难度: 简单 来源: 每日一题 2023.12.20 给你一个字符串数组 words 和一个字符串 s &#xff0c;请你判断 s 是不是 words 的 首字母缩略词 。 如果可以按顺序串联 words 中每个字符串的第一个字符形成字符串 s &#xff0c;则认为 s 是 words 的…

比例导引(PNG)-Matlab 程序

本文提供比例导引的matlab程序&#xff0c;想要看理论的可以看书《导弹飞行力学》或者我的博客 比例导引详解 代码 %% 三维比例导引末制导clc;clear; close all;%% 设置导弹初始参数和目标参数% 总步长 length 1000000; x_m zeros(length,1); y_m zeros(length,1); z_m z…

node.js mongoose

目录 官方文档 mongoose Schema Model Query document 关系 官方文档 Mongoose v8.0.3: Getting Started mongoose Mongoose 是一个 Node.js 环境下 MongoDB 的对象建模工具。它提供了一种在应用程序中与 MongoDB 数据库进行交互的方式&#xff0c;使得开发者能够使用…

基于k6和python进行自动化性能测试

摘要&#xff1a;在性能测试中&#xff0c;达到相应的性能指标对于一个软件来说十分重要&#xff0c;在本文中&#xff0c;将介绍一种现代化性能测试工具k6。 import http from k6/http; import { sleep } from k6; export default function () {http.get(https://test-api.co…

JNI 注册

一、 JNI 静态注册 ① 在 Android 的 Java 层定义方法 : 在 MainActivity 类中定义 如下 Native 方法 ; public native String stringFromJNI();② Native 方法实现 : 下面是一个 Native 方法实现的示例 ; extern "C" JNIEXPORT jstring JNICALL Java_kim_hsl_jni_…

JMeter如何进行多服务器远程测试

JMeter是Apache软件基金会的开源项目&#xff0c;主要来做功能和性能测试&#xff0c;用Java编写。 我们一般都会用JMeter在本地进行测试&#xff0c;但是受到单个电脑的性能影响&#xff0c;往往达不到性能测试的要求&#xff0c;无法有效的模拟高并发的场景&#xff0c;那么…

css实现0.5px宽度/高度显——属性: transform: scale

在大多数设备上&#xff0c;实际上无法直接使用 CSS 来精确地创建 0.5 像素的边框。因为大多数屏幕的最小渲染单位是一个物理像素&#xff0c;所以通常只能以整数像素单位渲染边框。但是&#xff0c;有一些技巧可以模拟出看起来像是 0.5 像素的边框。 这里介绍使用&#xff1a…

Linux内核模块

文章目录 一、内核模块介绍二、模块讲解1、最简模块代码&#xff1a;2、模块三要素3、常用操作命令3.1、 lsmod&#xff1a;显示已加载模块状态3.2、 insmod&#xff1a;载入模块3.3、rmmod&#xff1a;卸载模块3.4、dmesg&#xff1a;显示信息3.5、modinfo&#xff1a;显示ker…

Azure Machine Learning - 提示工程高级技术

本指南将指导你提示设计和提示工程方面的一些高级技术。 关注TechLead&#xff0c;分享AI全维度知识。作者拥有10年互联网服务架构、AI产品研发经验、团队管理经验&#xff0c;同济本复旦硕&#xff0c;复旦机器人智能实验室成员&#xff0c;阿里云认证的资深架构师&#xff0c…

2023/12/20 work

1. 使用select完成TCP客户端程序 2. 使用poll完成TCP并发服务器 3. 思维导图

linux 内核的 lru_list 的结构

在linux的slab分配的入口slab_alloc有一个传入参数lru&#xff0c;它的作用是使每个slab对象在unused&#xff0c;但可能后面继续使用的时候&#xff0c;不需要free&#xff0c;可以先放在lru_list上。lru_list的结构为&#xff1a; struct list_lru {struct list_lru_node *n…

【Axure RP9】中继器应用及相关案例

一 中继器简介 1.1 中继器是什么 中继器&#xff08;Repeater&#xff09;是一种高级的组件&#xff08;Widget&#xff09;&#xff0c;用于显示文本、图像和其他元素的重复集合。它是一个容器&#xff0c;容器中的每一个项目称作“item”&#xff0c;由于“item”中的数据由…

C# Tcplistener,Tcp服务端简易封装

文章目录 前言相关文章前言设计代码简单使用运行结果 前言 我最近有个需求要写Tcp服务端&#xff0c;我发现Tcp服务端的回调函数比较麻烦&#xff0c;简化Tcp的服务&#xff0c;我打算自己封装一个简单的Tcp服务端。 相关文章 C# TCP应用编程三 异步TCP应用编程 C# Tcpclient…

《数据结构、算法与应用C++语言描述》- 最小输者树模板的C++实现

输者树 完整可编译运行代码见&#xff1a;Github::Data-Structures-Algorithms-and-Applications/_31loserTree 输者树&#xff1a;每一个内部节点所记录的都是比赛的输者&#xff0c;晋级的节点记录在边上。本文中&#xff0c;赢者是分数较低的那个&#xff0c;输者是分数高…

线性回归中的似然函数、最大似然估计、最小二乘法怎么来的(让你彻底懂原理)收官之篇

图1 图2 图3 图4 问1&#xff1a;为什么要引入似然函数&#xff1f; 在线性回归中引入似然函数是为了通过概率统计的方法对模型参数进行估计。简单来说&#xff0c;我们希望找到一组参数&#xff0c;使得我们观测到的数据在给定这组参数的情况下最有可能发生。 问:1&#xf…

js之零碎工具(四)

一、数组的去重 简单类型的去重 let arr [1, 2, 2, 3, 4, 4, 5]; let uniqueArr [...new Set(arr)]; console.log(uniqueArr); // 输出&#xff1a;[1, 2, 3, 4, 5]在这个例子中&#xff0c;我们首先创建了一个新的 Set 对象&#xff0c;并将数组 arr 作为参数传递给 Set 的…

深度学习中的张量维度

1 深度学习中的张量 在深度学习框架中&#xff0c;Tensor&#xff08;张量&#xff09;是一种数据结构&#xff0c;用于存储和操作多维数组。张量可以被视为一种扩展的矩阵&#xff0c;它可以具有任意数量的维度。 在深度学习中&#xff0c;张量通常被用来表示神经网络的输入…

管理类联考——数学——真题篇——按题型分类——充分性判断题——蒙猜——按题号

上来先找C&#xff1a;一个等号一个不等号型&#xff0c;一个定量一个定性型&#xff0c;取值范围有交集型&#xff0c;最后找选项需要联立型&#xff08;因为是否需要联立&#xff0c;不要判断&#xff0c;一般如十字交叉&#xff09;。一般也就3-4个C。详见这里 找完C后找AB&…
最新文章