TypeScript完全解读

670 阅读7分钟

TypeScript完全解读

本文主要是从一个项目的角度来对typescript从无到有进行解读,若有不当或者不对之处,敬请指教。持续更新中...

1. 初始化

  • 初始化项目: npm init -y
  • 全局安装ts依赖:npm install typescript tslint -g
  • ts初始化:tsc --init
  • 安装webpack:npm install webpack webpack-cli webpack-dev-server -D

2. vscode需要安装的插件

  • TSLint
  • TSLint (deprecated)
  • TSLint Vue
  • TSLint Snippets
  • TSLint Vue-TSX
  • json to TS 将json类型的数据 直接生成ts的类型
  • Settings Sync 配置github保存
  • 图像预览工具:Image preview

3. ts的基础类型

3.1. 布尔值(和其他语言中一样)

let isDone: boolean = false;

3.2. 数字(ts中所有的数字类型都是number)

let num: number = 123
num = 12.3
num = 0b11;
num = 0o111;
num = 0x11;

3.3. 字符串类型(可以使用双引号,单引号,反引号来表示字符串)

let num1 = 12
let str: string;
str = 'abc';
str = `数值:${num1}`

3.4. 数组类型(有两种定形式,一种是在元素类型后边添加[],一种是使用泛型 Array[元素类型])

// 元素后边添加[]类型
let arr1: number[];
let arr2: (string | number)[];

// 使用泛型 Array[元素类型]
let arr3: Array<number>;
let arr4: Array<string | number>;
// 调用
arr1 = [1];
arr2 = [1, 'a']

3.5. 元组Tuple类型(表示一个已知元素数量和类型的数组,各元素的类型不必相同)

let tuple: [string, number, boolean];
tuple = ['a', 1, false]

3.6. 枚举类型(不设置初始值,自动从0开始,也可以自定义设置默认值)

enum Roles {
    ADMIN,
    USER = "admin",
}

3.7. any类型(尽量少用,否则ts将完全没有价值)

let value:any = 'abc'

3.8. void类型(没有返回值 默认返回值是undefine)

某种程度上void类型和any类型相反;此外声明一个void类型没有太大意义没因为它只能赋值undefined和null

const consoleText = (text: string): void => {
    console.log(text)
}

let unable:void = undefined | void;

3.9. Null和Undifined类型(是所有类型的子类型,其他值都是可以被赋值为null或undefined)

let u: undefined;
u = undefined;
let n: null;
n = null;

3.10. Never类型(永不存在的值的类型) 一般情况下错误类型和死循环 抛出的是never类型

// never类型  是不存在的类型
const errorFun = (message: string): never => {
    throw new Error(message)
}

//-死循环也是抛出的never类型
const infiniteFunc = (): never => {
    while (true) { }
}

3.11 Object类型 object表示非原始类型,也就是除number,string,boolean,symbol,null或undefined之外的类型。

3.12 断言(已经确定的类型) 断言有两种形式:一种尖括号语法;一种as语法

// 获取一个数据的长度
const getLenght = (target: string | number) => {
    if ((<string>target).length || (target as string).length === 0) {
        return (target as string).length
    } else {
        return target.toString().length
    }
}

注意:当在TypeScript里使用JSX时,只有 as语法断言是被允许的。

3.13 symbol类型

  • symbol是新增的一种类型,表示独一无二的值
  • symbol的值不可以与其他数据类型做运算

4. 函数

函数有两种定义方式:分别是使用字面量方式和关键字Function方式

const func = funct(){}
function func(){}

5. 高级类型

5.1 交叉类型 交叉类型一般使用& 符号来连接两个类型。相对于并集取值。

const mergeFunc = <T, U>(arg1: T, arg2: U): T & U => {
  // let res = {} as T&U;
  // let res = <T&U>{};
  let res = Object.assign(arg1, arg2);
  return res;

5.2 联合类型 联合类型一般使用| 符号来标识。相当于或的关系

let number: string | number;
// 获取长度的方法
const getLengthFunc = (content: string | number) => {
  if (typeof content === "string") return content.length;
  else return content.toString().length;
};

5.3 类型保护法 一般情况是有两种以上类型的时候,会做类型的判断,会导致类型报错。通常是有typeofinstanceof 两个类型判断语句进行。

  • typeof:只能作为等于或者不等于的操作,其他的规则不提供类型保护;运算的类型只鞥是以下四种类型中的一种:string/number/boolean/symbol
  • instanceof 类型保护效果,可使用上边非四种类型外的其他类型。

5.4 类型确定用法 在开发的过程中,确定某一种类型是什么,但是编辑器仍会报错,此时便可以用 ! 符号来使用类型断言,表示一定是这一个类型。

function getSplicedStr(num: number | null): string {
  function getRes(prefix: string) {
   // !此处表示一定是这个数据类型
    return prefix + num!.toFixed().toString();
  }
  num = num || 0.0;
  return getRes("sub_");
}

5.5 字符串字面量类型 在一些已确定的类型中使用字符串字面量 来定义类型,避免出现字面量以外的类型。数字字面量类型与字符串类字面量基本类似

// 定义了一个方向的字符串字面量类型
type Direction = "north" | "east" | "south" | "west";
// 获取第一个字母
function getDirectionFirstLetter(direction: Direction): string {
  return direction.substr(0, 1);
}
// 调用 只能输入定义的字面量类型
getDirectionFirstLetter("north");

5.6 可辨识联合类型 可辨识联合类型的两个要素:

    1. 具有普通的单例类型属性;
    1. 一个类型别名包含了那些类型的联合

以下是一个圆形、矩形、长方形求面积的一个实例:

// 定义正方形的接口
interface Square {
  kind: "square";
  size: number;
}
// 定义一个长方形的接口
interface Rectangle {
  kind: "rectangle";
  height: number;
  width: number;
}
// 定义一个圆形的接口
interface Circle {
  kind: "circle";
  radius: number;
}

// 将三种类型的接口 定义为一个字符串字面量类型
type Shape = Square | Rectangle | Circle;

// 非其他上述三种类型外的其他类型。
function asserNever(value: never): never {
  throw new Error("Unexpected Object:" + value);
}

//求各种类型的面积方法
function getArea(s: Shape): number {
  switch (s.kind) {
    case "square":
      return s.size * s.size;
    case "rectangle":
      return s.height * s.width;
    case "circle":
      return Math.PI * s.radius ** 2;
    default:
      return asserNever(s);
  }
}

5.7 索引类型 索引类型主要分为两部分,分别是索引类型查询和索引访问。

  • 索引查询

    • 索引查询使用操作符keyof可以生成一个字面量类型的联合类型。 enter description here
  • 索引访问

    • 索引访问使用操作符[] ,可以获取单个的属性值,也可以获取一组属性值

enter description here

5.8 映射类型 映射类型:可以用过一个旧类型转换成一个新的类型。

QQ截图20210622093421

映射中提供了一些内置的方法:readonlypartailpickrecord

  • readonly:表示将所有的属性变成只读

    type inner_readOnly = Readonly<oldInfoType>;

  • partail:表示将所有的数据变成可选

    type inner_readOnly = Partail<oldInfoType>;

  • pick:表示获取对象的部分属性

    enter description here

  • record 适用于将一个对象中的每一个属性 转换成其他值得一个场景 enter description here

5.9 增加或移除特定修饰符 可以使用 +- 来添加或者删除特殊修饰符 默认是添加 +

type oldInfoMap<T> = {
 + readonly [P in keyof T]-?: T[P]; // in 表示循环
};

5.10 unknown 类型

  1. 任何类型都可以赋值给unknown类型

    let value1: unknown;
    value1 = 11;
    value1 = "aaa";
    
  2. 如果没有类型断言或基于控制流的类型细化时,unknown 不可以赋值给其他类型,此时他只能赋值给unknown自身 和any 类型。

    let value2: unknown;
    
    // error:不能将类型“unknown”分配给类型“string”
    // let value3:string = value2;
    
  3. 如果没有类型断言或基于控制流的类型细化时,不能在他上面进行任何操作

    let value4: unknown;
    
    // error:对象的类型为 "unknown"
    // value4+=1;
    
  4. unknown 与任何其他类型组成的交叉类型,最后等于其他类型

    type type1 = string & unknown;
    type type2 = number & unknown;
    type type3 = unknown & unknown;
    type type4 = string[] & unknown;
    
  5. unknown 与任何其他类型(除了any)组成的联合类型,都等于unknown类型

    type type5 = string | unknown;
    type type6 = any | unknown;
    type type7 = string[] | unknown;
    
  6. never 类型是 unknown的子类型

    type type8 = never extends unknown ? true : false;
    
  7. keyof unknown 等于类型 never

    type type9 = keyof unknown;
    
  8. 只能对unknown进行等或不等操作,不能进行其他操作

    value1 === value2;
    value1 !== value2;
    
  9. unknown 类型的值不能访问他的属性、不能作为函数调用和作为类创建实例

    let value10: unknown;
    // value10.name= ''
    // value10()
    // new value10()
    
  10. 使用映射类型时如果遍历的是unknown类型,则不会映射任何属性

    type types1<T> = {
      [P in keyof T]: number;
    };
    type type10 = types1<any>;
    type type11 = types1<unknown>;
    
    

5.11 条件类型 示例:T extends U ? X : Y

//普通的用法 type types2<T> = T extends string ? string : number; //使用关键字的用法 type Type14<T> = T extends Array<infer U> ? U : T;

条件类型的 一些内置的方法:Exclude,Extract,NonNullable,ReturnType

  • Exclude<T,U> 获取U中不在T中的一项 type Type15 = Exclude<"a" | "b" | "c", "a" | "b">;
  • Extract <T,U> 获取T和U的交集 type Type16 = Extract<"a" | "b" | "c", "a" | "v">;
  • NonNullable 去掉null 和undefined type Type17 = NonNullable<string | number | null | undefined>;
  • ReturnType 获取返回值类型 type Type18 = ReturnType<() => string>;