1.首先需要具备TS的基础
附上链接:TS学习
这里也一并附上TS 官方文档地址:TS官方地址
2.项目学习视频,B站其他博主的视频
这里附上链接:React+TS+useReducer手手撕一个todoList
3.项目地址,可以直接clone到本地运行
注意:项目有点bug,点击复选框的时候有问题,欢迎指出问题并修正,谢谢!!
这里再附上我学习TS 的笔记:
### 一.TS基础概念
#### 1.什么是TS
a.对比原理
* 是JS的一个超集,在原有基础上,增加了
可选静态类型
基于类的面向对象编程
1.编写项目 - 更利于架构管理
2.自主检测 - 编译期间检测
3.类型检测 - 支持了动态和静态类型检测 => 本质存在类型检测
4.运行流程上 - 依赖编译
5.复杂特性 - 模块化 泛型 接口
#### 2.TS基础类型和写法
* boolean underfined null string number array
``` ts
let arr = ['a', 'b'];
// ts
let arr: string[] = ['a', 'b'];
```
* tuple - 元祖
```ts
let tupleType = [string, boolean]
tupleType = ['a', true]
```
* enum - 枚举
``` ts
// 数字类枚举 - 默认从0开始, 依次递增
enum Score {
BAD,
NG,
GOOD,
PREFECT
}
let score: Score = Score.BAD;
// 字符串类型
enum Score {
BAD = 'BAD',
NG = 'NG',
GOOD = 'GOOD',
PREFECT = 'PREFECT'
}
// 反向映射
enum Score {
BAD,
NG,
GOOD,
PREFECT
}
let scoreName = Score[0]; // 'BAD'
let scoreValue = Score['BAD'] // 0
// 异构 - 字符串 + 数字
enum Score {
A,
B,
C = 'C',
D = 'D',
E = 6,
F
}
// 面试题:手写实现一个异构枚举?
let Enum ;
(function(Enum){
Enum['A'] = 0;
Enum['B'] = 1;
Enum['C'] = 'C';
Enum['D'] = 'D';
Enum['E'] = 6;
Enum['F'] = 7;
Enum[0] = 'A';
Enum[1] = 'B';
Enum[6] = 'E';
Enum[7] = 'F';
})(Enum || (Enum = {}))
```
* any unknown void
``` ts
// any - 绕过所有检查 => 类型检查和编译筛查全部失效
let anyValue: any = 123;
anyValue = 'anyValue'
// unknown - 绕过赋值检查 => 禁止更改传递
// 传递
let unknownValue: unknown;
unknownValue= 'unknownValue';
let value1: unknown = unknownValue; // ok
let value: any = unknownValue; // ok
let value3: boolean = unknownValue; // 错误,禁止更改传递
// void - 声明函数的返回值
function voidFunction(): void {
// 没有返回值的函数
}
// never - 永不返回
function error(msg: string): never {
throw new Error(msg);
}
// 这种情况会使用never
function loop(): never {
while(true){}
}
```
* object | Object | {} - 对象
```ts
// object - 非原始类型
interface ObjectConstructor {
create(0: object | null): any;
}
const proto = {}
Object.create(proto);
// Object - 原型属性
// Object.prototype上属性
interface Object {
constructor: Function;
toString: string;
valueOf(): Object;
}
// {} 空对象 - 没有成员的对象 描述一个空值
const a = {} as A; // 作断言,否则以下代码报错
a.class = 'es';
a.age = 30;
```
### 二.接口 - interface
* 对行为的抽象,具体行为由类实现
```js
interface Class {
name: string;
time: number;
}
let course: Class = {
name: 'ts',
time: 2
}
// 只读
interface Class {
readonly name: string;
time: number;
}
// 任意
interface Class {
name: string;
time: number;
[PropName: string]: any;
}
// 面试题: 和js的引用不同
let arr: number[] = [1,2,3,4];
let ro: ReadonlyArray<number> = arr;
ro[0] = 12; // Error - 赋值
ro.push(5) // Error - 增加
ro.length = 100; // Error - 长度改写
arr = ro; // Error - 覆盖
```
### 三. 交叉类型
```ts
// 合并
interface A {x: D}
interface A {x: E}
interface C {x: F}
interface D {d: boolean}
interface E {e: string}
interface F {f: number}
type ABC = A & B & C;
let abc: ABC = {
x: {
d: false,
e: 'ts',
f: 5
}
}
// 合并冲突
interface A {
c: string;
d: string;
}
interface B {
c: number;
d: string;
}
type AB = A & B;
// 合并的关系是且 => C: never
```
#### 四. 断言 - 类型声明 | 转换
```ts
// 尖括号
let anyValue: any = 'ts';
let anyLength: number = (<string>anyValue).length; // 阶段性声明
// as 声明
let anyLength: number = (anyValue as string).length;
// 非空判断
type ClassTime = () => number;
const start = (classTime: ClassTime | underfined) => {
let num = classTime!(); // 确定一定不会为空
}
// 面试题
class tsClass: number | underfined = underfined;
cosnt course: number = tsClass!;
// 使用的意义 => 告知编译器,运行时下会被赋值
```
#### 五. 类型守卫
```ts
interface Teacher {
name: string;
courses:string[];
score: number;
}
interface Student {
name: string;
startTime: Date;
score: string;
}
type Class = Teacher | Student;
function startCourse(cls: Class) {
if('courses' in cls) {
// teacher的逻辑
}
if('startTime' in cls) {
// student的逻辑
}
}
function startCourse(cls: Class) {
if(cls instanceof Teacher) {
// teacher的逻辑
}
if(cls instanceof Student) {
// student的逻辑
}
}
function startCourse(name: string; score: string | number) {
if(type score === 'number') {
// teacher的逻辑
}
if(type score === 'string') {
// student的逻辑
}
}
```
### 六. TS进阶
#### 1. 泛型 - 重用
```ts
function startCalss<T, U>(name: T, score: U): T {
return name + class;
}
console.log(startClass<string, number>('yy', 5));
function startCalss<T, U>(name: T, score: U): string {
return `${name}${class}`;
}
function startCalss<T, U>(name: T, score: U): T {
return (name + String(score)) as any as T;
}
// T U K 键值 | V 值 | E节点
```
#### 2.装饰器 - decorator
```ts
function Yunyin(target: Function): void {
target.prototype.startClass = function(): vold{
// start逻辑
}
}
// 类装饰器
@Yunyin
class Course {
constructor() {
// 业务逻辑
}
}
// 属性装饰器
function nameWrapper(target: any, key: string) {
// 逻辑处理
Object.defineProperty(target, key, {
// 劫持
})
}
class Course {
constructor() {
// 业务逻辑
}
@nameWrapper
public name: string;
}
// 方法装饰器
```
#### 3. 原理解析
```ts
// 1. 源码梳理
let a: number = 2;
// 2. scanner扫描器扫描 => 识别内容范围生成数据流
[
"let": "keytword",
"a": "identifier",
"=": "assignment",
"2": "integer",
";": "eos" (end of statement)
]
// number
// 3. 解析器 parser 生成语法树 - AST抽象语法树
{
operation: "=",
left: {
keyword: 'var',
}
}
// 4. 绑定器 binder 主要职责 创建symbols
node.symbol
// 5. 检查器 - checker 检查TS语法错误 => 检查器中进行的
// 6. 发射器 emitter根据每个节点的检查结果产出node翻译成js
```