TS入门 | 青训营笔记

61 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

学习TypeScript的基础语法,了解其高级应用

TS发展与基础语法

为什么是TS?

👉TS发展历史

  • 2012-10:微软发布第一个版本
  • 2014-10:Angular 发布基于TS的2.0版本
  • 2015-04:微软发布VScode(最支持TS的开发软件)
  • 2016-05:@type/react发布,TS可以开发React
  • 2020-09:Vue3版本支持TS
  • 2021-11:TS v4.5版本发布

👉JS VS TS

  • (JS)动态类型 VS (TS)静态类型
    • 静态类型:可读性强、可维护性强、合作项目中能有更好的稳定性和开发效率
    • TS是JS的超集:包含与兼容JS的所有特性,支持共存;支持渐进式引入与升级

静态类型语言中,变量的类型必须先声明,即在创建的那一刻就已经确定好变量的类型,而后的使用中,你只能将这一指定类型的数据赋值给变量。如,一旦声明一个变量是int类型,之后就只能将int类型的数据赋值给它,否则就会引发错误。

动态类型则没有这样的限制,你将什么类型的数据赋值给变量,这个变量就是什么类型。

  • 都是弱类型语言
    • 强弱之分,体现在对类型的检查严格程度上,弱类型语言对于变量类型的检查比较宽松,容忍隐式类型转换。隐式类型转换,一般有两种形式:
      1. 相关类型之间隐式转换:如 int + float = float, int 先转换为 flaot 再相加
      2. 不相关类型之隐式间转换:如 int + string = string, int 先转换为 string 再合并
    • 在弱类型语言中,变量可以隐式强制转换为不相关类型,而在强类型语言中则不可以。

TS的基本语法

👉基础数据类型

  • any, string, numberm, boolean, null, undefined...
  • const q: string = 'string'

👉 type关键字(类型别名)

  • 用于定义类型,不同于 interface 只能定义对象类型, type 声明的方式可以定义任意类型。
  • 字符串/数字的字面量,允许指定固定值,type IOddNum = 1|3|5|7|9

👉接口与对象

  • 接口是一系列抽象方法的声明,可用于定义对象类型
  • 命名以I开头,用于区分TS自带的对象
 interface IMyInterface {
     // 只读,定义后不可修改
     readonly stuId: number;
     name: string;
     sex: 'man'| 'woman'| 'other';
     age: number;
     // 可选属性,定义时可以不写
     hobby?: string;
     // 任意属性,添加的新的其它属性的类型都必须是该类型的子类型
     [key: string]: any;
 }

 const ddInterface: IMyInterface= {
     stuId: 20230119,
     name: 'dede',
     sex:'woman',
     age: 23,
     hobby: 'code',
     platform: 'ByteDancer'
 }
 console.log(ddInterface);
 ​

👉函数

  • 需要声明类型的地方:传入和传出(返回)的参数
  • 传入参数可以设置成:可选、有默认值、剩余参数等
  • 可以使用接口实现
 function fn(name:string, age:number = 23, hobby?:string, ...restOfArgs: string[]): string{
     return 'Hi';
 }
 // 接口
 interface IMult {
     (x: number, y: number): number;
 }
 const mult: IMult = (x, y) => x * y;

👉数组

  • 类型+[] (常用)
  • 泛型generics,对类型编程(常用)
  • 元祖:允许存储不同类型的元素
  • 接口实现
 type IArr1 = number[];
 type IArr2 = Array<string | number | Record<string, number>>;
 type IArr3 = [number, number, string, string]
 interface IArr4 {[key: number]: any;}
 ​
 const arr1: IArr1 = [1, 2, 3, 4];
 const arr2: IArr2 = ['aa', 1, 2, { b: 3 }];
 const arr3: IArr3 = [1, 2, '3', '4'];
 const arr4: IArr4 = ['string', 100, {}, () => null]

👉其它补充类型

  • 空类型,表示无赋值
  • 枚举类型(E开头): 支持枚举值与枚举名的正反映射
 type IEmptyFn = () => void
 ​
 enum EExample {
     add = '+',
     mult = '*',
 }
 EExample['add'] === '+';
 EExample['*'] === 'mult';

👉泛型

  • 不预先指定具体的类型,在使用的时候再指定(对类型编程)
  • 对比两个GetArr
    • 不使用泛型,会产生输入number,返回string[]的情况。
    • 使用了泛型能保证输入了number,返回number的数组,即输入什么类型返回什么类型,
  • 泛型还可以用于接口、类、类型别名等。
 type IGetArr1 = (target: any) => any[];
 type IGetArr2 = <T>(target: T) => <T>[];
 ​
 interface IX<T,U> {
     key: T;
     val: U;
 }
 class IM<T> { instance: T; }
 type ITypeArr<T> = Array<T>
  • 泛型约束:限制泛型必须限定在一定范围内(使用extends关键字)
  • 泛型参数默认类型:type IGetString<T = string> = (target:T) =>T[]

高级应用

联合/交叉类型

  • 联合类型:IA | IB, 一个值可以是几种类型

    • 类型保护:TS处于程序安全考虑,仅允许访问联合类型的交集部分(JS都可以访问)
    • 类型守卫:定义一个函数,返回一个类型谓词
  • 交叉类型:IA & IB 多种类型叠加到一起成为一种类型

 // JS
 const bookList = [
 {
     author: 'xiaoming',
     type: 'history',
     range: '2001-2021',
 }, {
     author: 'xiaohong',
     type: 'story',
     theme: 'love',
 }]
 // TS
 type IBookList = Array<{
     author: string;
 } & ({
     type: 'history',
     range: '2001-2021',
 } | {
     type: 'story',
     theme: 'love',
 })>
 // 联合类型 + 类型保护 = 自动类型推断
 function logBookInfo(book: IBookList) {
     if(book.type == 'history') {  // 交集为type
         console.log(book.range);
     } else {
         console.log(book.theme);
     }
 }

TS的工程应用

浏览器web👉webpack

  • 配置webapack loader相关配置
  • 配置tsconfig.js 文件
  • 运行webpack启动/打包

Node👉tsc编译

  • npm install -g typescript
  • ts文件转换为js文件: tsc hello.ts
  • 执行js文件: node hello.js