第二十四章 TypeScript类型守卫

类型守卫

在 TypeScript 中,类型守卫(Type Guards)是一种用于在运行时检查类型的机制。它们允许你在代码中执行特定的检查,以确定变量的类型,并在需要时执行相应的操作。

1.typeof 类型收缩
const isString = (str:any) => {
   return typeof str === 'string';
}

在这个例子里面我们声明一个函数可以接受任意类型,只筛选出字符串类型,进行类型收缩2

2.instanceof
const isArr = (value:unknown) => {
    if(value instanceof Array){
        value.length
    }
}

使用 instanceof 类型守卫可以检查一个对象是否是特定类的实例

typeof 和 instanceof 区别

typeof 和 instanceof 是 TypeScript 中用于类型检查的两个不同的操作符,它们有不同的作用和使用场景。

1.typeof 和 instanceof 是 TypeScript 中用于类型检查的两个不同的操作符,它们有不同的作用和使用场景。
const str = "Hello";
console.log(typeof str); // 输出: "string"

const num = 42;
console.log(typeof num); // 输出: "number"

const bool = true;
console.log(typeof bool); // 输出: "boolean"

注意事项:typeof 只能返回有限的字符串类型,包括 “string”、“number”、“boolean”、“symbol”、“undefined” 和 “object”。对于函数、数组、null 等类型,typeof 也会返回 “object”。因此,typeof 对于复杂类型和自定义类型的判断是有限的。

2.instanceof
作用:instanceof 操作符用于检查一个对象是否是某个类的实例。它通过检查对象的原型链来确定对象是否由指定的类创建。
class Person {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

const person = new Person("Alice");
console.log(person instanceof Person); // 输出: true

const obj = {};
console.log(obj instanceof Person); // 输出: false

注意事项:instanceof 操作符主要用于检查对象是否是特定类的实例,它无法检查基本类型。此外,它也无法检查对象是通过字面量创建的,因为字面量对象没有显式的构造函数。

自定义守卫

结合题目实现

实现一个函数支持任意类型
如果是对象,就检查里面的属性,
如果里面的属性是number就取两位,如果是string就去除左右空格
如果是函数就执行

const isString = (str:any)=> typeof str === 'string'

const isNumber = (num:any)=> typeof num === 'number'

const isFn = (fn:any)=> typeof fn === 'function'

const isObj = (obj:any)=> ({}).toString.call(obj) === '[object Object]'

const fn = (data:any) => {
    let value;
    if(isObj(data)){
        Object.keys(data).forEach(key=>{
            value = data[key]
            if(isString(value)){
                data[key] = value.trim()
            }
            if(isNumber(value)){
                data[key] = value.toFixed(2)
            }
            if(isFn(value)){
                value()
            }
        })
    }
}
const obj = {
    a: 100.22222,
    b: ' test  ',
    c: function () {
        console.log(this.a);
        return this.a;
    }
}

fn(obj)

一看没啥问题 一运行就报错

他说找不到a 

当函数被单独调用时(例如 value()),函数内部的 this 会指向全局对象(在浏览器环境下是 window)

修改如下

const isString = (str:any)=> typeof str === 'string'

const isNumber = (num:any)=> typeof num === 'number'

const isFn = (fn:any)=> typeof fn === 'function'

const isObj = (obj:any)=> ({}).toString.call(obj) === '[object Object]'

const fn = (data:any) => {
    let value;
    if(isObj(data)){
        Object.keys(data).forEach(key=>{
            value = data[key]
            if(isString(value)){
                data[key] = value.trim()
            }
            if(isNumber(value)){
                data[key] = value.toFixed(2)
            }
            if(isFn(value)){
                data[key]() //修改这儿
            }
        })
    }
}
const obj = {
    a: 100.22222,
    b: ' test  ',
    c: function () {
        console.log(this);
        return this.a;
    }
}

fn(obj)

第一个问题解决了

第二个问题是我们编写的时候没有代码提示很烦

这时候就需要自定义守卫了

类型谓词的语法形式。它表示当 isString 返回 true 时,str 的类型被细化为 string 类型

// 类型守卫

// 1.类型收缩  | 类型收窄

// typeof 是有缺陷的 比如说数组 对象 函数 null他都返回的是object
// const isString = (str: any) => typeof str === 'string'
// const isArr = (arr: any) => arr instanceof Array


// 2.类型谓词 | 自定义守卫
// 实现一个函数,该函数可以传入任何类型
// 但是如果在object 就检查里面的属性,如果里面的属性是number 就去两位
// 如果是string就去除左右空格
// 如果是函数就执行
// 1.发现没有任何代码提示  原因是any类型
// 自定义守卫 他只能接受布尔值
// 语法规则 参数 is 类型
// 这个函数如果返回true 那么这个参数就是你想要的类型
// 2.properties of undefined (reading 'a')
// nodejs 环境this 成了 undefined
// 浏览器环境this成了window
// js基础知识 如果函数独立调用那么this 就是window

const isObj = (arg: any) => ({}).toString.call(arg) === '[object Object]';
const isNum = (num: any): num is number => typeof num === 'number'; // 如果返回true ,就是我们想要的类型
const isStr = (str: any): str is string => typeof str === 'string'
const isArr = (arr: any) => arr instanceof Array
const isFn = (fn: any): fn is Function => typeof fn === 'function'

const fn = (data: any) => {
	if (isObj(data)) {
		let val
		//遍历属性不能用for in 因为for in 会遍历 原型上的属性
		Object.keys(data).forEach((key) => {
			val = data[key]
			if (isNum(val)) {
				data[key] = val.toFixed(2)
			}
			if (isStr(val)) {
				data[key] = val.trim()
			}
			if (isFn(val)) {
				data[key].val()
			}
		})
		
	}
}

const obj = {
	a: 100.22222,
	b: ' test  ',
	c: function () {
		console.log(this);
		return this.a;
	}
}
fn(obj)

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值