【进阶】TS 中的 类型断言 和 泛型

news2025/1/23 12:12:29

类型断言

作用 : 手动指定值的具体类型 ( 缩写值的范围 )

应用场景 1

获取 DOM 元素的时候指定具体元素

示例 :

const box = document.getElementById('img')
console.log(box.src) // ts报错

错误内容 :
在这里插入图片描述

解析 :
上述语法在 js 中可以直接使用, 但是 TS 中就不行啦, 由于类型不明确会报错

  • 返回值的类型是 HTMLElement,只有标签公共的属性,不包含 imgsrc 属性

解决方法 : 使用类型断言明确具体类型

语法 : let 变量 = 值 as 类型

  • as 关键字实现类型断言
  • 关键字 as 后面的类型是一个具体的类型

实例 :

  • const box = document.getElementById('img') as HTMLImageElement
  • 指定了具体类型后 , 就可以使用 box.src

技巧: 获取 DOM 元素类型的方法

  • 在浏览器控制台,通过 __proto__ 获取 DOM 元素的类型;
  • document.createElement('a'),然后看代码提示、

在这里插入图片描述

应用场景 2

知道获取数据的类型, 但是不知道具体的数据时 , 使用类型断言后就会有提示

type User = {
  name: string,
  age: number
}

const u1 = {} as User

console.log(u1.name) // 这里就会有提示

非空断言

作用 :
明确地知道对象的属性一定不会为空,可以使用非空断言 !

应用场景 : TS 中 使用 useRef()

在这里插入图片描述

JS 中的语法直接使用会报错

错误解析 :

  • useRef 类型说明 : useRef的泛型参数用于指定current属性的值的类型
    在这里插入图片描述

  • 传入参数 null 时 , current属性的值类型也被指定为 null
    在这里插入图片描述

解决方法 :

  • 指定 useRef的泛型参数类型为 HTMLInputElement (已知类型)
  • 使用非空断言! 指定current属性的值不为空
function App() {
  const inputRef = useRef<HTMLInputElement>(null)
  return (
    <div className="App">
      <input type="text" ref={inputRef} />
      <button onClick={() => {
        console.log(inputRef.current!.value)
      }}>点击</button>
    </div>)
}

typeof

TS 中的 typeof 操作符 和 js 中的一样都是用来获取变量或属性类型

使用方法 :

获取类型 : type 变量 = typeof 常量

使用 : function(参数:变量){参数.常量的方法}

应用场景

获取到一个复杂的对象,我们把它当做实参传给一个函数fn,但是没有办法在使用形参时获取提示信息

typeof 解决

const res = { name: '小花', city: '武汉',  skills: ['js', 'css'] }

type Stu = typeof res

function fn(obj:Stu) {
    // 这里写 obj. 就会有提示
    obj.skills
}

fn(res)

在这里插入图片描述

注意 : typeof 只能用来查询变量或属性的类型,无法查询其他形式的类型(比如,函数调用的类型)

keyof

获取对象类型的属性名 , 得到新的类型

  • type 类型 = keyof 类型
    • 实例
      • type Point = { x: number; y: number }
      • type P = keyof Point
  • type 类型 = keyof 对象常量
    • type T = keyof {a:1,b:2}

使用方法

获取类型的属性名 :

  • type T = keyof {a:1,b:2}== type T = 'a'|'b'

使用 : let 变量:T = 'a'

  • 变量的取值只能是 ‘a’或者’b’
    在这里插入图片描述

泛型

什么是泛型

顾名思义就是多个类型 , TS 中指使用变量保存要使用的类型

泛型本质

泛型本质是参数化类型 , 就是所操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和函数的创建中,分别成为泛型类泛型接口泛型函数

泛型函数

什么是泛型函数 :

这个函数的参数类型或者返回值的类型是可变的

定义泛型函数 :

function 函数名<类型参数> (形参:类型参数):类型参数{}

  • 在函数名称的后面写 <>(尖括号),尖括号中添加类型变量
  • 类型变量相当于一个类型容器,能够捕获用户提供的类型(具体是什么类型由用户调用该函数时指定)

使用泛型函数

  • 方法1: const 返回值 = 函数名(实参) 类型推论实参的类型,传递给类型参数
  • 方法2 : const 返回值= 函数名<类型实参>(实参) 上述的非空断言就使用了此种方法
    • 此时的 <> 中的就是具体的类型

示例

 // 泛型函数
    function useState<T>(val: T | (() => T)): [T | (() => T), (newvalue: T) => void]{
       return [val,(newvalue)=>{val=newvalue}]
    } 
    const [str,setStr] = useState('1')
    const [num,setNum] = useState<number>(1)
    const [fn, setFn] = useState<number>(() => 1)

泛型推论

泛型推论就是, 利用类型推论简化函数调用

  • 在调用泛型函数时,可以省略 <类型> 来简化泛型函数的调用
  • 此时,TS 内部采用一种类型参数推断的机制,来根据传入的实参自动推断出类型变量 Type
    在这里插入图片描述

泛型对象

应用场景 :

函数中传入对象和该对象的属性,要求得到给对象的值

  // 泛型对象
    function getProp<T, K extends keyof T>(arr: T, key: K) {
        return arr[key]
    }
    let obj ={name:'ikun',age:18,hobby:'学习'}
    getProp(obj,'hobby')

解析 :

上述约定后, 后续调用时会有提示
在这里插入图片描述

泛型的问题

太灵活了

  • 默认情况下,泛型函数的类型变量 可以代表多个类型,这导致在泛型函数内部无法访问任何属性
function fn<T>(value: T): T {
  // 这里value. 不会有提示
  console.log(value.length)// 这里会报错
  return value
}

fn('a')

在这里插入图片描述

解决泛型太灵活的方法

为泛型添加约束来收缩类型(缩窄类型取值范围)

泛型约束

泛型约束主要有以下两种方式:

  • 指定更加具体的类型
  • 添加约束

指定更加具体的类型

指定更具体的类型缩小范围

function fn<T>(value: T[]): T[] {
  console.log(value.length) // 这里就可以获得提示
  return value
}

T[] 数组一定会有length属性

添加约束(推荐使用)

对已有类型做继承,已有类型中指定了 length属性

 interface ILength { length: number }
    function fn1<T extends ILength>(value: T): T {
        // 这里value. 不会有提示
        console.log(value.length)
        return value
    }

泛型接口

在接口中使用泛型来使用,以增加其灵活性,增强其复用性

语法 :

interface 接口名<类型变量1,类型变量2...> {
  属性名1:类型1,
  属性名2:类型2,
  属性名3:类型3
}

注意 :

  • 在接口名称的后面添加 <类型变量>,那么,这个接口就变成了泛型接口。
  • 接口的类型变量,对接口中所有其他成员可见,也就是接口中所有成员都可以使用类型变量
  • 使用泛型接口时,需要显式指定具体的类型

实例:

interface MyArray {
  length: number,
  push(n: number):void,
  pop():number,
  reverse():number[]
}

let obj: MyArray = {
  id(value) { return value },
  ids() { return [1, 3, 5] }
}

数组在ts中就是一个泛型接口
在这里插入图片描述

泛型工具类型

Partial

把已有的类型属性,变成一个新类型的可选属性

语法 : type 新类型 = partial<老类型>

Readonly

把已有类型全部转换为只读类型

语法和上述一直

定义对象使其内在属性不能修改

Pick

从已有类型中选一些属性来构造新的类型

语法 : type 新类型 = partial<老类型,属性|属性2>

详见代码

代码地址: github.com/jiang-zi/TS…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/408193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vue 动态样式绑定 class/style

简介&#xff1a; 字符串写法&#xff1a;类名不确定&#xff0c;要动态获取 对象写法&#xff1a;要绑定多个样式&#xff0c;个数确定&#xff0c;名字确定&#xff0c;但不确定用不用。 数组写法&#xff1a;要绑定多个样式&#xff0c;个数不确定&#xff0c;名字不确定。…

HTML基础 - HTML表格

HTML基础 - HTML表格 1.无表头的表格 <table> <tr> <td> <table>标签代表的是表 <tr>标签代表的是行 <td>标签代表的是列 在html页面中的表格来着&#xff0c;就和excl的表格不一样喽&#xff0c;咱自己有自己的规则&#xff1a; 这就是…

这一次,彻底搞懂箭头函数

一、箭头函数的特点 1. 相比普通函数&#xff0c;箭头函数有更加简洁的语法。 普通函数 function add(num) {return num 10 }箭头函数 const add num > num 10;2. 箭头函数不绑定this&#xff0c;会捕获其所在上下文的this&#xff0c;作为自己的this。 这句话需要注意的…

若依(ruoyi)字典管理插件实现思路探究

一个UI表单的构成&#xff0c;避免不了下拉框&#xff0c;多选框等标签&#xff0c;在开发这些标签时&#xff0c;通常会请求后台接口获取字典值进行动态渲染。定制化开发虽然实现简单&#xff0c;但会产生大量重复工作&#xff0c;解决这类问题的思路有哪些&#xff1f;文章对…

chrome插件开发时跨域问题解决方案

这是一个没有套路的前端博主&#xff0c;热衷各种前端向的骚操作&#xff0c;经常想到哪就写到哪&#xff0c;如果有感兴趣的技术和前端效果可以留言&#xff5e;博主看到后会去代替大家踩坑的&#xff5e;接下来的几篇都是uni-app的小实战&#xff0c;有助于我们更好的去学习u…

Vue在HTML中如何使用

&#x1f440;Vue是什么 一套用于构建用户界面的渐进式JavaScript框架。 构建用户界面&#xff1a;数据变成界面渐进式&#xff1a;Vue可以自底向上逐层的应用&#x1f440;Vue如何使用 一、引入vue.js <script src"./js/vue.js"></script> 二、准备一个…

HBuilderX uni-app简单实现静态登录页面(实例)

本章用到......uni-app页面跳转uni.navigateTo方法、uni.navigateBack方法。uni-app简单实现邮箱验证码发送点击后读秒样式。登录账号、密码正则表达式验证等 适合刚入门的小伙伴&#xff0c;大佬就没必要看了 静态页面&#xff01;静态页面&#xff01;没有绑定后端数据接口…

拿来即用的前端登录页面(简洁清爽版)

1、使用bootstrap实现 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>登录</title><link rel"stylesheet" href"/bootstrap-3.3.7-dist/css/bootstrap.m…

vue项目根据不同环境动态配置接口请求ip及全局变量(vue环境变量配置)

在项目的开发过程中&#xff0c;我们常常会遇到根据不同的环境需要切换不同的ip的问题&#xff0c;例如在项目部署到测试服时需要将接口请求ip替换成测试服的ip,部署到正式服时又需要将接口请求ip替换成正式服对应的ip,有些公司还有预发环境等&#xff0c;这样在每次部署不同环…

Vue实战篇三十五:实现滑动拼图验证登录

系列文章目录 Vue基础篇一&#xff1a;编写第一个Vue程序 Vue基础篇二&#xff1a;Vue组件的核心概念 Vue基础篇三&#xff1a;Vue的计算属性与侦听器 Vue基础篇四&#xff1a;Vue的生命周期&#xff08;秒杀案例实战&#xff09; Vue基础篇五&#xff1a;Vue的指令 Vue基础篇…

Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.

一、问题在启动springcloud的gateway模块的时候报错Please set spring.main.web-application-typereactive or remove spring-boot-starter-web dependency.二、问题产生的原因gateway组件中的 spring-boot-starter-webflux 和 springboot作为web项目启动必不可少的 spring-boo…

前端如何将静态页面部署到服务器,并可以通过公网ip访问。

问题描述 作为卑微的前端页面仔。在我们公司项目上线的时候&#xff0c;一般都是我们前端 npm run build&#xff0c;然后直接把打出来的dist包丢给后端&#xff0c;后端上传到服务器完成前端的部署。这个时候我就很好奇&#xff0c;页面是怎么上传到服务器的呢&#xff1f;上…

vue使用pinia (vue2/vue3)

pinia是什么&#xff1f;Pinia 是 Vue.js 的轻量级状态管理库 官方网站&#xff1a;Pinia 中文文档: 介绍 | Pinia 中文文档 pinia与vuex4 相同 是vue 官方 状态管理工具(作者是 Vue 核心团队成员&#xff09;是vue开发者工具支持pinia 不同 pinia相比vuex4&#xff0c…

云E办Springboot+vue——前端项目完整版(含源码)

一、项目简介 项目背景&#xff1a;受疫情的影响&#xff0c;许多企业由线上办公转为线下办公。随着线上办公的人数的增多&#xff0c;线上办公的优点逐步凸显&#xff1a;通过实现工作流程的自动化、节省企业办公费用、实现绿色办公&#xff0c;同时提升办公效率。 项目介绍…

uniapp在小程序中登录,获取用户信息,获取手机号逻辑记录

这里写目录标题概述uniapp小程序的授权描述授权的详细说明及使用1、微信小程序通过uni.login()方法可以获取到微信提供的code2、通过登录获取的code码可以以获取用户唯一标识openid以及会话密钥sessionkey用于解密获取手机的加密信息3、通过微信提供的获取微信手机号的方法getp…

ELK企业级日志分析平台(二)

文章目录一、kibana数据可视化1.部署2.定制数据可视化&#xff08;1&#xff09;网站访问量&#xff08;2&#xff09;访问量排行榜&#xff08;3&#xff09;创建dashboard&#xff0c;大屏展示二、ES集群监控1.启用xpack认证2.metricbeat监控3.filebeat日志采集一、kibana数据…

【玩转CSS】一文带你了解浮动

&#x1f525;一个人走得远了&#xff0c;就会忘记自己为了什么而出发&#xff0c;希望你可以不忘初心&#xff0c;不要随波逐流&#xff0c;一直走下去&#x1f3b6; &#x1f98b; 欢迎关注&#x1f5b1;点赞&#x1f44d;收藏&#x1f31f;留言&#x1f43e; &#x1f984; …

牛客前端刷题(六)—— JS基础

还在担心面试不通过吗?给大家推荐一个超级好用的刷面试题神器:牛客网,里面涵盖了各个领域的面试题库,还有大厂真题哦! 赶快悄悄的努力起来吧,不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享,感觉有用的小伙伴可以点个订阅,不定时更新相关面试题:面试专栏…

前端面试中经常提到的LRU缓存策略详解

&#x1f431; 个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️ 作者简介&#xff1a;2022年度博客之星前端领域TOP 2&#xff0c;前端领域优质作者、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &am…

微信小程序解决view点击事件穿透地图map触发markertap

微信小程序中使用map组件&#xff0c;ios手机中点击地图上的view&#xff0c;会触发底下的markertap&#xff0c;只要底下如果有marker点的话。 这就造成了用户体验不是很好。 然后无意间我发现点击能滑动的scroll-view反而不会触发底下的markertap&#xff0c;就等于是一个不…