TypeScript系列之-深度理解基本类型&画图讲解

JS的类型(8)null undefined string number boolean

bigint symbol

object(含 Array, Function,Date.....)

TS的类型(8+7): 以上所有,加上

void, never, enum, unknown, any

再加上自定义类型 type interface

上一节我们说到用集合的思路理解TS中的类型,下面就用一张图表示基础类型之间的关系:

any和unknown类型

  • any就是个开挂的(type any = noErrorType----但有些情况any也不能赋值)
  • unknown安全类型,使用 unknown 做任何事情都是不合法的(unknown是所有类型的联合类型--推荐使用)

const a:unknown = 1
const b = a as string
b.splict('')

function divide(param: unknown) {  return param / 2;} // Error
function divide(param: unknown) {  return param as number / 2;} //ok

never类型

never类型表示的是那些永不存在的值的类型(其实就是空集,用于类型推断)

type A =  string & number
const a:A  = //×

//类型推断
type B  = string | number
const a:B = ('hahah' as any);
if(typeof a ==== 'string'){
  a.splice('')
}else if(typeof a ==== 'number'){
  a.tofixed(2)
}else{
  a //  这里a就只能是never(要不然说不过去)
}

enum枚举

在任何项目开发中,我们都会遇到定义常量的情况,常量就是指不会被改变的值。

TS 中我们使用 const 来声明常量,但是有些取值是在一定范围内的一系列常量,比如一周有七天,比如方向分为上下左右四个方向。

这时就可以使用枚举(Enum)来定义。

数字枚举基本使用:

enum Direction {    Up,    Down,    Left,    Right}

枚举成员会被赋值为从 `0` 开始递增的数字
console.log(Direction.Up) //0    
console.log(Direction.Down) //1   
console.log(Direction.Left) //2   
console.log(Direction.Right) //3

枚举会对枚举值到枚举名进行反向映射
console.log(Direction[0]) // Up
console.log(Direction[1]) // Down
console.log(Direction[2]) // Left
console.log(Direction[3]) // Right

如果枚举第一个元素赋有初始值,就会从初始值开始递增
enum Direction {    Up = 6,    Down,    Left,    Right}
console.log(Direction.Up)    //6     
console.log(Direction.Down)  //7
console.log(Direction.Left)  //8 
console.log(Direction.Right) //9

结论:数字枚举有两个特点

  1. 数字递增
  2. 反向映射

反向映射的原理:

枚举是如何做到反向映射的呢,我们不妨来看一下被编译后的代码


var Direction;(function (Direction) {  
  Direction[Direction["Up"] = 6] = "Up";   
  Direction[Direction["Down"] = 7] = "Down";  
  Direction[Direction["Left"] = 8] = "Left"; 
  Direction[Direction["Right"] = 9] = "Right";
  })(Direction || (Direction = {}));

//主体代码是被包裹在一个自执行函数里,封装了自己独特的作用域。
Direction["Up"] = 6
//会将 Direction 这个对象的 Up 属性赋值为 6,JS 的赋值运算符返回的值是被赋予的值。
Direction["Up"] = 6 返回 6
执行 Direction[Direction["Up"] = 6] = "Up";
相当于执行Direction["Up"] = 6 =Direction[6] = "Up"

这样就实现了枚举的反向映射

手动赋值:

定义一个枚举来管理外卖状态,分别有已下单,配送中,已接收三个状态。

enum ItemStatus {    Buy = 1,    Send,    Receive}
console.log(ItemStatus['Buy'])      // 1
console.log(ItemStatus['Send'])     // 2
console.log(ItemStatus['Receive'])  // 3

//但有时候后端给你返回的数据状态是乱的,就需要我们手动赋值。
//比如后端说 Buy 是 100,Send 是 20,Receive 是 1,就可以这么写

enum ItemStatus {    Buy = 100,    Send = 20,    Receive = 1}
console.log(ItemStatus['Buy'])      // 100
console.log(ItemStatus['Send'])     // 20
console.log(ItemStatus['Receive'])  // 1

计算成员

枚举中的成员可以被计算,比如经典的使用位运算合并权限,可以这么写

enum FileAccess {  
Read    = 1 << 1,  
Write   = 1 << 2,  
ReadWrite  = Read | Write,
  }
console.log(FileAccess.Read)       // 2  -> 010
console.log(FileAccess.Write)  // 4   -> 100
console.log(FileAccess.ReadWrite)  // 6   -> 110


上面运用的示例:
Vue3 源码中的 patchFlags,用于标识节点更新的属性
// packages/shared/src/patchFlags.tsexport 
const enum PatchFlags { 
TEXT = 1, // 动态文本节点 
CLASS = 1 << 1,   // 动态 class 
STYLE = 1 << 2,    // 动态 style 
PROPS = 1 << 3,     // 动态属性 
FULL_PROPS = 1 << 4,   // 具有动态 key 属性,当 key 改变时,需要进行完整的 diff 比较 
HYDRATE_EVENTS = 1 << 5,     // 具有监听事件的节点 
STABLE_FRAGMENT = 1 << 6,    // 子节点顺序不会被改变的 fragment  
KEYED_FRAGMENT = 1 << 7,     // 带有 key 属或部分子节点有 key 的 fragment 
UNKEYED_FRAGMENT = 1 << 8,   // 子节点没有 key 的 fragment 
NEED_PATCH = 1 << 9,         // 非 props 的比较,比如 ref 或指令 
DYNAMIC_SLOTS = 1 << 10,     // 动态插槽 
DEV_ROOT_FRAGMENT = 1 << 11, // 仅供开发时使用,表示将注释放在模板根级别的片段 
HOISTED = -1,                // 静态节点 
BAIL = -2                    // diff 算法要退出优化模式
}

小结:枚举的意义在于,可以定义一些带名字的常量集合,清晰地表达意图和语义,更容易地理解代码和调试。数字枚举可以用,string和other少用(显得很赘)

void类型:

void类型与 any 类型相反,它表示没有任何类型。

function welcome(): void {    console.log('hello')}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值