ts的优势
- 编译时静态类型检测:函数或方法传参或变量赋值不匹配时,会出现编译错误提示,规避了开发期间的大量低级错误,省时,省力。
- 自动提示更清晰明确。因为在编译阶段就确定了变量类型,所以语法提示更清晰。
- 引入了泛型和一系列的TS特有的类型。
- 强大的d.ts声明文件,声明文件像一个书的目录一样,清晰直观展示了依赖库文件的接口,type类型,类,函数,变量等声明。
- 轻松编译成JS文件,即使TS文件有错误,绝大多数情况也能编译出JS文件。
- 灵活性高:尽管TS是一门强类型检查语言,但也提供了any类型和as any断言,这提供了TS的灵活度
类型推导和类型注解的区别
类型推导在定义时未约束类型,类型注解在定义时就被约束了类型。
Object、{}和object区别
Object
是根类型(number, string, boolean, undefined, null, symbol, bigint),但是null, undefined不能赋值给Object类型。{}
是Object的简写。object
只能赋值对象类型(数组,对象,函数等等)。null, undeined也不能进行赋值给object类型。
联合类型(|), 交叉类型(&)
- 当联合类型被赋值后,他的类型就已经是确定的独立类型了,而不是联合类型了。
- 类型想要交叉就必须有交集才可以。
never如何使用和呈现
never 表示永远不会发生值的类型。
如果我们指定一个函数参数为string和number的联合类型,并在其中做出string和number的判断,那么else部分获取该参数就是never的类型。
never
类型的一个重要特点是,可以赋值给任意其他类型。
function f(): never {
throw new Error("Error");
}
let v1: number = f(); // 不报错
let v2: string = f(); // 不报错
let v3: boolean = f(); // 不报错
为啥使用枚举
用于存放一组固定的常量序列。
- 如果枚举的值是数字类型,那么它具有双重映射,既可以使用key获取value,也可以使用value获取key。
- 如果枚举的值是字符串类型,那么它只具有单层映射,即只能通过key获取value。
没有枚举之前我们只能规定特定类型,降低了代码的可读性和可维护性。
any和unknown的区别
- any可以是任何类型的父类型也可以是任何类型的子类型。
let a: any = "1"
// any可以赋值给任何类型变量 (就好比后端返回的类型为any,然后赋值给前端中的一个特定类型的变量)
let b:number = a
- unknown可以是任何类型的父类型,但是不能是任何类型的子类型。
let a1: unknown = 1
let b: string = a1 // error
- 不能使用unknown类型的变量获取任何属性和方法,但是可以使用any类型的变量获取属性和方法。
unknown使用场景:一般用于函数参数类型约束,并且该参数用于内部函数参数传递,不获取属性和方法。
function bar(params:any) {
console.log(params)
}
function foo(params: unknown) {
return bar(params)
}
接口
定义对象类型。
优点
- 可以继承
- 类可以实现接口。相同类型的类可以实现相同接口,统一定义一个接口让若干相同类型的类实现。(为多个同类别的类统一提供方法和属性声明)
- 可索引签名。我们在定义可索引签名时,值类型一定要兼容具体的接口属性值类型。
interface List {
// 这里的key为string并不是表示对象键名必须是string类型
[key: string]: any
}
const list: List = {
1: "1",
false: "1",
[Symbol()]: "1",
key: "1"
}
- 同名接口会进行合并。
- 获取接口属性类型。
interface List {
[symbolId]: 1,
name: string,
age: number
}
// 这个就好比枚举属性值可以赋值给枚举类型一样
type t1 = List["name"] // string
type t2 = List["name" | "age"] // string | number
type t3 = List[typeof symbolId] // 1
- 获取接口属性字面量类型。
type t4 = keyof List // typeof symbolId | "name" | "age" | "fn"
type AllKeys<T> = T extends any ? T : never
type t5 = AllKeys<keyof List>
ts中的undefined, null
在js中null 表示的是:“定义了但是为空”。所以,在实际编程时,我们一般不会把变量赋值为 undefined,这样可以保证所有值为 undefined 的变量,都是从未赋值的自然状态。
在ts中如果我们将undefined,null赋值给指定类型的变量他将存在编译错误(在开启了strictNullChecks
属性时)这就强制不让我们给已经决定类型的变量赋值undefined,null。如果想要赋值就必须使用联合类型将undefined或者null设置进去。
let s:string = null; // error
let s1:string | null = null
undefined只能赋值给undefined, any, unknown类型,null只能赋值给 null, any, unknown类型。
动态属性获取对象属性编译错误
- 变量属性充当动态属性获取对象属性出现编译错误。
let name = "name"
const obj = {
name: "zh",
age: 18
}
const n = obj[name] // error, 因为name变量可能会发生变化,使用const定义即可。
- 指定对象类型为object/Object时,再通过动态属性获取对象属性时出现编译错误。因为object类型不能进行解析赋值后的对象属性(即不能准确解析具有的属性)。
const name = "name"
const obj: object = {
name: "zh",
age: 18
}
const n = obj[name] // error
interface 与 type区别
- 定义范围不同
- interface只能定义对象类型或者接口当名字的函数类型。
- type可以定义任何类型,包括基本类型,联合类型,交叉类型,元组。
- 接口可以继承其他接口和type,类可以实现接口,但是type没有继承功能。
- 接口可以合并声明,相同名称的接口可以合并,但是type不能。
约束数组元素不改变
使用断言。
const a = [1,2,3] as const
a[0] = 1 // error
可变元组
我们知道元组是一个固定数量和确定类型的数组。
我们可以通过...any[]
形式定义一个可变元组。使用于前几个元素类型固定,而且是不固定长度的数组变量。
const users: [string, number, boolean, ...any[]] = ["1", 1, true, 1, null, undefined]
为可变元组元素命名。主要是可以更直观的表达每个元素的意义。
const [name, age, sex, ...rest]: [_name: string, _age: number, _sex: number, ...rest: any[]] = ["zh", 20, 1, "669638556@qq.com"]
ts中getter和setter的意义
主要是对属性的赋值做约束。一般不在构造函数中进行约束,一般构造函数直接进行属性赋值,不做逻辑处理。
tsconfig.json
往期年度总结
往期文章
- 你有了解过原生css的scope?
- 现在比较常用的移动端调试你知道哪些?
- 众多跨标签页通信方式,你知道哪些?(二)
- 众多跨标签页通信方式,你知道哪些?
- 反调试吗?如何监听devtools的打开与关闭
- 因为原生,选择一家公司(前端如何防笔试作弊)
- 结合开发,带你熟悉package.json与tsconfig.json配置
- 如何优雅的在项目中使用echarts
- 如何优雅的做项目国际化
- 近三个月的排错,原来的憧憬消失喽
- 带你从0开始了解vue3核心(运行时)
- 带你从0开始了解vue3核心(computed, watch)
- 带你从0开始了解vue3核心(响应式)
- 3w+字的后台管理通用功能解决方案送给你
- 入职之前,狂补技术,4w字的前端技术解决方案送给你(vue3 + vite )
专栏文章
结语
本篇文章到此就结束了,欢迎在评论区交流。
🔥如果此文对你有帮助的话,欢迎💗关注、👍点赞、⭐收藏、✍️评论, 支持一下博主~