「未完...」
一、TS核心语法
基础知识
TypeScript = JS + 静态类型校验(代码执行前能错误预警)
TS为JS的超集。
TS可以类型判断、类型推断
TS优势:
- 更容易帮我们发现程序中的问题
- 语法提示更加完善
- 语义更强,代码可读性更高
ts不能直接执行,需要编译成js才能执行
npm install typescript -g
安装之后,可以使用tsc将ts编译为js
安装ts-node可在node环境执行ts文件
npm i ts-node -g
ts-node demo.ts
ts-node 本身并不支持自动地监听文件变更然后重新执行,而这一能力又是某些项目场景下的刚需,如 NodeJs API 的开发。因此,我们需要 ts-node-dev 库来实现这一能力。ts-node-dev 基于 node-dev(你可以理解一个类似 nodemon 的库,提供监听文件重新执行的能力) 与 ts-node 实现,并在重启文件进程时共享同一个 TS 编译进程,避免了每次重启时需要重新实例化编译进程等操作。
首先,我们还是在全局安装:
npm i ts-node-dev -g
ts-node-dev 在全局提供了 tsnd 这一简写,你可以运行 tsnd 来检查安装情况。最常见的使用命令是这样的:
ts-node-dev --respawn --transpile-only app.ts
TS类型
常用的24种TS类型 (注意区分大小写)
1.基本类型:
number,string,boolean,symbol,null,undefined
2.根类型:
Object, {} (这两种数据类型一样,一个全写一个简写)
根类型可接受除undefined和null之外的任意类型,Object只能赋给任意值, 不能调用方法,和any是不一样的
示例:
3.对象类型:
Array, object(注意大小写), function
示例:
4.枚举:
enum
-
枚举的定义:用来存放一组固定的常量的序列
-
枚举的分类:字符串枚举、数字枚举
// 数字枚举 // 可以不用给每个属性赋值 enum Week { Monday = 1, Tuesday, Wensday, ThirsDay, Friday, Sarturday, Sunday } console.log(Week.Monday) console.log(Week["Monday"]) console.log(Week[1]) console.log(Week[5]) // 字符串枚举 enum WeekEnd { Monday = "Monday", Tuesday = "Tuesday", Wensday = "Wensday", ThirsDay = "ThirsDay", Friday = "Friday", Sarturday = "Sarturday", Sunday = "Sunday" } console.log(WeekEnd.Monday) console.log(WeekEnd["Monday"]) /** 打印结果 1 1 Monday Friday Monday Monday **/ -
为什么要使用枚举类型?
解决多次if / switch判断中值的语义化的问题
-
常量解决
-
使用常量带来的局限性
方法参数不能定义为具体类型,只能初级使用number,string基本类型代替,降低了代码的可读性和可维护性
-
-
使用枚举的好处
- 有默认值和可以自增值,节省编码时间
- 语义更清晰,可读性增强
因为枚举是一种值类型的数据类型,方法参数可以明确参数类型为枚举类型
5.其他特殊类型:
any,unknown,never,void,元组 ( tuple),可变元组
-
never类型是为了避免出现未来扩展新的类没有对应类型的实现,目的是写出类型绝对安全的代码
// never类型 // dataFlowAnalysisWithNever 方法穷尽了 DataFlow 的所有可能类型。 // 使用 never 避免出现未来扩展新的类没有对应类型的实现。,具的就是写出类型绝对安全的 type DataFlow = string | number function dataFlowAnalysisWithNever(dataFlow: DataFlow) { if (typeof dataFlow === "string") { console.log("字符串类型:", dataFlow.length); } else if (typeof dataFlow === "number") { console.log("数值类型:", dataFlow.toFixed(2)); } else { let data = dataFlow } } dataFlowAnalysisWithNever("string") dataFlowAnalysisWithNever(3.199923) -
any, unknown的两点区别和应用场景
any 和 unknown 在开发中和第三方包源码底层经常看到,弄清楚它们的区别很重要。
相同: any 和unknown 可以是任何类的父类,所以任何类型的变量都可以赋值给 any 类型或unknown类型的变量。
不同点1: any 也可以是任何类的子类,但 unknown 不可以,所以 any 类型的变量都可以赋值给其他类型的变量
不同点2: 不能拿 unknown 类型的变量来获取任何属性和方法,但 any 类型的变量可以获取任意名称的属性和任意名称的方法
any 比较典型的应用场景: 1.自定义守卫 2.需要进行 as any 类型断言的场景
// Vue3 源码 片段 // any 的应用场景--自定义守卫中使用 any export function isRef(r: any): r is Ref f return Boolean(r && r.__v_isRef true) // any类型的 r 参数在雨数内部获取属性unknown 一般用作函数参数: 用来接受任意类型的变量实参,但在函数内部只用于再次传递或输出结果,不获取属性的场景 (使用unknown的场景都可以使用any来替代)
// Vue3 源码 片段 ref 的 unknown 参数 function ref(value?: unknown) { return createRef(value) // 函数内部只用于再次传递值,不获取属性 }
6.合成类型:
联合类型(Union),交叉类型
// 联合类型
let str: string | number = 3
console.log("str:", str)
// 交叉类型
type Obj1 = { username: string }
type Obj2 = { age: number }
let obj1: Obj1 = { username: "abc" }
let obj2: Obj2 = { age: 25 }
let obj3: Obj1 & Obj2 = { username: "kaka", age: 25 }
7.字面量数据类型:
接口和应用场景
接口: 另一种定义对象类型的类型
接口应用场景:
(1)一些第三方包或者框架底层源码中有大量的接口类型
(2)提供方法的对象类型的参数时使用
(3)为多个同类别的类提供统一的方法和属性声明
如何定义接口
继承接口
新的接口只是在原来接口继承之上增加了一些属性或方法,这时就用接口继承