TypeScript | 青训营笔记

148 阅读3分钟

TypeScript

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

为什么是 TypeScript

静态类型:

  • 可读性增强:基于语法解析 TSDoc, ide 增强
  • 可维护性增强:在编译阶段暴露大部分错误
  • 多人合作的大型项目中,获得更好的稳定性和开发效率

JS 的超集:

  • 包含于兼容所有 Js 特性,支持共存
  • 支持渐进式引入与升级

基本语法

基本类型

/* 字符串 */
const q:string = 'string';
/* 数字 */
const W:number = 1;
/* 布尔值 */
const е:boolean = true;
/* null */
const r:null = null;
/* undefined */ 
const t:undefined = undefined;

对象类型

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

函数类型

interface IMult {
  (x: number, y: number): number;
}
const mult: IMult = (x, y) => x * y;
function add(x: number, y: number): number {
  return x + y;
}
const mult: (x: number, y: number) => number = (x, y) => x * y;

数组类型

/*「类型+方括号」表示*/
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, 5, 6];
const arr2: IArr2 = [1, 2, '3', '4', { a: 1 }];
const arr3: IArr3 = [1, 2, '3', '4'];
const arr4: IArr4 = ['string', () => null, {}, []];

TypeScript 补充类型

/* 空类型,表示无赋值 */
type IEmptyFunction = () => void;
/* 任意类型,是所有类型的子类型 */
type IAnyType = any; 
/* 枚举类型: 支持枚举值到枚举名的正、反向映射 */
enum EnumExample {
  add = '+',
  mult = '*',
}
EnumExample['add'] === '+' ;
EnumExample['+'] === 'add' ;
​
enum ECorlor { Mon, Tue, Wed, Thu, Fri, Sat, Sun };
ECorlor['Mon'] === 0;
ECorlor [0] === 'Mon';
​
/* 范型 */
type INumArr = Array<number>;

TypeScript 范型

function getRepeatArr(target) {
  return new Array (100). fill(target);
}
​
type IGetRepeatArr = (target: any) => any[];
​
/* 不预先指定具体的类型,而在使用的时候再指定类型的一种特性 */
type IGetRepeatArrR = <T>(target: T) => T[];
/* 泛型约束:限制泛型必须符合字符串 */
type IGetRepeatStringArr = <T extends string>(target: T) => T[];
const getStrArr: IGetRepeatStringArr = target => new Array(100).fill(target);
/* 报错:类型"number"的参数不能赋给类型"string"的参数 */
getStrArr(123);
​
/* 泛型参数默认类型 */
type IGetRepeatArr<T = number> = (target: T) => T[];
const getRepeatArr: IGetRepeatArr = target => new Array(100).fill(target);
/* 报错: 类型"string"的参数不能赋给类型"number"的参数 */
getRepeatArr('123');

类型别名 & 类型断言

/*通过type关键字定义了IObjArr的别名类型*/
type IObjArr = Array<{
  key: string;
  [objKey: string]: any;
}>
​
function keyBy<T extends I0bjArr>(objArr: Array<T>) {
  /*未指定类型时,result类型为 {} */
  const result = objArr. reduce((res, val, key) => 
    res [key] = val;
    return res;
  }, []);
​
  /* 通过as关键字,断言result类型为正确类型 */ 
  return result as Record<string, T>;
}

字符串/数字 字面量

/*允许指定字符串/数字必须的固定值*/
​
/* IDomTag必须为html、 body、 div、 span中的其一 */ 
type IDomTag = 'html' | 'body' | 'div' | ' span';
/* IOddNumber必须为1、3、5、7、9中的其一 */
type IOddNumber = 1 | 3 | 5 | 7 | 9;

高级类型

联合/交叉类型

联合类型: IA | IB; 联合类型表示一个值可以是几种类型之一
交叉类型: IA & IB; 多种类型叠加到一起成为种类型,它包含了所需的所有类型的特性
type IBookList = Array<{
  author: string;
} & ({
  type: 'history';
  range: string;
} | {
  type: 'story';
  theme: string;
})>

举例子:

const bookL ist = [{
  author: 'xiaoming',
  type: 'history',
  range: '2001-2021', 
}, {
  author: 'xiaoli',
  type: 'story',
  theme: 'love',
}]

类型保护与类型守卫

类型保护

interface IA { a: 1, a1: 2 }
interface IB { b: 1, b1: 2 }
​
function log(arg: IA | IB) {
  /* 报错: 类型"IA |IB"上不存在属性"a"。类型"IB"上不存在属性"a" */
  /* 结论: 访问联合类型时,处于程序安全,仅能访问联合类型中的交集部分 */
  if (arg.a) {
    console.log(arg.a1);
  } else {
    console.log(arg.b1);
  }
}

类型守卫

interface IA { a:1, a1:2 }
interface IB { b:1, b1:2 }
​
/* 类型守卫: 定义一个函数, 它的返回值是一个类型谓词, 生效范围为子作用域 */
function getIsIA(arg: IA | IB): arg is IA {
  return !!(arg as IA).a;
}
​
function log2(arg: IA | IB) {
  if (getIsIA(arg)) {
    console.log(arg.a1);
  } else {
    console.log(arg.b1);
  }
}