从零开始的web前端学习-TypeScript

news/2025/3/31 16:42:15/文章来源:https://www.cnblogs.com/kidss/p/18791119

目录
  • 1TypeScript简介
  • 2开发环境搭建
  • 3变量
  • 4any关键字
  • 5函数
  • 6对象
  • 7类型别名
  • 8数组
  • 9联合
  • 10元组
  • 11枚举
  • 12接口
  • 13项目初始化(简陋)
  • 14类
  • 15类型修饰符
  • 16getter、setter方法
  • 17继承
  • 18接口实现
  • 19抽象类
  • 20泛型
  • 21类型缩小

这篇文章仅仅是分享 TypeScript 的部分内容,并没有完整地对其进行学习总结,想要完整地学习 TypeScript,请移至:https://www.typescriptlang.org/docs/

1TypeScript简介

TypeScript 通常被认为是 JavaScript 的超集,但这并不仅仅意味着其增加许多功能,而是我们以更加精确的方式编写 JavaScript,以便代码错误减少,实际上 TypeScript 最终会被编译成为 JavaScript,本质上其应被看作是一种开发工具

TypeScript 实际的作用是 Staic checking(静态检查),这意味着无论何时编写代码,整个语法都会被分析检查,减少错误,而不需要等待实际运行渲染时出现错误

TypeScript 可以以 .ts 格式编写,这是一种最简单、基础的 TypeScript 格式

2开发环境搭建

对于 TypeScript 的安装,可以使用 Node 的 npm 工具进行局部安装,这可以使得每个项目的版本独立,互不影响,同时也可以选择进行全局安装

REM 局部安装
npm i typescript --save-devREM 全局安装
npm i typescript -gREM 查看 TypeScript 版本
tsc -v

在开发环境搭建好后,可以尝试实际编写代码,并将其转换为 JavaScript

// test.ts
console.log('hello world')

在编写完 TypeScript 文件后,并不能以 .ts 格式运行代码,而需要在命令行用 tsc 命令对 .ts 格式的文件进行转换

REM .ts 转换 .js
tsc test.ts

3变量

TypeScript 可以说是关于 type(类型)的 JavaScript,其中包含十分多的变量类型如 number、string、boolean、underfined、object、array、null、void、tuples 等等,还有 any 关键字,使用它则意味着我们并不用被变量类型所困扰,unknown 这种 TypeScript 设置的特殊类型等等

// variable.ts
// 创建变量 -- let variableName: type = value
let greetings: string = 'Hello World'// JavaScript 语法也适用,并且更简洁
let myNum = 6// 使用变量
console.log(greetings)// 消除某些报错
export {}

注意:

  • 当你在 TypeScript 中对变量类型进行确定后,对应的变量不再能够使用其他类型的方法,若使用则它会报错告知,而仅仅能使用同类型的方法
  • 为变量进行类型确定显得低效冗余,实际上,TypeScript 在赋值时会对变量类型自动进行推断,所以可以使用更加简洁的语法

4any关键字

any 关键字并不意味着任何类型,它仅仅是 TypeScript 中的一个标记,被标记的变量将会取消掉对其值的类型推断,这在大部分时候并不推荐,可以配置 noImplicitAny 将任何隐式标记为错误

// 当变量声明不赋值时,该变量就会被 any 标记
let anyType

5函数

any 关键字标记对于变量来说,在部分时候是可用的,甚至极少情况下,我们需要 any 关键字标记,但在函数中,any 标记参数是会引发错误的,所以在函数部分,确定参数类型是十分有必要的

// function.ts
// JavaScript 语法,但此时参数 num 会被 any 标记
function addTwo (num) {return num + 2
}// 确定参数类型,取消 any 标记
function addTwo (num: number) {return num + 2
}// 箭头函数,参数带默认值
let loginUser = (name: string, email: string, isPaid: boolean = false) => {}
// 若带默认值,则可以省略参数传递
loginUser('Tom', '123@q.com')// 确定返回值类型
function addTwo (num: number): number {return num + 2
}// 箭头函数同样适用
function getStr = (s: string): string {return ''
}// 方法同样适用
const heros = ['thor', 'spiderman', 'ironman']
heros.map((hero): string => { // 由于 heros 是一个字符串数组,所以会自动推断 hero 是字符串类型return `hero is ${hero}`
})// 无返回值
function consoleErr (errmsg: string): void {console.log(errmsg)
}// never 意味着函数永远不会返回值,是为错误处理设置的
function handleErr (errmsg: string): never {throw new Error(errmsg)
}// 返回值类型多样时,TypeScript 会自动推断并联合
function getValue (myVal: number) { // 此时返回值类型为 true | "Your value lower than 5"if (myVal >= 5) {return true}return "Your value lower than 5"
}export {}

注意:never 代表从未被观察到的值,在返回类型中,这意味着函数抛出发生异常或终止程序的执行

6对象

// object.ts
// JavaScript 的对象创建语法同样适用于 TypeScript
const user = {name: 'Tom',email: '123@q.com',isActive: true
}// 常见场景
function createUser ({name: string, isLogin: boolean}) {}
const userOne = createUser({name: 'Tom', isLogin: false})const userTwo = createUser({name: 'Marry', isLogin: false, email: '123@q.com'}) // 这会报错
const newUser = {name: 'Marry', isLogin: false, email: '123@q.com'}
createUser(newUser) // 这不会报错,但实际上并不存在属性 email// 返回值类型为对象
function createCourse (): {name: string, price: number} { // 实际上,可读性以及实用性都较差return {name: 'react', price: 100} // 当返回值属性无法对应时会报错
}

7类型别名

类型别名简单来讲是一个属性集,它只关注用户的输入参数,获取用户的输入信息,这可以简化函数的输入参数列表,也能够优化返回值为对象的差可读性

// typeAlias.ts
type User = { // 类型别名readonly _id: string, // 只读变量,下划线前缀代表该变量故意不使用name: string,email: string,isPaid: boolean,credcardDetails?: number // 选择变量,可选择输入或不输入
}type cardNumber = {cardNumber: string
}type cardDate = {cardDate: string
}type cardDetails = cardNumber & cardDate & { // 混合类型cvv: number
}

注意:TS 编译成为 JS 后,JavaScript 并没有相关的只读约束,readonly 仅仅是 TypeScript 的特性,在出现修改只读变量的错误时,它会阻止编译

8数组

// array.ts
const superHeros = [] // never 类型数组
superHeros.push('spiderman') // never 类型数组拒绝接受 stringconst scores: number[] = [] // number 类型数组
scores.push(6) // number 类型数组接受 numberconst names: Array<string> = [] // string 类型数组const MLModels: number[][] = [ // 类似二维数组,且仅允许存储 number 数组[255, 255, 255],[0, 0, 0]
]

9联合

联合允许数据类型的多样化,是多种类型数据的组合

let score: number | string = 33 // 联合类型,score 是 number 或 string 类型type User = {name: stringid: number
}type Admin = {userName: stringid: number
}let Tom: User | Admin = {name: 'Tom', id: 123} // 联合类型,但现为普通用户Tom = {userName: 'hc', id: 456} // 成为管理员function getDBId (id: number | string) {if (typeof id === 'string'){ // 联合类型视为新的类型,需要细化类型id.toLowerCase() // 联合类型不能直接调用对应类型方法}
}const data: number[] | string[] = [] // data 是一个 number 类型数组或一个 string 类型数组
const datas: (number | string)[] = [] // datas 是一个 number 类型与 string 类型混合的数组let PI: 3.14 = 3.14 // 类似于常量定义,只允许赋值 3.14
let seatPosition = 'aisle' | 'middle' | 'window' // 允许联合类型

10元组

元组从广义上看,它是一个数组,一种特殊的数组,TypeScript 对其存在某些限制

// tuple.ts
let tUser: [string, number, boolean] // 元组声明tUser = ['hc', 100, true] // 赋值类型必须对应type User = [number, string] // 类型别名实现元组效果
const newUser: User = [112, 'Tom']newUser[1] = 'Marry' // 在某些版本中,这是允许的操作,尽管是 const 声明newUser.push(true) // 数组方法,打破元组限制

注意:TypeScript 对于元组的限制并不严格,在使用元组类型时,更需要自行添加一些限制以防止程序的错误

11枚举

// enams.ts
const enum SeatChoice { // 枚举声明,const 会防止编译生成过多 JavaScript 代码,而仅生成必要内容AISLE = 10, // 默认值设置MIDDLE,WINDOW
}const seatPosition = SeatChoice.AISLE // 枚举使用

注意:第一枚举变量默认值为零,后续变量会递增,但可以自行设置默认值,后续变量同样会递增,不仅仅是第一枚举变量,所有枚举变量都可以设置默认值,但请注意,递增操作仅针对于 number 类型,若设置 string 类型,就需要每个都设置默认值,除非有某一枚举变量设置为 number 类型,其后续变量会递增

12接口

// interface.ts
interface User { // 接口声明readonly DBId: number, // 只读属性email: string,userId: number,googleId?: string, // 可选属性sayHi: () => string, // 方法,返回值类型为 stringsayBye(): string // 方法,返回值类型为 stringsay(words: string): string // 含参方法,返回值类型为 string
}interface User { // 接口属性增加githubToken: string
}const Tom: User = {DBId: 123, email: '123@q.com', userId: 123,sayHi: () => {return 'Hi'},sayBye: () => {return 'Bye'},say: (word: 'Hello') => { // 传入参数名称可选,但类型必须固定return `say {$words}`},githubToken: 'github' // 增加属性
}interface Admin extends User { // 接口继承role: 'admin' | 'user'
}

13项目初始化(简陋)

REM 项目根目录
tsc --init

在项目文件夹下执行指令,将会得到 tsconfig.json 配置文件

REM 项目根目录
npm init -y

在项目文件夹下执行指令,将会得到 package.json 配置文件
注意:tsconfig.json 用于 TypeScript 配置,package.json 是包管理器配置文件

还需要在项目根目录下创建项目资源文件夹 src 以及打包分发文件夹 dist

// tsconfig.json
"outDir": "./dist" // 输出目录

但通过 tsc 指令将 TS 编译成 JS,不会将文件输出至输出目录

REM 监视模式
tsc -w

通过 tsc 指令进入监视模式后,编译文件将会默认输出至 dist/index.js 文件

14类

// class.ts
class User { // 类声明email: string,readonly name: string, // 只读属性constructor(email: string, name: string){ // 构造函数this.email = email,this.name = name}
}const Tom = new User('123@q.com', 'Tom') // 实例化
Tom.email = '456@q.com' // 修改属性

15类型修饰符

// class.ts
class User {public email: string, // 公有属性,默认公有name: string,private city: string = 'GuangZhou', // 私有属性constructor(email: string, name: string){this.email = email,this.name = name}
}const Tom = new User('123@q.com', 'Tom')
console(Tom.city) // 这并不会被允许,私有属性不能从外部访问// 简化语法
class Admin {readonly city: string = 'GuangZhou',constructor(private email: string,private name: string){}
}

16getter、setter方法

// class.ts
class User {readonly city: string = 'GuangZhou',constructor(private _email: string, // 下划线可以区分私有属性和公有属性,但并不是规范private _name: string){},get getEmail(): string { // getter 方法return `${this._email}`},set setName(name: string) { // setter 方法,不应该设置返回值类型,即使为 voidthis._name = name}
}

17继承

// class.ts
class User {private keyId = 1protected _count = 1
}class subUser extends User {changeCount () {this.count += 1}
}

注意:private 修饰的属性只能在类内部访问,继承类也无法访问,但 protected 修饰的属性可以在类内部和继承类内部访问

18接口实现

// class.ts
interface takePhoto {cameraMode: string,filter: string,burst: number,betterPhoto(): void
}class Instagram implements takePhoto { // 接口实现必须访问所有属性,实现所有方法constructor( // 访问属性public cameraMode: string,public filter: string,public burst: number,public video: string // 允许丰富接口属性){},betterPhoto(): void { // 实现方法console.log('Make photos better')}
}

19抽象类

// abstractClass.ts
abstract class takePhoto { // 抽象类,无法实例化constructor(public cameraMode: string,public filter: string){},abstract betterPhoto(): void // 抽象方法,无需实现getReelTime(): number { // 非抽象方法,需实现return 2}
}class Instagram extends takePhoto { // 继承抽象类并实现constructor( // 访问属性public cameraMode: string,public filter: string,public burst: number // 丰富属性){super(cameraMode, filter)},betterPhoto(): void { // 实现抽象方法console.log('Make photos better')}
}

注意:抽象类可以有非抽象方法,但抽象方法必须存在于抽象类中

20泛型

// generics.ts
function identityOne (val: number | boolean): number | boolean { // 联合实现泛型return val
} // 存在范围的约束,例如此处 string 类型将会被拒绝function identityTwo (val: any): any { // any 关键字实现泛型return val
} // 类型隐患,any 关键字将会取消类型检查,可能导致类型不一致等问题function identityThree<Type> (val: Type): Type { // 泛型函数,Type 可以换成其它字符串,但需相同return val
} // 在保证类型安全的同时,实现对所有类型的接受function identityFour<T> (val: T): T { // Type 可以换成其它字符串,但需相同return val
}// 泛型函数,数组输入
function arrayInput<T> (array: T[]): T { // T[] 也可写作 Array<T>return array[0] // 返回值类型为 T,则需要返回 T[] 中的值
} // 只有在数组作为输入时,才能使用数组方法// 泛型函数,箭头函数形式
const getScores = <T> (scores: T[]): T => { // <T, > 添加逗号可以表示这不是 JSX 标签,而是泛型return scores[0]
}// 多泛型参数函数,泛型参数限制
function another<T, U extends number> (valOne: T, valTwo: U): object { // U 应为 number 类型return {valOne,valTwo}
}// 泛型类
class Sellable<T> {public cart: T[] = [],addToCart (product: T) {this.cart.push(product)}
}

21类型缩小

类型缩小实际上是对泛型或联合等包含多种类型时的类型检查,这是一种类型保护工作,能够避免许多错误

// narrowing.ts
function detectType (val: string | number) {if (typeof val === 'string') { // typeof 实现 type narrowing 效果return val.toLowerCase()}return val + 2
}function printAll(strs: string | string[] | null) {if (strs) { // string 类型if (typeof strs === "object") { // 数组实际上认为是 object 类型for (const s of strs) {console.log(s)}} else if (typeof strs === "string") { // null 类型console.log(strs)}}
} // 代码块实际上存在漏洞,空字符串情况被忽略// in 运算符
interface User {name: string,email: string
}interface Admin {name: string,email: string,isAdmin: boolean
}function isAdminAccount (account: User | Admin) {if ('isAdmin' in account) { // 检查是否含有对应属性return account.isAdmin}
}// instanceof 关键字
function logValue(x: Date | string) {if (x instanceof Date) { // 检查是否为某类的实例化console.log(x.toUTCString())} else {console.log(x.toUpperCase())}
}// as 谓词
type fish = {swim: () => void}
type bird = {fly: () => void}function isFish(pet: fish | bird): pet is fish { // 特殊返回值,true 则返回 pet is fishreturn (pet as fish).swim !== undefined // 检查是否含有对应方法
} // 类似 in,但 in 更倾向于“你有我没有”,as 则是“找不同”interface Circle {kind: 'circle',radius: number
}interface Square {kind: 'square',side: number
}type Shape = Circle | Squarefunction getShape (shape: Shape) {if (shape.kind === 'circle') {return Math.PI * shape.radius ** 2}return shape.side * shape.side
}// switch 重写
function getArea (shape: Shape) {switch (shape.kind) {case 'circle':return Math.PI * shape.radius ** 2case 'square':return shape.side * shape.sidedefault:const _defaultShape: never = shape // never 类型的使用场景return _defaultShape}
} // default 情况能够避免某些错误,因为它会在错误时告知

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

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

相关文章

K8s Ingress, 你这个老6

Ingress 这个老6,结合nodeport和ClusterIp两种服务类型,你在引流这一块玩的花啊。 入口一夫当关,对内如鱼得水。本文是有态度马甲的第185篇原创。 本文记录了k8s中核心对象Ingress的产生背景和实现机制。 我们都知道k8s Service是一种将Pods通过网络暴露出来的抽象,每个服务…

C# .NET core 中处理图像,SkiaSharp,ImageSharp,NetVips,Magick.net多维度对比

2025年有哪些图像处理库,我们可以在项目中使用哪些库?本文列出了最流行的现有库。 .NET Core图片处理库SkiaSharp(https://github.com/mono/SkiaSharp) Magick.net(https://github.com/dlemstra/Magick.NET) ImageSharp(https://github.com/SixLabors/ImageSharp) NetV…

20243317 实验二《Python程序设计》实验报告

课程:《Python程序设计》 班级: 2433 姓名: 邓雅文 学号:20243317 实验教师:王志强老师 实验日期:2025年3月26日 必修/选修: 公选课 一、实验内容 1、掌握python中函数定义与调用相关知识点 大致框架与C语言相同,同样有实参,形参,可能有返回值,形式如下: def 函数名…

MEBCY-v2

MERCY-v2 信息收集 查找目标主机ip ┌──(root㉿kali)-[~] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:84:b2:cc, IPv4: 192.168.158.143 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.158.1 00:50:56:c…

人群密度分析预警摄像机

人群密度分析预警摄像机是可以实时地统计出一个指定区域内的总人数。当所监视区域的人员数量达到设定的阀值时摄像机输出报警信号。可设置人数阈值和时间阈值。用于设置触发进入区域内的人数值,达到该设定的阈值则摄像机输出报警信号。人数阈值可以手动设置,系统默认值为5人,…

CloudFlare DNS实现根域名跳转WWW域名,301跳转

0. 目的 托管在CloudFlare上的域名,已配置好www.bktai.com,想在用户访问根域名https://bktai.com时,重定向到 https://www.bktai.com. 为什么是重定向而不是同时可以访问?搜索引擎会搜到重复的内容,且维护两套路径都能正常工作,会造成混乱。 1. 配置根域名 点击自己要设置…

day:32 jmeter及性能测试——介绍

一、性能测试介绍 1、什么叫做性能测试? (1)通过某些工具或手段来检测软件的某些指标是否达到了要求,这就是性能测试 (2)指通过自动化的测试工具模拟多种正常、峰值以及异常负载条件来对系统的各项性能指标进行测试 2、性能测试的时间? 在功能测试完成后才能进行性能测试…

第六周第五天

所用时间:405分钟 代码量(行):689 博客量(篇):20 了解到的知识点: 1.VLAN的创建与划分 今天进行了计算机网络的实验一,在昨天下载的packet tracer上进行,实现了VLAN的创建与划分,进行跨交换机的相同vlan之间的计算机和不同vlan之间的计算机的通信实验2.树状结构查询…

独立按键控制LED数码管

前言 通过1个独立按键,控制LED数码管显示字符。 结合之前我的两篇文章独立按键控制LED流水灯方向 https://www.cnblogs.com/luckydoog/p/18796974数码管静态显示 https://www.cnblogs.com/luckydoog/p/18797690效果原理 提前在程序里存储共阴极数码管的编码表,能表示的字符范…

day:32 jmeter操作数据库——参数化

一、数据库通过用户参数设置变量 1、建一个查询的jdbs请求2、前置处理器中添加用户参数3、修改线程数4、查看结果二、txt文档实现参数化 1.编辑sql语句中导入变量${变量名}新建一个txt文档:data 命名导入txt文档运行以上内容是将sql语句写入到txt文档中引用 2. 将数据写入txt文…