TypeScript 入门 | 青训营笔记

63 阅读4分钟

TypeScript 入门 | 青训营笔记

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

为什么选择TypeScript

image.png 静态类型:

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

JS的超集:

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

基本语法

基础数据类型

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

对象类型

image.png

  • 只读属性:约束属性不可在对象初始化外赋值

    readonly jobId: number

  • 可选属性:定义改属性可以不存在

    hobby?: string

  • 任意类型:约束所有对象属性都必须是该属性的子类型

    [key : string]: any

函数类型

js函数代码

function add(x, y) {
    return x + y;
}

转化为Ts:

  1. 方法一
    interface IAdd {
        (x:number, y:number): number
    }
    const add : IAdd = (x, y) => x + y;
    
  2. 方法二
    function add(x:number, y:number): number {
        return x + y;
    }
    // 箭头函数方式
    const add: (x:number, y:number) => number = (x,y) => x + y; 
    
    

数组类型

image.png

补充类型

空类型

// 函数中无返回值
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>

不预先指定具体的类型,而在使用的时候再指定类型

type IGerRepeatArr = <T>(target:T) => T[]
// 数字数组
IGerRepeatArr<Number> 
// 字符串数组
IGerRepeatArr<String>

泛型接口 & 多泛型

interface IX<T, U> {
    key:T;
    val:U;
}

泛型类

class IMan<T> {
    instance:T
}

泛型约束

extends可查看我另一平台上的文章

type IGetRepeatStringArr = <T extends string>(target:T) => T[]
const getStrArr : IGetRepeatStringArr = target => new Array(100).fill(target)

/* 报错:类型"number"的参数不能赋给"string"的参数 */
getStrArr(123)

泛型参数默认类型

type IGetRepeatStringArr = <T = number>(target: T) => T[];
const getStrArr: IGetRepeatStringArr = (target) => new Array(100).fill(target);
/* 报错:类型"string"的参数不能赋值给类型"number"的参数 */
getStrArr("123");

类型别名 & 类型断言

通过type关键字定义了IObjArr的类型别名,这样便于使用

type IObjArr = Array<{
    key: string;
    [objKey: string]: any;
}>

as类型断言

type Record<K extends string | number | symbol, T> = { [P in K]: T; }
function keyBy<T extends IObjArr>(objArr:T) {
  const result = objArr.reduce((pre,cur,curIndex) => {
    pre[curIndex] = cur;
    return pre
  },{})
  /* 通过as关键字,断言result类型为指定的类型 */
  return result as Record<string,T>
}

字符串/数字 字面量

允许指定字符串/数字必须的固定值,即必须为固定值之一

IDomTag必须是html、body、div、span中的其一
type IDomTag = 'html' | 'body' | 'div' | 'span'

高级类型

联合交叉类型

image.png

  • 联合类型:A | B ;联合类型表示一个值可以是几种类型之一
  • 交叉类型:A & B ;多个类型叠加到一起成为一种类型,它包含所需的所有类型的特性

image.png

但是如果类型出现了冲突,那么会变成never类型

interface IOne {
  author:string
}

interface ITwo {
  author:number
}

type Ires = IOne & ITwo

const obj : Ires = {
  // 不能将类型“string”分配给类型“never”
  author:'123'
}

类型保护与类型守卫

interface IOne {
  a:1,
  a1:2;
}

interface ITwo {
  b:1,
  b1:2
}

function log(arg: IOne | ITwo) {
  // 类型“IOne | ITwo”上不存在属性“a”。类型“ITwo”上不存在属性“a”。
  if(arg.a) {
    console.log(arg.a1)
  } else {
    console.log(arg.b1)
  }
}

结论:访问联合类型时,处于程序安全的考虑便,仅能访问联合类型中的交集部分

定义一个类型守卫:

/* 类型守卫:定义一个函数,它的返回值时一个类型谓词,生效范围为子作用域 */
function getIsTOne(arg: IOne | ITwo) : arg is IOne {
  // 必须return一个布尔值,用于判断是否是指定类型
  return !!(arg as IOne).a
}

function log(arg: IOne | ITwo) {
  if(getIsTOne(arg)) {
    console.log(arg.a1)
  } else {
    console.log(arg.b1)
  }
}

针对于类型不相同的参数,可以if判断中使用typeof等关键字来区分

function log(arg: string | number) {
  if(typeof arg === 'number') {
    console.log('number',arg)
  } else {
    console.log('string',arg)
  }
}

联合类型 + 类型保护 = 自动类型推断

function logBook(book:IBookItem) {
  if(book.type == 'history') {
    console.log(book.range)
  } else {
    console.log(book.theme)
  }
}

Merge 函数类型实现

/**
 * 实现merge函数类型
 * 要求sourceObj必须是targetObj的子集
 * 作用:sourceObj中的值覆盖targetObj中值
 */
function merge1(sourceObj, targetObj) {
  const result = {...sourceObj}
  for(let key in targetObj) {
    const itemVal = sourceObj[key]
    itemVal && (result[key] = itemVal)
  }
  return result
}

function merge2(sourceObj, targetObj) {
  return {...sourceObj, ... targetObj}
}

将其转化为TS版

image.png

函数返回值类型

image.png