likes
comments
collection
share

「学习笔记」ts

作者站长头像
站长
· 阅读数 3

ts是js的超集,增加了类型, 用来进行类型检查类型提示(自动补全), 使写的代码更加健壮、安全

类型检查例子:

「学习笔记」ts

字面量联合类型提示,输入两个冒号就会提示有哪些值 「学习笔记」ts

函数类型提示,鼠标移动到函数变量上就会提示参数和返回值 「学习笔记」ts

类型推导,let与const区别,const声明的变量会自动推导为字面量类型 「学习笔记」ts

vscode中按下command按键,鼠标移动到上面可以看类型详情

ts中含有内置类型(dom、es2020、事件等tsconfig.json中lib参数),基础类型,高级类型,自定义类型,首字母大写的类型都是装箱类型(包装类)

一、ts中类型的级别

  1. top type(顶级类型)有any和unknown
  2. Object,object 对象类型 // object 非基础类型 //{},0bject 不采用,偶尔会使用 {} 表示对象上无任何属性。 可以将任何值赋予给{}或者 0bject
  3. Number、String、Bollean
  4. number、string、bollean
  5. 字面量类型:变量值1、‘字符串’、true等等,例如type Direction = 'up'|'down'|'left'|'right'
  6. (bottom type)never 其中低等级类型的变量,可以赋值给高等级类型变量,例如 let a1:Object = '1' let a2: boolean = true a1 = a2 但是高等级的变量赋值给低等级会报错

「学习笔记」ts

二、any与unknown相同与不同

any类型的变量可以接受任意类型的变量赋值,也可以赋值给任意类型变量,any类型的对象在没有某个属性的时候去获取是不会报错的

unknown类型的变量可以接受任意类型的变量赋值,但是unknown只能赋值给unknown和any类型的变量,unknown类型赋值为一个对象的话从对象里面取值会报错

let obj: unknown = {a:1}
obj.a // unknown没有办法读任何属性或方法

unknown类型比any更加严格, 当你要使用any的时候可以优先使用unknown类型

三、TS中的特殊字符(?, !)

1、?可选操作符(js语法),属性或参数中使用 ?:——表示该属性或参数为可选项, 如果遇到 null 或 undefined 就可以立即停止某些表达式的运行 可选链 a?.b

2、!非空断言符号(ts语法), 变量后使用 !:——表示类型推断排除null、undefined

a!.toString()表示变量a一定有toString方法

3、?? 空值合并运算符(js语法), 当左侧操作数为 null 或 undefined 时,其返回右侧的操作数,否则返回左侧的操作数。

false ?? 2 // false
null ?? 2 // 2

Js的逻辑或 || 运算符: 运作规则:逻辑或会在左操作数为 false 值时返回右侧操作数。

false || 2 // 2
null || 2 // 2

四、tsconfig.json中的include和exclude使用

include作用:指定需要编译处理的文件列表,支持 glob 模式匹配,文件的解析路径相对于当前项目的 tsconfig.json 文件位置 exclude作用:用于指定当解析 include 选项时,需要忽略的文件列表, 任何被 files 或 include 指定的文件所引用的文件也会被包含进来,A.ts 引用了 B.ts,因此 B.ts 不能被排除,除非引用它的 A.ts 在 exclude 列表中。tsconfig之include和exclude详解

五、type与interface的不同

type有联合类型,有交叉类型(联合类型满足其中一个类型就可以,交叉类型必须同时满足多个类型)

interface可以通过extends继承

六、never类型用法

// 永远没返回值
function F1():never {
    while(true) {
    }
}

// 报错情况
function F2():never {
    throw new Error('报错了')
}

完整性保护,保障程序不缺失,如下当value新增一个类型的时候,如果不多写一个case,兜底逻辑会报错

「学习笔记」ts

「学习笔记」ts

「学习笔记」ts

//空对象
type EmptyObject = Record<string, never>

七、Record的用法

`Record<string, never>` 空对象  
`Record<string, unknown> `任意对象  
`{}` 任何不为空的对象

Record源码解读

type Record<K extends keyof any, T> = {
    [P in K]: T;
};

type K1 = keyof any // string | number | symbol
type K2 = PropertyKey // string | number | symbol
type Record1<K extends string | number | symbol,T> = {
    [p in K]: T
}

八、infer的使用

type R = T extends U ? X : Y

如果占位符类型U是一个可以被分解成几个部分的类型,譬如数组类型,元组类型,函数类型,字符串字面量类型等。这时候可以通过infer来获取U类型中某个部分的类型。 infer语法的限制如下:

  1. infer只能在条件类型的 extends 子句中使用
  2. infer得到的类型只能在true语句中使用, 即X中使用 参考地址
type A = ['a', 'b', 'c']
type B1<T> = T extends any[] ? T[number] : never
type B2<T> = T extends Array<infer U> ? U : never
// 取第一个
type B3<T> = T extends [infer one, ...any] ? one : never
// 取第二个
type B5<T> = T extends [infer one, infer two, ...any] ?  two: never
// 取剩余的
type B6<T> = T extends [infer one, ...infer rest] ?  rest : never

type Test = B1<A> // type Test = "a" | "b" | "c"
type Test2 = B2<A> // type Test2 = "a" | "b" | "c"
type Test3 = B3<A> // type Test3 = "a"
type Test5 = B5<A> // type Test5 = "b"
type Test6 = B6<A> // type Test6 = ["b", "c"]

九、import type与import

TypeScript 3.8 - Type-Only Imports and Export纯类型导入和导出 import type only imports declarations to be used for type annotations and declarations. It always gets fully erased, so there’s no remnant of it at runtime. Similarly, export type only provides an export that can be used for type contexts, and is also erased from TypeScript’s output. import type只导入用于类型注释和声明的声明。 它总是被完全擦除,所以在运行时不会有残留。 类似地,export type只提供一个可用于类型上下文的导出,并且也会从TypeScript的输出中删除。

import 引入的在编译时和运行时都会存在

十、怎么把对象的key值数组转为联合类型,使用keyof

const A = {
  1: "类型1",
  2: "类型2",
  3: "类型3",
  4: "类型4"
}
type B = keyof typeof A // type B = 1 | 2 | 3 | 4

十一、元组转联合类型

export const dictType = [
    'area',
    'trade',
    'status',
] as const; // 'const' 断言只能作用于枚举成员、字符串、数字、布尔值、数组或对象字面量。
export const dictType1 = [
    'area',
    'trade',
    'status',
];
type Tp = typeof dictType // readonly ["area", "trade", "status"]
type Tp1 = typeof dictType1 // string[]
type Tarr = ['str1', 'str2', 'str3']
export type TKeyDictType = (Tarr)[number] // type TKeyDictType = "str1" | "str2" | "str3"

十二、dom类型

let canvas: HTMLCanvasElement = document.querySelector('canvas')!
let ctx = canvas.getContext('2d') // HTMLCanvasElement类型有getContext属性

let canvas: HTMLElement = document.querySelector('canvas')!

### 十五、赋值表达式的左侧不能是可选属性访问

十六、怎么给interface增加一个属性?

利用继承

interface Type1 {
  a: number
}
// 新建一个类型
interface Type2 extends {
  b: number
}

十七、TypeScript 中,把对象的所有键/值变成一个联合类型 Union Type

要把一个对象的所有键、值组合成一个联合类型,需要三步骤:

    • 定义一个只读对象
    • 使用 keyof typeof 得到对象的所有键类型
    • 使用键去得到联合类型
// 👇️ const obj: {readonly name: "Tom"; readonly country: "Chile";}
const obj = {
  name: 'Tom',
  country: 'Chile',
} as const;

// 👇️ type UValues = "Tom" | "Chile"
type UValues = typeof obj[keyof typeof obj];

// 👇️ type UKeys = "name" | "country"
type UKeys = keyof typeof obj;

这里是利用 const 断言,它会尽量将类型特定化 当然,你只要保持这个对象只读就可以,因此可以用其他方式,比如:

interface O {
  readonly name: string;
  readonly country: string;
}

const obj: O = {
  name: 'Tom',
  country: 'Chile',
};

为什么必须是只读的,主要是防止对象在中途被篡改,那么得到的联合类型就不准确,因此 TypeScript 才加上如此限制 原文链接

十八、使用Object类型报错

  • If you want a type meaning "any object", you probably want object instead.
  • If you want a type meaning "any value", you probably want unknown instead.
  • If you really want a type meaning "any non-nullish value", you probably want NonNullable<unknown> instead.eslint@typescript-eslint/ban-types

十九、tuple元组类型

元组就是长度和类型固定的数组

二十、void类型

代表函数的返回值为空,只在函数中使用

二十一、联合类型

联合类型可以做到属性的互斥 type Person = { men: true, muscle: string // 肌肉 } | { men: false, makeup: string // 化妆 } let p: Person 当给p赋值时men为true时只能添加muscle属性,当men为false时只能添加makeup属性

二十二、断言as与非空断言!

非空断言是!,例如a!.b()断言变量a上一定有b方法 as可以把类型断言成已经存在的某个类型,例如type A = string | boolean; A as string 双重断言(变基),可以把一个值断言成any,然后再断言成某个类型,例如type A = string | boolean; A as any as number

学习

# TS 里几个常用的内置工具类型(Record、Partial 、 Required 、 Readonly、 Pick 、 Exclude 、 Extract 、 Omit)的使用