前端基础:TypeScript

335 阅读4分钟

1.type 和interface的区别

定义语法不同:type也可以用来定义接口的数据结构,跟interface的语法不同

type Props = {};
interface Props {}

类型范围不同:interface一般表示object,class,function类型。type可以复杂类型(例如联合类型等)如下:

type JSXElementConstructor<P> =
        | ((props: P) => ReactElement | null)
        | (new (props: P) => Component<P, any>);

// 当你想要获取一个变量的类型时,可以使用typeof
let div = document.createElement('div');
type B = typeof div;

重名规范不同:interface定义接口允许重名,type不允许。interface重复定义的接口(包括class)会自动聚合。

interface Props {
	x: string;
}
interface Props {
	y: number;
}
// 两者会自动聚合为
interface Props {
	x: string;
	y: number;
}

继承语法不同:两者都可以继承,语法不同

interface IPoint {
	x: number;
}
type Point = {
	x: number;
}

// 接口继承接口
interface Point2 extends IPoint {
	y: number;
}
// 接口继承type
interface Point2 extends Point {
	y: number;
}
//type继承接口
type Point2 = IPoint & {y: number;}
//type继承type
type Point2 = Point & {y: nummber}

2.高级类型

高级类型:
交叉类型: a&b
联合类型: string | number
索引类型:k extends keyof t
映射类型: in keyof 

Partial 把所有的属性变成可选的

定义:

type Partial<T> = {
  [P in keyof T]?: T[P]
}

用法:

Required 所有的属性变成必填

定义:

type Required<T> = {
    [P in keyof T]-?:T[P]
}

用法:

Readonly 所有的属性变成只读不可更改

定义:

type Readonly<T> = {
    readonly [P in keyof T]: T[P]
}

用法:

Pick 从T中取出K中有的属性

定义:

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

用法:

Record 把k中的属性转成T类型

定义:

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

用法:

Exclude, Extract

定义:

// 提取T中不包含在U中的属性
// 如果T能赋值给U,返回never类型,最终会将T中属于U的属性移除
type Exclude<T, U> = T extends U ? never : T;
// 提取T中包含在U中的属性
type Extract<T, U> = T extends U ? T : never;

Omit 忽略T中存在在K中的属性

定义:

type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>

3.typeScript是什么

typeScript是微软开发的一款开源的编程语言,它是JavaScript的一个超集,本质上是为JavaScript增加了静态类型声明。

TypeScript相比于JavaScript具有以下优点:

  • 更好的可维护性和可读性
  • 引入了静态烈性声明,不需要太多的注释和文档,大部分的函数看类型定义就知道如何使用了
  • 在解释阶段就能发现大部分因为变量类型导致的错误

4.typeScript的类型

  1. number:任意数字,let a:number
  2. string:任意字符串,let a:string
  3. boolean:布尔值true/false,let a:boolean
  4. 字面量:值本身,限制变量的值就是该字面量的值,let a:10,类似const,值只能是10
  5. any:任意类型,会导致其他的变量也不会检测
  6. unknown:任意类型,不会导致其他变量的检测,可以使用断言将unknown类型的值赋值给其他已知类型的变量
  7. void:空值(undefined)用于函数的返回值
  8. never:没有值,不能是任何值,一般用户错误处理函数的返回值类型定义
  9. object:任意的JS对象
  10. array:任意JS数组,let a:Array; let b: string[];
  11. tuple(元组):已知元素数量和类型的固定长度的数组
  12. enum(枚举)

枚举

使用枚举可以定义一些有名字的数字常量,枚举类型会被编译成一个双向映射的对象。枚举成员会被赋值为从0开始递增的数字,同时,也会被枚举值到枚举名进行反向映射。

使用枚举可以解决的问题

  • 可读性差:很难记住数字的含义
  • 可维护差:硬编码,牵一发动全身

注意事项

  1. 字符串枚举是不可以做双向映射的
  2. 异构枚举,把数字和字符串枚举混用,不推荐使用,会造成混乱
  3. 枚举成员的值不可修改

常量枚举:const enum

常量枚举回在编译阶段被移除

当我们不需要一个对象,而需要对象的值,就可以使用常量枚举,这样就可以避免在编译时生成多余的代码和简介引用

  1. 没有设置初始值
  2. 对已有枚举成员的引用
  3. 常量的表达式

需要计算的枚举成员

这些枚举成员的值不会在编译阶段计算,而是保留到程序的执行阶段

enum Char {
    a,
    b= 1+2,
    d = Math.random()
}

"use strict";
var Direction;
(function (Direction) {
    Direction[Direction["Up"] = 1] = "Up";
    Direction[Direction["Down"] = 2] = "Down";
    Direction[Direction["Left"] = 3] = "Left";
    Direction[Direction["Right"] = 4] = "Right";
})(Direction || (Direction = {}));

5.运算符

借鉴地址

1. extends 泛型约束

2. keyof 返回接口的所有key的联合类型

3. extends ? xxx:sss. 条件判断

4. is 运算符 限定返回类型

5. in 运算符 会for循环出联合类型