【TypeScript】进阶之路语法细节,类型和函数

进阶之路

      • 类型别名(type)的使用
      • 接口(interface)的声明的使用
        • 二者区别:
      • 联合类型和交叉类型
        • 联合类型
        • 交叉类型
      • 类型断言
          • 获取DOM元素
      • 非空类型断言
      • 字面量类型的使用
      • 类型缩小(类型收窄)
      • TypeScript 函数类型
          • 函数类型表达式
          • 内部规则检测
          • 函数的调用签名
          • 如何选择他们?
        • 参数的可选类型
        • 参数的默认值
        • 剩余参数
      • 函数重载
      • 函数重载-联合类型(优先使用)

类型别名(type)的使用

  • 为解决给联合类型的类型定义过长的问题
  • 使用类型别名
// 使用关键字type定义类型别名对象,可以复用
type myname = number | string
function hander1(name: myname) {
    console.log(name)
    if (typeof name === 'string') {
        console.log(name.length)
    }
}
//不使用类型别名
function hander2(x: number,y:number,z?:number) {
}
//使用类型别名
type myx={x: number,y:number,z?:number}
function hander3(mytype:myx) {
}

接口(interface)的声明的使用

  • 关键字使用interface声明
  • 相比较类型别名,少了=
//接口interface,没有=号
interface myX2 {
    x: number 
    y: number 
    z?: number
}
//使用接口声明
function hander4(mytype: myX2) {
}

二者区别:

  • 类型别名和接口声明非常相似,在定义对象的时候,可以任意选择使用
  • 主要区别:
  • type类型使用范围更广
  • type定义的是别名,不允许两个相同名称的别名使用
type myname = number | string
  • 1,接口类型只能用来声明对象
  • 2,接口类型声明对象的时候可以多次声明
  • 3,接口类型支持继承
  • 4,接口类型支持被类实现
//接口interface,没有=号,可以多次声明
interface myX2 {
    x: number 
    y: number 
}
//接口interface,没有=号
interface myX2 {
    z?: number
}
//使用接口声明
function hander4(mytype: myX2) {
}




//接口interface,支持继承
interface myX2 {
    x: number 
    y: number 
}
interface myX3 extends myX2 {
    z?: number
}
function hander5(mytype: myX3) {
    console.log(mytype.x,mytype.y,mytype.z)
}
hander5({x:1,y:2,z:3})

联合类型和交叉类型

联合类型

  • ts允许我们使用多种运算符,从现有类型中构建新类型
  • 联合类型由两个或多个类型组成的类型
  • 表示可以是这些类型中的任何一个值
  • 联合类型中的每一个类型被称为联合成员
// 联合类型
function hander(name: number | string) {
    console.log(name)
}
hander(1)
hander("123")

//联合类型
let nainfo: number | string = "abc"
nainfo = 1
nainfo = "123"

//但联合类型要使用的时候,要注意类型缩小,类似
// 联合类型
function hander1(name: number | string) {
    console.log(name)
    if (typeof name === 'string') {
        console.log(name.length)
    }
}
hander1(1)
hander1("123")

  • 注意:
  • 在拿联合类型的值之后,因为它可能是任何一种类型,如何使用呢?
  • 类似拿到的是number,就不能使用string的一些方法
  • 解决:
  • 需要使用缩小集合,也就是类型缩小,根据缩小的代码,推断出更加具体的类型

交叉类型

  • 交叉类型表示需要满足多个类型的条件
  • 交叉类型使用&符号
//交叉类型,两种或者多种类型同时满足
type myY = number & string//想同时满足数值和字符串类型,不可能,估没有意义
type myY2 = number & string

interface myX2 {
    x: number
    y: number
}
interface myX3 {
    z?: number
    p: () => void
}
//表示即满足myX2也得满足myX3,否则里面会有报错提示
const info: myX2 & myX3 = {
    x: 1,
    y:2,
    p:()=>{
        console.log("方法")
    }
}

类型断言

  • 有时候ts无法获取具体额度类型信息,这个时候需要使用类型断言
  • ts只允许类型断言转换为更具体的或者不太具体的类型版本,此规则可防止不可能的强制转换
获取DOM元素

在这里插入图片描述

// <img class="img">。使用类型缩小使用,只知道会返回html类型,但不知道具体类型
const imgE1 = document.querySelector("img")
// imgE1.src = "",会报错
if (imgE1 != null) {
    imgE1.src = ""
}
// <img class="img">。此时imgE2为element,不能直接使用,使用类型断言
//当你确信他存在且为html时,直接使用类型断言为更具体的样子,
const imgE2 = document.querySelector(".img") as HTMLImageElement
imgE2.src = ""

在这里插入图片描述

  • 类似,这样。类型断言成不太具体的样子
const num = 12
const num2 =num as any
  • 也可以继续,将不太具体的类型类型断言成更具体的样子
  • 但不支持这样来回断言,有安全隐患
const num = 12
const num2 =num as any
const num3 =num2 as string

非空类型断言

  • 当传入的值有可能为undefined时,这个时候方法不能执行
  • 采用符号!,必须确保某个标识符是有值的,可以跳过ts在编译阶段对它的检测
interface hander{
    name:string,
    age:number,
    size?:number
}
const info: hander={
    name:"乞力马扎罗",
    age:18
}
//访问可以用可选的
console.log(info?.size)

//赋值的时候,可选链不行
// info?.size=23

// 解决方法:
// 1,类型缩小
if(info.size){
    info.size=23
}
// 2.非空类型断言,有点危险,确保非空值的父值一定有值,才能使用
info!.size=23
console.log(info.size)//23

字面量类型的使用

  • 将赋予的值当做类型,使用的时候只能使用字面量
  • 默认情况下没有多大意义,但是可以将多个类型联合在一起,你只能是我们中一个

在这里插入图片描述

type numtype = "left" | "top" | "up"
const num3: numtype = "left"

// 使用背景
// 一般请求方式,get或者post
// 采用这种方式,可以让用户必须传get或者post,否则报错
type requestype = "get" | "post"
function reqest(url: string, method: requestype) {

}
reqest('http//xxx.com', 'get')
  • 使用背景
// 使用背景
// 一般请求方式,get或者post
// 采用这种方式,可以让用户必须传get或者post,否则报错
type requestype = "get" | "post"
function reqest(url: string, method: requestype) {

}
const  hander={
    url:'xxx',
    method:'post'
}
// reqest('http//xxx.com',hander.method)
//报错,报错原因,不认识你这个hander.method获取的是string类型,不是get或者post
  • 解决方法1
// 解决方法1:类型断言
reqest('http//xxx.com',hander.method as "post")
  • 解决方法2
// 解决方法2,直接让hander对象是个字面量类型
const  hander1 :{ url:string,method:'post'}={
    url:'xxx',
    method:'post'
} as const
reqest('http//xxx.com',hander1.method)
// 或者,字面量推理
const  hander2={
    url:'xxx',
    method:'post'
} as const
reqest('http//xxx.com',hander2.method)

类型缩小(类型收窄)

  • 可以通过类似下面的判断语句,来改变ts的执行路径
if(info.size){
    info.size=23
}
  • 类似这样的语句也称之为类型保护
  • 在给定的执行路径中,可以缩小比声明时更小的类型,这个过程称之为缩小
  • 常见的类型保护
  • typeof,检查返回的类型
type requestype = "get" | "post"
function reqest(url: string, method: requestype) {
    if(typeof url ==='string'){
        console.log(url)
    }
}
  • 平等缩小(=== 和!== 和==等等),字面量的判断
type requestype = "get" | "post"
function reqest(url: string, method: requestype) {
    if(method==="get"){
        console.log(method)
    }
}
  • instanceof,表示是不是这个的实例
//传入一个实例
function reqest(data:string|Date) {
   if(data instanceof Date){
    console.log(data.getTime())
   }
}
  • in ,用于确定对象是否具有带名称的属性,in 运算符
  • 等等…

TypeScript 函数类型

函数类型表达式
  • 可以编写函数类型的表达式,来表示函数类型
  • ts中,函数类型中的形参名是不能省略的
// 函数类型表达式
// 格式:(参数列表)=>返回值
const fun: (num2: number) => number = (arg: number): number => {
   return 123
}
// 为了可阅读性,类型形参里的名不能省略
type funtype = (num2: number) => number//这个就代表一个函数类型
const fun2: funtype = (arg: number) => {
   return 123
}

// 例子,传入计算方式,计算两位数字,js写法
function cals(func) {
   const num1 = 12
   const num2 = 13
   const res = func(num1, num2)
}
function func1(num1, num2) {
   return num1 + num2
}
cals(func1)

//ts写法
type calstype = (num1: number, num2: number) => number
function cals1(func: calstype) {
   const num1 = 12
   const num2 = 13
   const res = func(num1, num2)
}
function func2(num1: number, num2: number) {
   return num1 * num2
}
cals1(func2)
内部规则检测
// ts对于很多的类型的检测报不报错,取决于它的内部规则
interface gule {
   name: string
   age: number
}
//直接写报错,原因,第一次定义的时候,会检测规则报错
//  const info:gule={
//    name:"山头",
//    age:12,
//    size:'大'
//  }

//但取决于内部规则,赋值完,再使用,这样就没检测,单指size的增加,其他已定义的还是会检测
const p = {
   name: "山头",
   age: 12,
   size: '大'
}
const info: gule = p
函数的调用签名
  • 在js中,函数除了可以被调用,自己也可以有属性值的
  • 类型表达式并不能支持声明属性
  • 当你想要一个带有属性的函数,就可以在一个对象类型中写一个调用签名
//函数表达式,这里是箭头
//不能声明其他属性
type obj2 = (num1: number) => number



//调用签名
interface obj {
   name: string
   age: number
   //函数可以调用:函数调用签名,这里是冒号
   (num1: number): number
}

const func: obj = (num1: number): number => {
   return 123
}
func(123)
如何选择他们?
  • 如果只是描述函数类型本身(函数类型可以被调用),使用函数表达式
  • 如果再描述函数作为对象可以被调用,同时也有其他属性时,使用函数调用签名

参数的可选类型

  • 可选参数必须放在必传参数的后面
// 可选参数类型是什么
// 当不传的时候,y就是undefined类型,也就是number|undefined联合类型
function fun(x:number,y?:number){
   console.log(x,y)
   if(y!=undefined){
      console.log(y)
   }
}
fun(1)

参数的默认值

// 函数的参数有默认值
// 有默认值的情况下,参数的类型注解可以省略
// 此时,有默认值的参数,哪怕是number,也可以接收一个undefined类型
function fun(x:number,y=100){
   console.log(x,y)
   if(y!=undefined){
      console.log(y)
   }
}
fun(1)

剩余参数

  • 剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
  • 利用剩余参数我们可以定义一个形参不固定的计算和的函数。
function sum (first, ...args) {
    console.log(first); // 10
    console.log(args); // [20, 30] 
}
sum(10, 20, 30)// 或者
// 剩余参数,通过这种方式扩展了类型注解
function fun(...arrs: (string| number)[]) {

}
fun(1,2,3,'4')

函数重载

  • ts中,可以去编写不同的重载函数,来表示函数可以以不同的方式进行调用
  • 一般是编写两个或者以上的重载签名。再去编写一个通用的函数以及实现
// 需求。将两个数字或者字符串相加
// 联合类型,这个案例用不了

// 普通实现
// function add(n1, n2) {
//    return n1 + n2
// }
// add(1,2)通用函数不可调用

//函数重载
//1,先编写重载函数
function add2(n1:number, n2:number):number
function add2(n1:string, n2:string):string

//2,再编写通用的函数
function add2(n1:any, n2:any) {
   return n1 + n2
}
console.log(add2(1,2))//3
console.log(add2("1","2"))//12

// add2("1",2)//函数 不能被调用,没有对应的重载函数

函数重载-联合类型(优先使用)

  • 能用就用联合类型
//函数重载-联合类型
//定义一个函数,可以传入字符串或者数组,获取他们的数组
//1,编写重载函数-联合类型
function add2(arg:string|any[]) {
   return arg.length
}
console.log(add2("123"))//3

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

线性规划模型-应用篇

文章目录 模型特点使用技巧工具包和求解器模型线性化 应用实例经验总结 模型特点 上一篇中&#xff0c;详细阐述了线性规划问题和单纯形法的算法原理&#xff0c;本文将着重介绍线性模型在工业场景中的应用。 首先需要说清楚的是&#xff0c;为什么线性模型深受研发人员青睐。…

【dnf5文档】新一代RedHat自动化包管理器

前言 HI,CSDN的码友们&#xff0c;距离上一次我发文章已经过去了半年的时间&#xff0c;现在我又来介绍自己新发现和探究的开源技术了。计算机的发展总是飞速的&#xff0c;当我在写这篇文章的时候&#xff0c;Fedora rawhide已经进入了40版本、默认采用的自动化包管理器为dnf…

iPhone苹果手机触屏失灵无法关机,如何强制重启

参考:https://zhuanlan.zhihu.com/p/615223121 1&#xff0c;只轻按一下音量上键后快速松开 2&#xff0c;只轻按一下音量下键后快速松开 3&#xff0c;只按住右侧电源键长按不松手&#xff0c;直到手机关机。

什么是CSS中的渐变(gradient)?如何使用CSS创建线性渐变和径向渐变?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 渐变&#xff08;Gradient&#xff09;在CSS中的应用⭐ 线性渐变&#xff08;Linear Gradient&#xff09;语法&#xff1a;示例&#xff1a; ⭐ 径向渐变&#xff08;Radial Gradient&#xff09;语法&#xff1a;示例&#xff1a; ⭐ 写…

CentOS安装Postgresql

PG基本安装步骤 安装postgresql&#xff1a; sudo yum install postgresql-server初始化数据库&#xff1a;安装完毕后&#xff0c;需要初始化数据库并创建初始用户&#xff1a; sudo postgresql-setup initdb启动和停止服务&#xff1a; sudo systemctl start postgresql sudo…

FreeRTOS源码分析-12 低功耗管理

目录 1 STM32低功耗管理概念及应用 1.1睡眠模式 1.2 停止模式 1.3 待机模式 2 Tickless低功耗管理 2.1 Tickless低功耗模式介绍 2.2 FreeRTOS低功耗模式配置 2.3 FreeRTOS低功耗模式应用 3 低功耗管理实际项目开发 3.1 低功耗设计必须要掌握的硬件知识 …

什么是BFC?它有什么作用?如何创建BFC?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 什么是BFC⭐ BFC的作用⭐ 创建BFC的方法⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&#xff01;这个专栏是为那些对Web…

TENNECO EDI 项目——X12与XML之间的转换

近期为了帮助广大用户更好地使用 EDI 系统&#xff0c;我们根据以往的项目实施经验&#xff0c;将成熟的 EDI 项目进行开源。用户安装好知行之桥EDI系统之后&#xff0c;只需要下载我们整理好的示例代码&#xff0c;并放置在知行之桥指定的工作区中&#xff0c;即可开始使用。 …

在Java中操作Redis(详细-->从环境配置到代码实现)

在Java中操作Redis 文章目录 在Java中操作Redis1、介绍2、Jedis3、Spring Data Redis3.1、对String的操作3.2、对哈希类型数据的操作3.3、对list的操作3.4、对set类型的操作3.5、对 ZSet类型的数据&#xff08;有序集合&#xff09;3.6、通用类型的操作 1、介绍 Redis 的Java客…

C语言笔试训练【第六天】

大家好&#xff0c;我是纪宁。今天是C语言笔试训练的第6天&#xff0c;加油&#xff01; 往期回顾&#xff1a; C语言笔试训练【第五天】 C语言笔试训练【第四天】 C语言笔试训练【第三天】 C语言笔试训练【第二天】 C语言笔试训练【第一天】 1、以下叙述中正确的是&…

client-go实战之十二:选主(leader-election)

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《client-go实战》系列的第十二篇&#xff0c;又有一个精彩的知识点在本章呈现&#xff1a;选主(leader-election)在解释什么是选主之前&…

【2023 华数杯全国大学生数学建模竞赛】 A题 隔热材料的结构优化控制研究 问题分析及完整论文

【2023 华数杯全国大学生数学建模竞赛】 A题 隔热材料的结构优化控制研究 问题分析及完整论文 1 题目 A 题 隔热材料的结构优化控制研究 新型隔热材料 A 具有优良的隔热特性&#xff0c;在航天、军工、石化、建筑、交通等高科技领域中有着广泛的应用。 目前&#xff0c;由单…

微服务Ribbon-负载均衡策略和饥饿加载

目录 一、负载均衡策略 1.1 负载均衡策略介绍 1.2 自定义负载均衡策略 二、饥饿加载 &#xff08;笔记整理自bilibili黑马程序员课程&#xff09; 一、负载均衡策略 1.1 负载均衡策略介绍 负载均衡的规则都定义在IRule接口中&#xff0c;而IRule有很多不同的实现类&…

使用巴特沃兹滤波器的1D零相位频率滤波研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Redis布隆过滤器的原理和应用场景,解决缓存穿透

目录 一、redis 二、布隆过滤器 三、缓存穿透问题 四、布隆过滤器解决缓存穿透 一、redis Redis&#xff08;Remote Dictionary Server&#xff09;是一种开源的内存数据存储系统&#xff0c;也是一个使用键值对&#xff08;Key-Value&#xff09;方式的高性能数据库。Red…

Scratch 之 单个角色模糊特效

想给单独一个角色用模糊特效&#xff0c;怎么办&#xff01;&#xff01;&#xff01; 完全不用慌&#xff0c;最近&#xff0c;我做出了超好用的个体模糊特效&#xff0c;用起来超级简单&#xff0c;接下来进入讲解。 1.原理 前几天&#xff0c;我闲来无事&#xff0c;摘下眼镜…

Express 实战(一):概览

在正式学习 Express 内容之前&#xff0c;我们有必要从大的方面了解一下 Node.js 。 在很长的一段时间里&#xff0c;JavaScript 一门编写浏览器中运行脚本的语言。不过近些年&#xff0c;随着互联网的发展以及技术进步&#xff0c;JavaScript 迎来了一个集中爆发的时代。一个…

DCMM数据管理成熟度之数据治理-数据治理沟通

​01 标准原文 1 概述 数据治理沟通旨在确保组织内全部利益相关者都能及时了解相关政策、标准、流程、角色、职责、计划的最新情况,开展数据管理和应用相关的培训,掌握数据管理相关的知识和技能。数据治理沟通旨在建立与提升跨部门及部门内部数据管理能力,提升数据资产意识,…

V3s uboot 通过env 修改LCD 参数信息

实际项目中我们可能使用各种参数的LCD 显示器&#xff0c;有7吋&#xff0c;4.3 寸等等&#xff0c;我这里使用的uboot 版本是U-Boot 2017.01-rc2 &#xff0c;在make menuconfig 时候会填入lcd 配置信息&#xff0c;如下&#xff1a; 所以这里使用起来很不方便&#xff0c;查看…

【Vue2.0源码学习】生命周期篇-初始化阶段(new Vue)

文章目录 1.综述1.1 前言1.2 生命周期流程图1.3 总结 2.初始化阶段2.1 前言2.2 new Vue()都干了什么2.3 合并属性2.4 callHook函数如何触发钩子函数2.5 总结2.5 总结 1.综述 1.1 前言 在Vue中&#xff0c;每个Vue实例从被创建出来到最终被销毁都会经历一个过程&#xff0c;就…