当前位置: 首页 > news >正文

TypeScript 小结

TypeScript 是什么?

TypeScript 是由微软开发的一种自由和开源的编程语言。它是 JavaScript 的一个超集,本质上是在 JavaScript 的基础上添加了可选的静态类型和基于类的面向对象编程。

TypeScript 和 JavaScript 的区别?

在这里插入图片描述

TypeScript 的安装

# npm安装
npm install -g typescript
# 验证
tsc -v # Version 4.6.4
# 编译
tsc helloworld.ts # helloworld.ts => helloworld.js

TypeScript 的数据类型

  • Boolean 类型
  • Number 类型
  • String 类型
  • Symbol 类型
  • Array 类型
  • Enum 类型
    • 数字枚举
    enum Direction {
      NORTH = 3, // 默认初始值从0开始, 可手动指定
      SOUTH,
      EAST,
      WEST,
    }
    
    • 字符串枚举
    enum Direction {
      NORTH = "NORTH",
      SOUTH = "SOUTH",
      EAST = "EAST",
      WEST = "WEST",
    }
    
    • 常量枚举
    const enum Direction {
      NORTH,
      SOUTH,
      EAST,
      WEST,
    }
    
    • 异构枚举
    enum Enum {
      A,
      B,
      C = "C",
      D = "D",
      E = 8,
      F,
    }
    
  • Any 类型
    • 在 TypeScript 中,任何类型都可以归类为 any 类型,本质上 any 类型是类型系统的顶级类型(全局超级类型)。TypeScript 允许开发者对 any 类型的值执行任何操作,而无需事先执行任何形式的检查
    • 使用 any 类型,可以很容易地编写出类型正确但在实际代码运行过程中有问题的代码,使用了 any 类型就无法使用 TypeScript 提供的大量的保护机制
  • Unknown 类型
    • 为了解决 any 类型带来的问题,TypeScript 3.0 引入了 unknown 类型
    • 就像所有的类型都可以赋值给 any 类型一样,所有的类型也都可以赋值给 unknown 类型。这样使得 unknown 类型成为 TypeScript 类型系统的另一种顶级类型
    • unknown 类型只能被赋值给 any 类型和 unknown 类型本身
  • Tuple 类型
    • 元组是TypeScript 中特有的类型,其工作方式类似于数组,元组可用于定义具有有限数量的未命名属性的类型,每个属性都有一个关联的类型。使用元组时,必须提供每个属性的值
    let tupleType: [ string, boolean ];
    tupleType = [ "semlinker", true ];
    
  • Void 类型
    • void 类型与 any 类型相反,它表示没有任何类型,当一个函数没有返回值时,可以设置返回值类型为 void
  • Null 和 Undefined 类型
  • object,Object 和 {} 类型
  • Never 类型
    • never 类型表示那些永远不存在的值的类型(例如那些总是会抛出异常或者根本不会有任何返回值的函数表达式或箭头函数表达式)

TypeScript 的断言

  • 类型断言
    • 类型断言类似于类型转换,但是不进行特殊的数据检查和解构,它没有运行时的影响,只是在编译阶段起作用
    const someValue: any = "this is a string";
    const strLength: number = (<string>someValue).length; // 尖括号写法
    const strLength: number = (someValue as string).length; // as写法
    
  • 非空断言
    • 在上下文中当类型检查器无法断定类型时,一个新的后缀表达式操作符 ! 可以用于断言操作对象是非 null 和非 undefined 类型。具体而言,x! 将从 x 值域中排除 null 和 undefined
    function myFunc(maybeString: string | undefined | null) {
      // Type 'string | null | undefined' is not assignable to type 'string'.
      // Type 'undefined' is not assignable to type 'string'. 
      const onlyString: string = maybeString; // Error
      const ignoreUndefinedAndNull: string = maybeString!; // Ok
    }
    

TypeScript 的接口

interface Person {
  name: string; 
  age?: number; // 可选属性
  readonly sex: number; // 只读属性
  [ x: string ]: any; // 任意属性
}

let semlinker: Person = {
  name: "semlinker",
  age: 33,
};

TypeScript 接口与类型别名的区别?

  • 接口和类型别名都可以用来描述对象的形状或函数签名
    // 接口
    interface Point {
      x: number;
      y: number;
    }
    
    interface SetPoint {
      (x: number, y: number): void;
    }
    
    // 类型别名
    type Point = {
      x: number;
      y: number;
    };
    
    type SetPoint = (x: number, y: number) => void;
    
  • 与接口类型相比,类型别名可用于一些其他类型(比如原始类型、联合类型和元组)
    // primitive
    type Name = string;
    
    // object
    type PartialPointX = { x: number; };
    type PartialPointY = { y: number; };
    
    // union
    type PartialPoint = PartialPointX | PartialPointY;
    
    // tuple
    type Data = [ number, string ];
    
  • 扩展
    // Interface extends interface
    interface PartialPointX { x: number; }
    interface Point extends PartialPointX { 
      y: number; 
    }
    
    // Type alias extends type alias
    type PartialPointX = { x: number; };
    type Point = PartialPointX & { y: number; };
    
    // Interface extends type alias
    type PartialPointX = { x: number; };
    interface Point extends PartialPointX { y: number; }
    
    // Type alias extends interface
    interface PartialPointX { x: number; }
    type Point = PartialPointX & { y: number; };
    
    // 与类型别名不同, 接口可以定义多次, 多个接口会被自动合并为单个接口
    interface Point { x: number; }
    interface Point { y: number; }
    const point: Point = { x: 1, y: 2 };
    

TypeScript 的泛型

function identity <T, U>(value: T, message: U) : T {
  console.log(message);
  return value;
}
identity<Number, string>(68, "Semlinker");
// 我们也可以完全省略尖括号, 让编译器自动选择这些类型
identity(68, "Semlinker")

// 泛型接口
interface GenericIdentityFn<T> {
  (arg: T): T;
}

// 泛型类
class GenericNumber<T> {
  zeroValue: T;
  add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function (x, y) {
  return x + y;
};

// 泛型工具类型
// Partial<T>的作用就是将某个类型里的属性全部变为可选项?
// 首先通过keyof T拿到T的所有属性名, 然后使用in进行遍历, 将值赋给P
// 最后通过T[P]取得相应的属性值, 中间的?号用于将所有属性变成可选
type Partial<T> = {
  [ P in keyof T ]?: T[ P ];
};

TypeScript 的配置文件

  • tsconfig.json 的作用
    • 用于标识 TypeScript 项目的根路径
    • 用于配置 TypeScript 编译器
    • 用于指定编译的文件
  • tsconfig.json 的重要字段
    • files:设置要编译的文件的名称
    • include:设置需要进行编译的文件,支持路径模式匹配
    • exclude:设置无需进行编译的文件,支持路径模式匹配
    • compilerOptions:设置与编译流程相关的选项
  • compilerOptions 的选项
    {
      "compilerOptions": {
    
        /* 基本选项 */
        "target": "es5",                       // 指定ECMAScript目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017' or 'ESNEXT'
        "module": "commonjs",                  // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
        "lib": [],                             // 指定要包含在编译中的库文件
        "allowJs": true,                       // 允许编译javascript文件
        "checkJs": true,                       // 报告javascript文件中的错误
        "jsx": "preserve",                     // 指定jsx代码的生成: 'preserve', 'react-native' or 'react'
        "declaration": true,                   // 生成相应的'.d.ts'文件
        "sourceMap": true,                     // 生成相应的'.map'文件
        "outFile": "./",                       // 将输出文件合并为一个文件
        "outDir": "./",                        // 指定输出目录
        "rootDir": "./",                       // 用来控制输出目录结构 --outDir.
        "removeComments": true,                // 删除编译后的所有的注释
        "noEmit": true,                        // 不生成输出文件
        "importHelpers": true,                 // 从tslib导入辅助工具函数
        "isolatedModules": true,               // 将每个文件做为单独的模块(与 'ts.transpileModule'类似).
    
        /* 严格的类型检查选项 */
        "strict": true,                        // 启用所有严格类型检查选项
        "noImplicitAny": true,                 // 在表达式和声明上有隐含的any类型时报错
        "strictNullChecks": true,              // 启用严格的null检查
        "noImplicitThis": true,                // 当this表达式值为any类型的时候, 生成一个错误
        "alwaysStrict": true,                  // 以严格模式检查每个模块, 并在每个文件里加入 'use strict'
    
        /* 额外的检查 */
        "noUnusedLocals": true,                // 有未使用的变量时, 抛出错误
        "noUnusedParameters": true,            // 有未使用的参数时, 抛出错误
        "noImplicitReturns": true,             // 并不是所有函数里的代码都有返回值时, 抛出错误
        "noFallthroughCasesInSwitch": true,    // 报告switch语句的fallthrough错误(即不允许 switch的case语句贯穿)
    
        /* 模块解析选项 */
        "moduleResolution": "node",            // 选择模块解析策略: 'node'(Node.js) or 'classic'(TypeScript pre-1.6)
        "baseUrl": "./",                       // 用于解析非相对模块名称的基目录
        "paths": {},                           // 模块名到基于baseUrl的路径映射的列表
        "rootDirs": [],                        // 根文件夹列表, 其组合内容表示项目运行时的结构内容
        "typeRoots": [],                       // 包含类型声明的文件列表
        "types": [],                           // 需要包含的类型声明文件名列表
        "allowSyntheticDefaultImports": true,  // 允许从没有设置默认导出的模块中默认导入
    
        /* Source Map Options */
        "sourceRoot": "./",                    // 指定调试器应该找到TypeScript文件而不是源文件的位置
        "mapRoot": "./",                       // 指定调试器应该找到映射文件而不是生成文件的位置
        "inlineSourceMap": true,               // 生成单个soucemaps文件而不是将sourcemaps 生成不同的文件
        "inlineSources": true,                 // 将代码与sourcemaps生成到一个文件中, 要求同时设置了 --inlineSourceMap或 --sourceMap属性
    
        /* 其他选项 */
        "experimentalDecorators": true,        // 启用装饰器
        "emitDecoratorMetadata": true          // 为装饰器提供元数据的支持
      }
    }
    

TypeScript 的 .d.ts

.d.ts 文件是 TypeScript 用来声明变量、模块、type、interface 等等的。

和纯 js 文件相比,在 .d.ts 文件中声明变量或者模块后,在其他地方可以不用 import 导入就能直接使用,并且还有语法提示。

但并不是说创建了 .d.ts 文件,里面声明的东西就能生效,毕竟归根到底它也是 .ts 文件,需要进行预编译,所以需要在 tsconfig.json 文件里面的 include 数组里面添加这个文件。

include 数组里面可以不用写 .d.ts 文件的绝对路径,可以通过 glob 通配符,匹配这个文件所在的文件夹或者是相对路径。

TypeScript 的 declare

.d.ts 文件中的顶级声明必须以 declare 或者 export 修饰符开头。

通过 declare 声明的类型、变量和模块,在 include 包含的文件范围内,都可以直接引用而不用去 import 或者 import type 相应的变量或类型。

// declare声明一个类型
// 在include包含的文件范围内可以直接使用这个type
declare type Asd {
	name: string;
}

// declare声明一个模块
// 在编辑ts文件的时候, 如果你想导入一个.css/.less/.png格式的文件, 如果没有经过declare是会提示语法错误的
declare module '*.css';
declare module '*.less';
declare module '*.png';

// declare声明一个变量
// 假如在项目中引入了一个sdk(以微信的sdk为例), 里面有一些全局的对象(比如wx), 但是如果不经过任何的声明, 在ts文件里面直接用wx.config(), 肯定会报错的
// declare就是告诉ts编译器, 你担保这些变量和模块存在, 同时声明了相应类型, 在编译的时候不需要提示错误

// declare声明一个作用域
// 声明完之后在其他地方的ts就可以直接通过API.ResponseList引用到这个接口类型
declare namespace API {
	interface ResponseList {}
}
  • .d.ts 文件的顶级声明 declare 最好不要和 export 同级使用,不然在其他 ts 文件中引用这个 .d.ts,就需要手动 import 导入了
  • 在 .d.ts 文件里,如果顶级声明不用 export,declare 和直接写 type、interface 的效果是一样的,在其他任何地方都可以直接引用

参考文档

  • https://juejin.cn/post/6872111128135073806#heading-0
  • https://juejin.cn/post/7083869402001178655
  • https://www.tslang.cn/docs/handbook/tsconfig-json.html

相关文章:

  • Netty(10)协议设计与解析(IdleStateHandler:空闲检测器、心跳)
  • PostgreSQL数据库统计信息——analyze大致流程
  • C开发环境与基础
  • Android系统_MSM8953_android10_adb连接adbd加入密码检测
  • 23设计模式之 --------- 什么是设计模式?
  • 在以「基础设施」为定位的发展阶段里,产业变成了一个可以有诸多创新的存在
  • Vue相关面试题(1)
  • 基于SpringBoot的网上购物商场管理系统
  • Python——time模块
  • 【深度学习】卷积神经网络的架构参考 以MNIST数据集为例(未调节架构)测试集正确率: 98.66%
  • C++ 哈希桶模拟实现(补充)
  • Rethinking the Inception Architecture for Computer Vision--Christian Szegedy
  • 安卓毕业设计成品基于Uniapp+SSM实现的智能课堂管理APP在线学习网
  • 基于metaRTC嵌入式webrtc的H265网页播放器实现(我与metaRTC的缘分)
  • 【设计模式】Java设计模式 - 组合模式
  • [NodeJS] 关于Buffer
  • Android单元测试 - 几个重要问题
  • angular2开源库收集
  • Docker下部署自己的LNMP工作环境
  • IndexedDB
  • Java 11 发布计划来了,已确定 3个 新特性!!
  • Java Agent 学习笔记
  • leetcode46 Permutation 排列组合
  • Magento 1.x 中文订单打印乱码
  • Service Worker
  • Vue ES6 Jade Scss Webpack Gulp
  • 当SetTimeout遇到了字符串
  • 得到一个数组中任意X个元素的所有组合 即C(n,m)
  • 好的网址,关于.net 4.0 ,vs 2010
  • 基于组件的设计工作流与界面抽象
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 通过git安装npm私有模块
  • 微服务框架lagom
  • - 语言经验 - 《c++的高性能内存管理库tcmalloc和jemalloc》
  • 正则与JS中的正则
  • zabbix3.2监控linux磁盘IO
  • 如何在招聘中考核.NET架构师
  • ​LeetCode解法汇总307. 区域和检索 - 数组可修改
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • $emit传递多个参数_PPC和MIPS指令集下二进制代码中函数参数个数的识别方法
  • (01)ORB-SLAM2源码无死角解析-(66) BA优化(g2o)→闭环线程:Optimizer::GlobalBundleAdjustemnt→全局优化
  • (windows2012共享文件夹和防火墙设置
  • (二)c52学习之旅-简单了解单片机
  • (附源码)计算机毕业设计SSM保险客户管理系统
  • (全注解开发)学习Spring-MVC的第三天
  • (推荐)叮当——中文语音对话机器人
  • (转)Linq学习笔记
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET/C# 将一个命令行参数字符串转换为命令行参数数组 args
  • .net和php怎么连接,php和apache之间如何连接
  • .net经典笔试题
  • .NET开源项目介绍及资源推荐:数据持久层
  • .net中的Queue和Stack
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?