Typescript初体验

Typescript

Typescript 官网地址: https://www.typescriptlang.org/zh/

使用 nvm 来管理 node 版本: https://github.com/nvm-sh/nvm

装 Typescript:

npm install -g typescript

使用 tsc 全局命令:

// 查看 tsc 版本
tsc -v
// 编译 ts 文件
tsc fileName.ts

1.原始数据类型和Any类型

//布尔类型
let isDone: boolean = true
//数字类型
let age: number = 123
//字符串类型,模板字符串也可以
let firstName = 'Kiwi'
let message = `hello ${firstName}`
//undefined 和 null
let u: undefined = undefined
let n: null = null//注:undefined 和 null 是所有类型的子类型
// let num: number = undefined
// 但是在新版的 ts 中,有一个特殊的配置是 strictNullChecks,
// 在有些编辑器中默认为 true。它会严格检查 null 以及 undefined 类型,它只能赋值给本身的类型或者 any。//any:允许赋值为任意类型
let notSure: any = 4
notSure = 'maybe a string'
notSure = true
//在其上还可以任意调用方法和属性,在我们有明确类型时,应避免使用any
notSure.myName
notSure.geyName()

2.数组和元组

数组的声明方式如下,以纯数字数组举例

let arrayOfNumbers: number[] = [1, 2, 3]
arrayOfNumbers.push(3)
arrayOfNumbers.unshift(4)
//arrayOfNumbers.push('hello')	会报错

与js一样ts也可以使用一些数组的方法,但如果在方法里传入的参数与声明的类型不同的话,是会报错的

补充:我们都知道在js里有一种特殊的数据结构——类数组(array-like Objects),它很像数组,但是和数组不一样

//类数组
function test() {console.log(arguments);arguments.lengtharguments[0]// let arrat: any[] = arguments   不能把一个数组赋值给arguments
}

其具备数组的一些属性,如length,并且可以取其索引,但是它没有数组上的一些方法,并且我们不能把一个数组赋值给他,说明arguments和数组不是一个类型

其实在ts里给arguments专门定义了一个类型,叫IArguments

在这里插入图片描述

同理ts还有很多其他的内置类型,在这里不做细讲,后面如果有用到再会过来复习

元祖tuple:一定程度上限制了数据类型的数组

简单理解定义了具体索引的具体数据类型的数组

//元组
let user: [string, number] = ['kiwi', 21]

数据类型不对应或者数组内容多了或少了都会报错

但可以通过push()方法突破这个限制,但是只能添加规定好的类型中的一种(上述例子即只能添加string和number中的一种)

user.push(123)
user.push('我饿了')
// user.push(true)	报错

3.Interface- 接口 初探

interface 对对象(shape)进行描述

IPerson 中I用于提示定义的是一个interface,我这里没加

readonly 和 const 的区别: readonly用于定义对象的属性只读,const 用于定义的变量只读

interface Person {//readonly只读属性,只能在初始化时修改readonly id: numbername: stringage: number//可选属性  字面意思sex?: string
}let kiwi: Person = {id: 1,name: 'kiwi',age: 21,sex: '男'
}
kiwi.age = 23
// kiwi.id = 2  readonly属性不能二次修改let mjy: Person = {id:2,name: 'mjy',age: 21,
}

4.函数

// function add(x: number, y: number, z?: number): number {
//     if (typeof z == 'number') {
//         return x + y + z
//     } else {
//         return x + y
//     }
// }//函数表达式写法
const add = (x: number, y: number, z?: number): number => {if (typeof z == 'number') {return x + y + z} else {return x + y}
}
//let add2:string=add赋值不适配赋值函数需要按照函数的方式进行生命
// 不是函数声明的情况下 给变量赋值表达式返回值需要使用箭头
let add2: (x: number, y: number, z?: number) => number = add//interface在函数中的使用
interface ISum {(x: number, y: number, z?: number): number
}
let add3: ISum = add

说实话有点没理解这个赋值函数类型的意义在哪里。。

这里当我们把一个变量赋值给一个函数的时候,这个变量就自动获得了一个类型,如下图所示,至于为什么下一节给大家解释

在这里插入图片描述

5.类型推论、联合类型和类型断言

上一节我们发现把一个变量赋值给一个函数的时候,这个变量就自动获得了一个类型,这其实是ts的一个原则——类型推论

类型推论:ts会自动推断当前变量的类型,如赋值无关类型则会报编译错误

例:

let num = 123
// num = '123'报错

之前我们学了any类型,any是一个大而全的数据类型,在不到万不得以的情况下我们不会使用它,但是现在假设有一种情况我们需要允许一部分的类型可以使用,比如说一个变量可以是字符串也可以是数字,其他类型则不行,那么这种情况我们该怎么处理呢

这里我们引入一个新的数据类型——联合类型(union types)

//union type
let numberOrStirng: number | string
numberOrStirng = 123
numberOrStirng = '123'

注意:联合类型的变量只能访问此联合类型所有类型里共有的属性或方法,但有的时候我们又确实要在不确定变量类型的情况下访问对于的属性或方法

这里我们就要使用到类型断言

类型断言:将一种不确定的变量类型,告诉ts编译器,就是某一种变量类型。可欺骗编译器但避免不了运行时的报错(使用as关键字)

例:假设我们现在要一个getLength()函数,要求其输入的类型可以是number也可以是string,但返回的类型只能是number(因为获取的是长度)

function getLength(input: number | string): number {const str = input as stringif (str.length) {return str.length} else {const number = input as numberreturn number.toString().length}
}

注意:类型断言不是类型转换,如果在这里定义一个变量将其断言为联合类型中不存在的数据类型的话,是会报错的

除了使用类型断言可以实现以外,我们还可以使用类型守卫type-guard来实现(使用typeof关键字)

function getLength(input: number | string): number {if (typeof input == 'string') {return input.length     //这里的input是string类型} else {return input.toString().length  //这里的input自动变成了number类型}
}

6.Class类

面向对象编程的三大特点

  • 封装(Encapsulation):将对数据的操作细节隐藏起来,只暴露对外的接口。外界调用端不需要(也不可能)知道细节,就能通过对外提供的接口来访问该对象,
  • 继承(Inheritance):子类继承父类,子类除了拥有父类的所有特性外,还有一些更具体的特性。
  • 多态(Polymorphism):由继承而产生了相关的不同的类,对同一个方法可以有不同的响应。
class Animal {name: string;constructor(name: string) {this.name = name}run() {return `${this.name} is running`}
}
const snake = new Animal('lily')// 继承的特性
class Dog extends Animal {bark() {return `${this.name} is barking`}
}const xiaobao = new Dog('xiaobao')
console.log(xiaobao.run())
console.log(xiaobao.bark())// 这里我们重写构造函数,注意在子类的构造函数中,必须使用 super 调用父类的方法,要不就会报错。
class Cat extends Animal {constructor(name) {super(name)console.log(this.name)}run() {return 'Meow, ' + super.run()}
}
const maomao = new Cat('maomao')
console.log(maomao.run())

类成员的访问修饰符:

  • public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的
  • private 修饰的属性或方法是私有的,不能在声明它的类的外部访问
  • protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的

7.类与接口

用类实现一个接口

interface Radio {switchRadio(trigger: boolean): void;
}
class Car implements Radio {switchRadio(trigger) {return 123}
}
class Cellphone implements Radio {switchRadio() {}
}interface Battery {checkBatteryStatus(): void;
}// 要实现多个接口,我们只需要中间用 逗号 隔开即可。
class Cellphone implements Radio, Battery {switchRadio() {}checkBatteryStatus() {}
}

8.enums枚举

enum Direction {Up,Down,Left,Right
}console.log(Direction.Up);	//0// 还有一个神奇的点是这个枚举还做了反向映射
console.log(Direction[0])	//Upenum Direction {Up = 10,Down,Left,Right
}
console.log(Direction.Down);	//11// 字符串枚举
enum Direction1 {Up = 'UP',Down = 'DOWN',Left = 'LEFT',Right = 'RIGHT',
}
const value = 'UP'
if (value === Direction1.Up) {console.log('go up!')
}//常量枚举constenum编译时直接编译成常量,提高性能
const enum Direction3 {Up,Down,Left,Right
}

9.泛型 Generics

泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。

function echo(arg) {return arg
}
const result = echo(123)
// 这时候我们发现了一个问题,我们传入了数字,但是返回了 anyfunction echo<T>(arg: T): T {return arg
}
const result = echo(123)// 泛型也可以传入多个值
function swap<T, U>(tuple: [T, U]): [U, T] {return [tuple[1], tuple[0]]
}const result = swap(['string', 123])

10.约束泛型

在函数内部使用泛型变量的时候,由于事先不知道它是哪种类型,所以不能随意的操作它的属性或方法

interface搭配泛型之后,可以灵活的返回不同的类型

创建一个拥有特定类型的容器,仿佛给一个容器贴标签一样

泛型就好像一个可变的参数,在用的时候传入,生成这个不同类型的一个容器,或者像上节课讲的用它来灵活的约束参数的类型,不需要参数是一个特别死板的类型,不希望他是一个特定string、number类型,我要传入的参数必须有某某属性、某某方法,否则就会报错。

在函数使用的时候,函数的这个类型推断,不会流入到函数体内,所以使用表达式,没法建立明确的绑定,用泛型可以让我们打破这个鸿沟,这个时候就可以返回它传入的类型。

class Queue {private data = [];push(item) {return this.data.push(item)}pop() {return this.data.shift()}
}const queue = new Queue()
queue.push(1)
queue.push('str')
console.log(queue.pop().toFixed())
console.log(queue.pop().toFixed())//在上述代码中存在一个问题,它允许你向队列中添加任何类型的数据,当然,当数据被弹出队列时,也可以是任意类型。在上面的示例中,看起来人们可以向队列中添加string 类型的数据,但是那么在使用的过程中,就会出现我们无法捕捉到的错误,class Queue<T> {private data = [];push(item: T) {return this.data.push(item)}pop(): T {return this.data.shift()}
}
const queue = new Queue<number>()//泛型和 interface
interface KeyPair<T, U> {key: T;value: U;
}let kp1: KeyPair<number, string> = { key: 1, value: "str"}
let kp2: KeyPair<string, number> = { key: "str", value: 123}

11.类型别名、字面量、交叉类型

类型别名,其实对于js就是将一个表达式赋给一个新变量,目的就是为了,能减少重复代码量,

对于联合类型新的理解,就是或类型,意思就是可以是多个类型中的一个;也要加type关键字要不然和普通变量之间无法区别,自己尝试的时候忘加了type关键字,这个要注意

交叉类型:就是与的关系,但这个有点特殊它不是在选交集,它是多种类型同时满足的意思,用**关键字&**来连接;它可以配合接口来使用

//类型别名
//type-aliase
let sum: (x: number, y: number) => number
// const result = sum(1,2)type PlusType = (x: number, y: number) => number
let sum2: PlusType
let result2 = sum2(1, 2)type StrOrString = string | number
let res: StrOrString = 123
res = '123'//字符串字面量
const str1: 'name' = 'name'
const number1: 1 = 1
type Direction = 'Up' | 'Down' | 'Left' | 'Right'
let toUp: Direction = 'Up'//交叉类型
interface IName {name: string
}
type person = IName & { age: number }
let me: person = { name: 'yjt', age: 21 }

12.声明文件

声明文件后缀:xxx.d.ts

它里面没有任何的实际实现代码,只有类型声明

可以用来查一些第三方库:https://types.kubajastrz.com/package/vue

声明文件一般是用于非ts编写的项目,即原来是js模块现在想用ts项目中在次使用

下面我们用一个小例子来体会一下

calculator.d.ts

//字面量
type IOperator = 'plus' | 'minus'
//传入两个参数,
//第一个看起来像是一个字符串,其实是一个限制了输入的字面量,限制只能输入 plus 或者 minus 
//第二个输入的是一个数组,表示用于计算的数字
//type ICalculator = (operator: IOperator, numbers: number[]) => number
interface ICalculator {(operator: IOperator, numbers: number[]): number	//函数类型使用冒号plus
}
declare const calculator: ICalculator 
//模块导出
export default calculator

13.内置类型

const a: Array<number> = [1,2,3]
// 大家可以看到这个类型,不同的文件中有多处定义,但是它们都是 内部定义的一部分,然后根据不同的版本或者功能合并在了一起,一个interface 或者 类多次定义会合并在一起。这些文件一般都是以 lib 开头,以 d.ts 结尾,告诉大家,我是一个内置对象类型欧
const date: Date = new Date()
const reg = /abc/
// 我们还可以使用一些 build in object,内置对象,比如 Math 与其他全局对象不同的是,Math 不是一个构造器。Math 的所有属性与方法都是静态的。Math.pow(2,2)// DOM 和 BOM 标准对象
// document 对象,返回的是一个 HTMLElement
let body: HTMLElement = document.body
// document 上面的query 方法,返回的是一个 nodeList 类型
let allLis = document.querySelectorAll('li')//当然添加事件也是很重要的一部分,document 上面有 addEventListener 方法,注意这个回调函数,因为类型推断,这里面的 e 事件对象也自动获得了类型,这里是个 mouseEvent 类型,因为点击是一个鼠标事件,现在我们可以方便的使用 e 上面的方法和属性。
document.addEventListener('click', (e) => {e.preventDefault()
})

Typescript 还提供了一些功能性,帮助性的类型,这些类型,大家在 js 的世界是看不到的,这些类型叫做 utility types,提供一些简洁明快而且非常方便的功能。

// partial,它可以把传入的类型都变成可选
interface IPerson {name: stringage: number
}let viking: IPerson = { name: 'viking', age: 20 }
type IPartial = Partial<IPerson>
let viking2: IPartial = { }// Omit,它返回的类型可以忽略传入类型的某个属性type IOmit = Omit<IPerson, 'name'>
let viking3: IOmit = { age: 20 }

14.配置文件 tsconfig.json

官方文档:https://www.typescriptlang.org/tsconfig

  • files:运行tsc时会编译括号内的文件
  • compilerOptions:怎么编译?
    • outDir:编译好的文件应该输出放到哪里,默认是当前文件夹
    • module:指要输出的module的类型
    • target:选择要符合的ES标准
    • declaration:true自动生成目录下文件的声明文件
{"files": ["test.ts", "test2.d.ts"],	"compilerOptions": {"outDir": "./output","module": "ESNext","target":"ES5","declaration": true}

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

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

相关文章

利用数字人技术“活”化吉祥物,打造“科技+”数融盛会

在第十四届全国冬季运动会上&#xff0c;吉祥物“蒙古彩娃”安达和塞努不再同于往常静态的吉祥物形象&#xff0c;而是升级为生动活泼、能够与观众实时互动的数字人形象&#xff0c;活跃于赛事宣传、场馆介绍等多个场景&#xff0c;为本届冰雪盛会注入数字活力&#xff0c;提升…

RoboRAVE世界机器人大会亚洲分会toio™专项挑战顺利收官,toio™实现“双首次”突破

2024年2月21日&#xff0c;北京——2024 RoboRAVE国际教育机器人大会&#xff08;下称RoboRAVE&#xff09;亚洲分会toio™专项挑战在北京科技大学成功举办。现场云集来自华北、华南、华东等全国各地40组杰出学生队伍&#xff0c;展开热烈的机器人编程限时挑战。本届toio™专项…

并发编程入门指南

文章目录 并发编程进程和线程的区别并发和并行的区别创建线程的方式线程之间的状态&#xff0c;状态之间的转换新建三个线程&#xff0c;如何保证按顺序执行wait方法和sleep的区别如何停止一个正在运行的线程synchronized关键字底层原理Monitor属于重量级锁&#xff0c;了解过锁…

day04_流程语句_if_while_for

今日内容 1.if 2.switch 3.while,do-while,for 零、复习 1算术运算符中除法特性 整数相除不保留小数 10/33 2什么作用,i和i什么区别 让数据自增1i,是在后先使用后自增i,是在前先自增后使用 3&& 和 & 有相同点和不同点 相同点: 两边判断式子,一错就错全对才对不同点…

一文了解web开发基础知识【HTML、CSS、JavaScript】

文章目录 1 前言1.1 HTML1.2 CSS1.3 JavaScript1.4 理解HTML、CSS、JavaScript之间的关系 2 HTML2.1 什么是网页2.2 什么是HTML2.2.1 文本内容2.2.1.1 标题 2.2.2 图像2.2.3 链接2.2.4 列表2.2.5 表格2.2.6 HTML代码注释 2.3 第一个HTML文件2.3.1 示例2.3.2 补充2.3.2.1 < l…

苹果iPad通过Code APP应用实现SSH连接服务器远程进行开发

文章目录 1. 在iPad下载Code APP2.安装cpolar内网穿透2.1 cpolar 安装2.2 创建TCP隧道 3. iPad远程vscode4. 配置固定TCP端口地址4.1 保留固定TCP地址4.2 配置固定的TCP端口地址4.3 使用固定TCP地址远程vscode 本文主要介绍开源iPad应用IDE Code App 如何下载安装&#xff0c;并…

基于springboot + vue实现的前后端分离-酒店管理系统

项目介绍 基于springboot vue实现的酒店管理系统一共有酒店管理员和用户这两种角色。 管理员功能 登录&#xff1a;管理员可以通过登录功能进入系统&#xff0c;确保只有授权人员可以访问系统。用户管理&#xff1a;管理员可以添加、编辑和删除酒店的用户&#xff0c;包括前…

运维SRE-18 自动化批量管理-ansible4

12.2handles handles触发器(条件)&#xff0c;满足条件后再做什么事情应用场景&#xff1a;想表示&#xff1a;配置文件变化&#xff0c;再重启服务 配置handlers之前&#xff0c;每次运行剧本都会重启nfs&#xff0c;无论配置文件是否变化。 [rootm01 /server/ans/playbook]…

C++--输入一个数字判断是否是素数

一.算法思路 要判断数字n是否是素数&#xff0c;那么用n除以一个2~根号n的数字i&#xff0c;若有一个被整除&#xff0c;说明n不是素数&#xff0c;否则是素数 二.完整代码 #include<cmath> #include<iostream> bool IsPrime(int n) {for (int i 2;i < sqrt(n…

【MATLAB GUI】 1. 普通按钮、静态文本和可编辑文本

看B站up主freexyn的freexyn编程实例视频教程系列36Matlab GUI的学习笔记 文章目录 初步认识普通按钮静态文本和可编辑文本设计一个简易计算机 初步认识普通按钮 任务要求&#xff1a;点击一次“100”按钮&#xff0c;按钮上的文字值就递增1&#xff1b;点击“close”按钮&…

UniApp中打开蓝牙所需哪些权限

Hello&#xff0c;各位同学们新年好呀&#xff0c;咱们又见面了&#xff01;我是咕噜铁蛋&#xff01;随着移动应用的普及&#xff0c;蓝牙技术正变得越来越重要。在UniApp中&#xff0c;打开蓝牙功能为我们提供了更多便利和创新的可能性。然而&#xff0c;很多人可能不清楚在U…

【计算机网络】socket 网络套接字

网络套接字 一、端口号1. 认识端口号2. socket 二、认识TCP协议和UDP协议1. TCP协议2. UDP协议 三、网络字节序四、socket 编程1. socket 常见API2. sockaddr 结构3. 编写 UDP 服务器&#xff08;1&#xff09;socket()&#xff08;2&#xff09;bind()&#xff08;3&#xff0…

【Unity编辑器扩展】Unity编辑器主题颜色设置工具

可以用来应用和自定义你的Unity编辑器。14个主题可供选择。轻松创建自己的主题。 主题展示:

明御运维审计与风险控制系统漏洞复现

简介 明御运维审计与风险控制系统是安恒信息在多年运维安全管理的理论和实践经验积累的基础上,采用B/S架构,集“身份认证、账户管理、控制权限、日志审计”于一体,支持多种字符终端协议、文件传输协议、图形终端协议、远程应用协议的安全监控与历史查询,具备全方位运维风险…

ChatGPT丨“成像光谱遥感技术中的AI革命:ChatGPT应用指南“

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境&#xff0c;是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型&#xff0c;在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用&#xff0c;人工智能…

【医学大模型】临床推理 + 大模型,推理感知型诊断框架

临床推理 大模型&#xff0c;推理感知型诊断框架 提出背景Module II-1: 少数样本CoT推理Module II-2: 单模态学生蒸馏Module II-3: 多模态学生蒸馏 提出背景 论文&#xff1a;https://arxiv.org/pdf/2312.07399.pdf 这篇文章提出了一种新的诊断框架&#xff0c;专注于利用大型…

Android T 远程动画显示流程其二——动画的添加流程(更新中)

前言 接着上篇文章分析 Android T 远程动画显示流程其一 切入点——处理应用的显示过渡 下面&#xff0c;我们以从桌面点击一个应用启动的场景来分析远程动画的流程&#xff0c;窗口添加的流程见Android T WMS窗口相关流程 这里我们从AppTransitionController.handleAppTran…

HAL STM32 HW I2C DMA + SSD1306/SH1106驱动示例

HAL STM32 HW I2C DMA SSD1306/SH1106驱动示例 &#x1f4cd;硬件I2C DMA驱动参考&#xff1a;https://blog.csdn.net/weixin_45065888/article/details/118225993 &#x1f4cc;github上的相关项目&#xff1a;https://github.com/taburyak/STM32_OLED_SSD1306_HAL_DMA &am…

五种多目标优化算法(MOGWO、MOJS、NSWOA、MOPSO、MOAHA)性能对比,包含6种评价指标,9个测试函数(提供MATLAB代码)

一、5种多目标优化算法简介 1.1MOGWO 1.2MOJS 1.3NSWOA 1.4MOPSO 1.5MOAHA 二、5种多目标优化算法性能对比 为了测试5种算法的性能将其求解9个多目标测试函数&#xff08;zdt1、zdt2 、zdt3、 zdt4、 zdt6 、Schaffer、 Kursawe 、Viennet2、 Viennet3&#xff09;&#xff0…

Linux服务器安装MySQL8

进入安装目录 /usr/local下载 wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz解压,重命名 tar -Jxvf mysql-8.0.20-linux-glibc2.12-x86_64.tar.xzmv mysql-8.0.20-linux-glibc2.12-x86_64 mysql8创建用户组、用户 # 需要…