当前位置: 首页 > news >正文

TypeScript-知识点梳理

1. 类型声明

let a: string  //变量a只能存储字符串
let b: number  //变量a只能存储数值
let c: boolean  //变量a只能存储布尔值a = 'hello'
a = 100 //警告:不能将类型“number”分配给类型“string”b = 666
b = '你好' //警告:不能将类型“string”分配给类型“number”c = true
c = 666 //警告:不能将类型“number”分配给类型“boolean”// 参数x必须是数字,参数y也必须是数字,函数返回值也必须是数字
function demo(x:number,y:number):number{return x + y
}demo(100,200) 
demo(100,'200')		//警告:类型“string”的参数不能赋给类型“number”的参数
demo(100,200,300)	//警告:应有 2 个参数,但获得 3 个
demo(100)			//警告:应有 2 个参数,但获得 1 个

2. 类型推断

let d = -99 //TypeScript会推断出变量d的类型是数字
d = false  //警告:不能将类型“boolean”分配给类型“number”

3. 类型总览

JavaScript 中的数据类型:

string、number、boolean、nullundefined、bigint、symbol、object

备注:其中 object 包含:Array、Function 、Date …

TypeScript 中的数据类型:

1. 以上所有 
2. 四个新类型: void 、 never 、 unknown 、 any 、 enum 、 tuple 
3. ⾃定义类型: type 、 interface

注意点: JS 中的这三个构造函数: NumberStringBoolean ,他们只⽤于包装对象,正常开发时,很少去使⽤他们,在 TS 中也是同理。

let n = 56
n.toFixed(2)
/*
当执⾏n.toFixed(2) ,底层做了这⼏件事:1.let temp = new Number(42)2.value = temp.toFixed(2)3.删除value4.返回value
*/

类型总览:

类型描述举例
number任意数字1 , -33 , 2.5
string任意字符串‘hello’ , ‘ok’ , ‘你好’
boolean 布尔值 true 或 falsetrue 、 false
字⾯量值只能是字⾯量值值本身
any任意类型1 、 ‘hello’ 、 true …
unknown类型安全的 any 1 、 ‘hello’ 、 true …
never不能是任何值⽆值
void空 或 undefined空 或 undefined
object任意的 JS 对象{name:‘张三’}
tuple元素, TS 新增类型,固定⻓度数组[4,5]
enum枚举, TS 中新增类型enum{A, B}

4. 常⽤类型

4.1. 字⾯量

let a: '你好'		//a的值只能为字符串“你好”
let b: 100		 //b的值只能为数字100a = '欢迎'		//警告:不能将类型“"欢迎"”分配给类型“"你好"”
b = 200 		//警告:不能将类型“200”分配给类型“100”let gender: '男'|'⼥' //定义⼀个gender变量,值只能为字符串“男”或“⼥”
gender = '男'
gender = '未知'	 //不能将类型“"未知"”分配给类型“"男" | "⼥"”

4.2. any

any的含义是:任意类型,⼀旦将变量类型限制为 any ,那就意味着放弃了对该变量的类型检查。

//明确的表示a的类型是any —— 显式的any
let a:any
//以下对a的赋值,均⽆警告
a = 100
a = '你好'
a = false//没有明确的表示b的类型是any,但TS主动推断了出来 —— 隐式的any
let b
//以下对b的赋值,均⽆警告
b = 100
b = '你好'
b = false

注意点: any 类型的变量,可以赋值给任意类型的变量

/* 注意点:any类型的变量,可以赋值给任意类型的变量 */
let a
let x: string
x = a // ⽆警告

4.3. unknown

unknown 的含义是:未知类型。

备注1: unknown 可以理解为⼀个类型安全的 any

备注2: unknown 适⽤于:开始不知道数据的具体类型,后期才能确定数据的类型

// 设置a的类型为unknown
let a: unknown//以下对a的赋值,均正常
a = 100
a = false
a = '你好'// 设置x的数据类型为string
let x: string
x = a //警告:不能将类型“unknown”分配给类型“string”

若就是想把 a 赋值给 x ,可以⽤以下三种写法:

// 设置a的类型为unknown
let a: unknown
a = 'hello'
//第⼀种⽅式:加类型判断
if(typeof a === 'string'){x = a
}
//第⼆种⽅式:加断⾔
x = a as string
//第三种⽅式:加断⾔
x = <string>a

any 后点任何的东⻄都不会报错,⽽ unknown 正好与之相反。

let str1: string = 'hello'
str1.toUpperCase() //⽆警告let str2: any = 'hello'
str2.toUpperCase() //⽆警告let str3: unknown = 'hello';
str3.toUpperCase() //警告:“str3”的类型为“未知”// 使⽤断⾔强制指定str3的类型为string
(str3 as string).toUpperCase() //⽆警告

4.4. never

never 的含义是:任何值都不是,简⾔之就是不能有值, undefined 、 null 、 ‘’ 、 0 都不⾏!

1.⼏乎不⽤ never 去直接限制变量,因为没有意义,例如:

/* 指定a的类型为never,那就意味着a以后不能存任何的数据了 */
let a: never
// 以下对a的所有赋值都会有警告
a = 1
a = true
a = undefined
a = null

2.never ⼀般是 TypeScript 主动推断出来的,例如:

// 指定a的类型为string
let a: string
// 给a设置⼀个值
a = 'hello'if(typeof a === 'string'){a.toUpperCase()
}else{console.log(a) // TypeScript会推断出此处的a是never,因为没有任何⼀个值符合此处的逻辑
}

3.never也可⽤于限制函数的返回值

// 限制demo函数不需要有任何返回值,任何值都不⾏,像undeifned、null都不⾏
function demo():never{throw new Error('程序异常退出')
}

4.5. void

void 的含义是: 空 或 undefined ,严格模式下不能将 null 赋值给 void 类型。

let a:void = undefined
//严格模式下,该⾏会有警告:不能将类型“null”分配给类型“void”
let b:void = null

void 常⽤于限制函数返回值

// ⽆警告
function demo1():void{
}// ⽆警告
function demo2():void{return
}// ⽆警告
function demo3():void{return undefined
}// 有警告:不能将类型“number”分配给类型“void”
function demo4():void{return 666
}

4.6. object

关于 Object 与 object ,直接说结论:在类型限制时, Object ⼏乎不⽤,因为范围太⼤了,⽆意义。

1.object 的含义:任何【⾮原始值类型】,包括:对象、函数、数组等,限制的范围⽐较宽泛,⽤的少。

let a:object //a的值可以是任何【⾮原始值类型】,包括:对象、函数、数组等// 以下代码,是将【⾮原始类型】赋给a,所以均⽆警告
a = {}
a = {name:'张三'}
a = [1,3,5,7,9]
a = function(){}// 以下代码,是将【原始类型】赋给a,有警告
a = null // 警告:不能将类型“null”分配给类型“object”
a = undefined // 警告:不能将类型“undefined”分配给类型“object”
a = 1 // 警告:不能将类型“number”分配给类型“object”
a = true // 警告:不能将类型“boolean”分配给类型“object”
a = '你好' // 警告:不能将类型“string”分配给类型“object”

2.Object 的含义: Object 的实例对象,限制的范围太⼤了,⼏乎不⽤。

let a:Object //a的值必须是Object的实例对象,// 以下代码,均⽆警告,因为给a赋的值,都是Object的实例对象
a = {}
a = {name:'张三'}
a = [1,3,5,7,9]
a = function(){}
a = 1 // 1不是Object的实例对象,但其包装对象是Object的实例
a = true // truue不是Object的实例对象,但其包装对象是Object的实例
a = '你好' // “你好”不是Object的实例对象,但其包装对象是Object的实例// 以下代码均有警告
a = null // 警告:不能将类型“null”分配给类型“Object”
a = undefined // 警告:不能将类型“undefined”分配给类型“Object”

3.实际开发中,限制⼀般对象,通常使⽤以下形式

// 限制person对象的具体内容,使⽤【,】分隔,问号代表可选属性
let person: { name: string, age?: number}// 限制car对象的具体内容,使⽤【;】分隔,必须有price和color属性,其他属性不去限制,有没有都⾏
let car: { price: number; color: string; [k:string]:any}// 限制student对象的具体内容,使⽤【回⻋】分隔
let student: {id: stringgrade:number
}// 以下代码均⽆警告
person = {name:'张三',age:18}
person = {name:'李四'}
car = {price:100,color:'红⾊'}
student = {id:'tetqw76te01',grade:3}
  • 逗号(,):是最常用的分隔方式,和 JavaScript 对象字面量写法一致,简洁且通用。
  • 分号(;):虽功能和逗号相同,但使用场景较少,更多是强调语句的结束。
  • 回车(换行):在属性较多或定义复杂时使用,可提高代码的可读性和可维护性。

4.限制函数的参数、返回值,使⽤以下形式

let demo: (a: number, b: number) => numberdemo = function(x,y) {return x+y
}

5.限制数组,使⽤以下形式

let arr1: string[] // 该⾏代码等价于: let arr1: Array<string>
let arr2: number[] // 该⾏代码等价于: let arr2: Array<number>arr1 = ['a','b','c']
arr2 = [1,3,5,7,9]

4.7. tuple

tuple 就是⼀个⻓度固定的数组。

let t: [string,number]t = ['hello',123]// 警告,不能将类型“[string, number, boolean]”分配给类型“[string, number]”
t = ['hello',123,false]

4.8. enum

enum 是枚举

// 定义⼀个枚举
enum Color {Red,Blue,Black,Gold
}// 定义⼀个枚举,并指定其初识数值
enum Color2 {Red = 6,Blue,Black,Gold
}console.log(Color)
/*{0: 'Red',1: 'Blue',2: 'Black',3: 'Gold',Red: 0,Blue: 1,Black: 2,Gold: 3}
*/
console.log(Color2)
/*{6: 'Red',7: 'Blue',8: 'Black',9: 'Gold',Red: 6,Blue: 7,Black: 8,Gold: 9}
*/// 定义⼀个phone变量,对其进⾏限制
let phone: {name:string,price:number,color:Color}phone = {name:'华为Mate60',price:6500,color:Color.Red}
phone = {name:'iPhone15Pro',price:7999,color:Color.Blue}if(phone.color === Color.Red){console.log('⼿机是红⾊的')
}

5. ⾃定义类型

⾃定义类型,可以更灵活的限制类型

// 性别的枚举
enum Gender {Male,Female
}// ⾃定义⼀个年级类型(⾼⼀、⾼⼆、⾼三)
type Grade = 1 | 2 | 3// ⾃定义⼀个学⽣类型
type Student = {name:string,age:number,gender:Gender,grade:Grade
}// 定义两个学⽣变量:s1、s2
let s1:Student
let s2:Students1 = {name:'张三',age:18,gender:Gender.Male,grade:1}
s2 = {name:'李四',age:18,gender:Gender.Female,grade:2}

6. 抽象类

常规类:

class Person {name: stringage: numberconstructor(name:string,age:number){this.name = namethis.age = age}
}
const p1 = new Person('张三',18)
const p2 = new Person('李四',19)
console.log(p1)
console.log(p2)

继承:

// Person类
class Person { ... }
// Teacher类继承Person
class Teacher extends Person { ... }
// Student类继承Person
class Student extends Person { ... }
// Person实例
const p1 = new Person('周杰伦',38)
// Student实例
const s1 = new Student('张同学',18)
const s2 = new Student('李同学',20)
// Teacher实例
const t1 = new Teacher('刘⽼师',40)
const t2 = new Teacher('孙⽼师',50)

抽象类:不能去实例化,但可以被别⼈继承,抽象类⾥有抽象⽅法

// Person(抽象类)
abstract class Person { ... }// Teacher类继承Person
class Teacher extends Person {// 构造器constructor(name: string,age: number){super(name,age)}// ⽅法speak(){console.log('你好!我是⽼师:',this.name)}
}// Student类继承Person
class Student extends Person { ... }// Person实例
// const p1 = new Person('周杰伦',38) // 由于Person是抽象类,所以此处不可以new Person的实例对象

7. 接⼝

接⼝梳理:

1.接⼝⽤于限制⼀个类中包含哪些属性和⽅法:

// Person接⼝
interface Person {// 属性声明name: stringage: number// ⽅法声明speak():void
}// Teacher实现Person接⼝
class Teacher implements Person {name: stringage: number// 构造器constructor(name: string,age: number){this.name = namethis.age = age}// ⽅法speak(){console.log('你好!我是⽼师:',this.name)}
}

2.接⼝是可以重复声明的:

// Person接⼝
interface PersonInter {// 属性声明name: stringage: number
}
// Person接⼝
interface PersonInter {// ⽅法声明speak():void
}// Person类继承PersonInter
class Person implements PersonInter {name: stringage: number// 构造器constructor(name: string,age: number){this.name = namethis.age = age}// ⽅法speak(){console.log('你好!我是⽼师:',this.name)}
}

3.【接⼝】与【⾃定义类型】的区别:

接⼝可以:

  1. 当⾃定义类型去使⽤;

  2. 可以限制类的结构;

⾃定义类型:

  1. 仅仅就是⾃定义类型;
// Person接⼝
interface Person{// 应该具有的属性name: stringage: number// 应该具有的⽅法speak():void
}// Person类型
/*type Person = {// 应该具有的属性name: stringage: number// 应该具有的⽅法speak():void}
*/// 接⼝当成⾃定义类型去使⽤
let person:Person={name:'张三',age:18,speak(){console.log('你好!') }
}

4.【 接⼝ 】与【 抽象类 】的别:

抽象类:

  1. 可以有普通⽅法,也可以有抽象⽅法 ;
  2. 使 ⽤ extends 关 键字去继承抽 象 类 ;

接⼝中:

  1. 只能能有抽象法 ;
  2. 使⽤ implements 关键字去实现接⼝

抽象类举例:

// 抽象类 —— Person
abstract class Person {// 属性name:stringage:number// 构造器constructor(name:string,age:number){this.name = namethis.age = age}// 抽象⽅法abstract speak():void// 普通⽅法walk(){console.log('我在⾏⾛中....')}
}// Teacher类继承抽象类Person
class Teacher extends Person {constructor(name:string,age:number){super(name,age)}speak(){console.log(`我是⽼师,我的名字是${this.name}`)}
}

接⼝举例:

// 接⼝ —— Person,只能包含抽象⽅法
interface Person {// 属性,不写具体值name:stringage:number// ⽅法,不写具体实现speak():void
}
// 创建Teacher类实现Person接⼝
class Teacher implements Person {name:stringage:numberconstructor(name:string,age:number){this.name = namethis.age = age}speak(){console.log('我在⻜快的⾏⾛中......')}
}

8. 属性修饰符

readonly只读属性属性⽆法修改
public公开的可以在类、⼦类和对象中修改
protected受保护的可以在类、⼦类中修改
private私有的可以在类中修改

9. 泛型

定义⼀个函数或类时,有些情况下⽆法确定其中要使⽤的具体类型(返回值、参数、属性的类型不能确 定),此时就需要泛型了

举例: <T> 就是泛型,(不⼀定⾮叫 T ),设置泛型后即可在函数中使⽤ T 来表示该类型:

function test<T>(arg: T): T{
return arg;
}// 不指名类型,TS会⾃动推断出来
test(10)// 指名具体的类型
test<number>(10)

泛型可以写多个:

function test<T, K>(a: T, b: K): K{return b;
}
// 为多个泛型指定具体⾃值
test<number, string>(10, "hello");

类中同样可以使⽤泛型:

class MyClass<T>{prop: T;constructor(prop: T){this.prop = prop;}
}

也可以对泛型的范围进⾏约束:

interface Demo{length: number;
}
// 泛型T必须是Demo的⼦类,即:必须拥有length属性
function test<T extends Demo>(arg: T): number{return arg.length;
}test(10) // 类型“number”的参数不能赋给类型“Demo”的参数
test({name:'张三'}) // 类型“{ name: string; }”的参数不能赋给类型“Demo”的参数test('123')
test({name:'张三',length:10}

10. 断言

断言: 其实就是告诉 TS, 我知道我自己在做什么, 不要你管

const box = document.querySelector('.box')
console.log(box.innerHTML)
// TS中会报错box可能未null

类型断言

方式1: 利用 as 书写断言

语法 : 数据 as 类型

const box = document.querySelector('.box')
console.log((box as HTMLDivElement).innerHTML)

方式2 : 利用 <> 书写断言

语法 : <类型>数据

const box = document.querySelector('.box')
console.log((<HTMLDivElement>box).innerHTML)

对某一个数据断定为某一个类型,这样就可以直接按照该数据类型去调用属性和方法了。

非空断言

也就是在开发的过程中, 忽略有可能出现的 undefined 和 null 类型,这里我们使用 ! 来做这个事情

const box = document.querySelector('.box')
console.log(box!.innerHTML)

当 box 只有可能是 一个内容 或者 undefined 或者 null 的时候,我们可以用!进行断言,告诉他 box 不可能是 null 或者 undefined

利用 ! 排除了 undefined 和 null 的可能

确定赋值断言

在开发中还有这样一种情况,就是我们在初始定义某一个变量的时候,有可能是不赋值的,在后面的代码或者函数内对其进行赋值, 然后再使用。

// 初始化的时候不进行赋值
let n: number// 通过调用这个函数对 n 进行赋值操作
function init () { n = 100 }
init()// 这里使用一下 x
console.log(x.toFixed(2))// 结果:然后我们就发现, TS 又提示错误了

这是因为 TS 不太清楚你的 init 函数调用以后会对 x 进行赋值,所以就会告诉你,你还没有赋值呢,就调用了 toFixed 方法

这个时候,我们就可以使用确定赋值断言,还是使用 !

// 初始化的时候不进行赋值
let n!: number// 通过调用这个函数对 n 进行赋值操作
function init () { n = 100 }
init()// 这里使用一下 x
console.log(x.toFixed(2))

在初始化的时候, 给变量后面加一个 !,也就是告诉 TS,这个变量我一定会百分之一万赋值的,你少管

const 断言

这个有点和我们定义变量的关键字差不多,但是又不太一样,小伙伴不要搞混淆了哦
我们先来看这个代码吧

let n: number = 100 as const
let s: string = 'hello world' as const

这样一来, 我们定义的 n 和 s 就不能被更改了

我直接用 const 定义变量不好吗, 为什么 … ( 如果不能骂街, 那我无话可说 )

我们再来看下一段代码

const obj = { name: 'Jack', age: 18 }

这个就是用 const 定义的一个变量,只不过值是一个引用数据类型了

我们的 const 只能保证 obj 不会被改变, 但是 obj 内部的子级数据是不会被限制的

如果我们想让 obj 内的每一个成员都是只读的属性,不允许被更改呢

只能是在书写接口的时候,把每一个属性都定义为 readonly

O(∩_∩)O哈哈~,我的 const 断言有用武之地了

const obj = { name: 'Jack', age: 18 } as const

这样一来,我们 obj 内 所有的子级数据就都不能被更改了

相关文章:

  • 阿里云 AI 搜索开放平台:RAG智能化工作流助力 AI 搜索
  • 【数据结构和算法】6. 哈希表
  • Hive中Map和Reduce阶段的分工
  • C++笔记-stack_queue(含deque,priority_queue,仿函数的讲解)
  • NHANES指标推荐:CTI
  • NOIP2012提高组.同余方程
  • Java基础复习(JavaSE进阶)第九章 网络编程
  • 考研单词笔记 2025.04.23
  • 脂质体挤出器有哪些知名品牌?
  • 2025深圳中兴通讯安卓开发社招面经
  • 【金仓数据库征文】从Oracle到KingbaseES的语法兼容与迁移
  • Spring Boot 项目:如何在 JAR 运行时读取外部配置文件
  • 【每日八股】复习计算机网络 Day4:TCP 协议的其他相关问题
  • 【Java学习笔记】random的使用
  • 并行RANSAC平面拟合(C++)
  • [特殊字符]‍[特殊字符]Linux驱动开发入门 | 并发与互斥机制详解
  • ActiveMQ 核心概念与消息模型详解(二)
  • centos7 设置EMQX开机自启动(创建init.d脚本来设置emqx的自启动服务)
  • 文档构建:Sphinx全面使用指南 — 实战篇
  • leetcode 二分查找应用
  • 刘国中:毫不松懈巩固拓展脱贫攻坚成果,全力以赴抓好农业防灾减灾工作
  • 中国海油总裁:低油价短期影响利润,但也催生资产并购机会
  • 中行一季度净赚超543亿降2.9%,利息净收入降逾4%
  • 西夏文残碑等文物来沪,见证一段神秘灿烂的历史
  • 众信旅游:去年盈利1.06亿元,同比增长228.18%
  • 四川省社科联期刊:不建议在读硕士、博士将导师挂名为第一作者