TypeScript|青训营笔记

67 阅读3分钟

什么是 TypeScript 主流

发展历史 => 略微了解一下就好


为什么是TS?
  1. JS:动态类型、弱类型语言 动态类型 => 执行阶段才进行变量类型的匹配
  2. TS: 静态类型、弱类型语言 静态类型 => 提前进行变量类型的匹配

可读性增强

可维护性增强 => 编译阶段就会暴露大部分错误 => 适合多人共同维护项目

JS 超集 => 支持渐进式引入与升级 + 包含所有JS特性

基本语法


/*字符串*/
const q = 'string'
/*同样是字符串类型的变量 TS提前做了变量的类型定义*/
const q:string = 'string'
对象类型
const bytedancer:IBytedancer = {
/*手动创建一个类型*/
  jobId:930245,
  name:'zeng',
  sex:'man',
  age:28,
  hobby:'swimming',
}

interface IBytedancer {
/*只读属性: 约束属性不可在对象初始化外赋值*/
readonly jobId:number;
name:string;
sex:'man'|'woman'|'other';
age:number;
/*可选属性: 定义该属性可以不存在*/
hobby?: string;
/*任意属性: 约束所有对象属性都必须是该属性的子类型*/
[key:string]: any;
}

📌 readonly 标记的属性只能在声明时或类的构造函数中赋值

const user : Readonly<USER> = {
    name: 'zhb',
    age: 23
}

user.name = 'zzz' // error => name属性只可读
数组类型
/*类型 + 方括号*/
type IArr1 = number[];
/*泛型表示*/
type IArr2 = Array<string | number | Record<string,number>> // 尖括号内就是数组元素的类型
//---------------------------------
/*原始表示*/
type IArr3 = [number,string,number];
/*接口表示*/
interface IArr4 = {
    [key:number]:any;
}
/*Record:以 typeof 形式创建一个类型,包含一组指定的属性且必填*/
type example = Record<'x'|'y',number>;
=> 等同于
type example = {
    x:number;
    y:number;
}
TS 泛型 => 不预先指定变量的类型,在使用的时候再指定类型的一种特性
  1. 泛型约束:限制泛型必须符合字符串

    type IGetRepeatStringArr = <T extends string>(target: T) => T[];
    const getStrArr = IGetRepeatStringArr = target => new Array(100).fill(target);
    getStrArr(123);// error 传参类型不匹配
    
  2. 泛型参数默认类型

    type IGetRepeatArr<T = number> = (target: T) => T[];
    const getStrArr = IGetRepeatStringArr = target => new Array(100).fill(target);
    getStrArr('123');// error 
    
  3. 类型别名 & 类型断言

函数重载
  1. 📚 首先,重载是指方法名字相同,参数不同,返回类型可以相同也可以不相同
  2. 每个重载的方法(或者构造函数) 都必须有一个独一无二的参数类型列表

=> 范围问题 => 将自定义变量的范围大于匿名函数的范围

// 示例
function disp(string):void;
function disp(number):void;

// 进阶案例
/* 对getDate函数进行重载,timestamp可为缺省参数*/
function getDate(type:'string',timestamp?:string):string;
interface IGetDate{
    (type:'string',timestamp?:string):string;
    (type:'string',timestamp?:string):Date;
    (type:'string'|'date',timestamp?:string):Date | string;
}

const getDate2:IGetDate = (type,timestamp)=>{
    const date = new Date(timestamp);
    return type === 'string'? date.toLocaleString():date;
}

image.png 让我们看看报错信息 👁️ image.png 从图中我们可以看到,ts自动对我们的timestamp变量类型做了判断,但是这个判断并不符合,这也就是上面提到的变量范围的原因,我们要将声明变量中的范围大于匿名函数中变量的范围即可。 image.png

TypeScript 高级类型

联合/交叉类型
  1. 联合类型
    • "IA | IB":表示一个值可以是几种类型之一
  2. 交叉类型
    • "IA & IB":多种类型叠加到一起成为一种类型,它包含了所需的所有类型的所有特性
  3. 具体实例
    // 原始声明
    const bookList = [{
        author:'xiaoming',
        type:'history',
        range:'2001-2021',
    },{
        author:'xiaoli',
        type:'story',
        theme:'love'
    }]
    // ------------
    type IBookList = Array<{
        // 公共类型
        author:string,
    } & ({
        type:'history';
        range:string;
    } | {
        type:'story';
        theme:string;
    })
    
类型保护与类型守卫

类型守卫:定义一个函数,它的返回值是一个类型谓词,生效范围为子作用域

interface IA{a:1,a1:2}
interface IB{b:1,b1:2}

function getIsIA(args:IA|IB):arg is IA{
    return !!(arg as IA).a;
}
function log2(args:IA|IB){
    if(getIsIA(arg)){
        console.log(arg.a1)
    }else{
        console.log(arg.b1)
    }
}

TypeScript 工程应用

Webpack

  1. loader => 实现对ts文件的编译和检查

Node.js

  1. 使用TSC编译 🔍code.ts => TSC(code.ts) => code.js