TypeScript 是 JavaScript 的一个超集,它添加了静态类型和其他一些功能,使得代码更易于维护和阅读。以下是 TypeScript 的一些主要特点:
- 静态类型
- 接口
- 泛型
- 枚举
- 类型推断
- 类
- 模块
- 类型别名
- 类型守卫
- 声明文件
TypeScript的优势
- 编译时静态类型检查
- 自动提示更清晰明确
- 引入泛型和一系列的TS特有类型
- 强大的
t.ts声明文件 - 轻松编译成JS文件
- 灵活性高
类型注解和类型推导
let data: number = 0
// data = '222' // 提示报错
let money = "abc" // 类型系统会推断为string
// money = 1111 // 提示报错
-
区别:
- 类型注解:定义时固化类型
- 类型推导:根据值的类型反过来推导类型
-
优点
TS编译和编译优化
-
正常情况下,TS检测变量,会把所有变量都当成全局变量检测
- 解决方法
- 在代码结尾添加
export {}作用域- 表明当前变量作用域是当前文件
- 在代码结尾添加
- 解决方法
-
TS代码默认不能被正常运行
- 不能使用
node直接运行 - 浏览器也不能直接加载运行
- 不能使用
-
运行方式
|------------| tsc |------------|
| Javascript |----------------> | Typescript |
|------------| |------------|
TS的24种类型
-
基本类型
- number
- string
- boolean
- symbol
- null
- undefined
-
根类型
- Object
-
对象类型
- Array
- object
- function
-
特殊类型
- any
- unknown
- never
- void
- tuple
- 可变元组
-
合成类型
- 联合类型
- 交叉类型
-
字面量数据类型
// 联合数据类型
let dat: string | number = 'a'
// 交叉类型,可以合并在一起
type Obj1 = { username: sring}
type Obj2 = { age: number}
let obj1:Obj1 = { username: 'aaa' }
let obj2:Obj2 = { age: 22 }
let obj3: Obj1 & Obj2 = { username: 'ww', age: 3 }
any和unknown的区别和应用场景
-
相同点
any和unknown可以是任何类的父类- 所以任何类型的变量都可以赋值给
any类型或unknown类型的变量
- 所以任何类型的变量都可以赋值给
-
不同点
any也可以是任何类的子类,但unknown不可以- 所以
any类型的变量都可以赋值给其它类型的变量
- 所以
- 不能拿
unknown类型的变量来获取任何属性和方法,但any类型的变量可以获取任意名称的属性和任意名称的方法
-
any比较典型的应用场景- 自定义守卫
- 需要进行
as any类型断言的场景
-
unknown的应用场景- 一般用作函数参数
- 用来接受任意类型的变量实参
- 但在函数内部只用于再次传递或输出结果,不获取属性的场景
- 一般用作函数参数
export function isRef(r: any): r is Ref {
return Boolearn(r && r.__v_isRef === true) // any类 型的r参数在函数内部获取属性
}
function ref(value?: unknown) {
return createRef(value) // 函数内部只用于再次传递,不获取属性
}
接口 和应用场景
-
接口
- 另一种定义对象类型的类型
-
接口的应用场景
- 一些第三方包或者架构底层源码中有大量的接口类型
- 提供方法的对象类型的参数时使用
- 为多个同类别的类提供统一的方法和属性声明
-
如何定义接口
- 接口中的类型的方法都只有声明,没有实现
-
接口继承
- 新的接口知识在原来的接口继承上增加了一些属性或方法
-
接口的可索引签名
- 用来接收不确定字段名
interface Product {
name: string
price: number
account: number
[x: string]: any // string, 支持各种类型,如果是number,则只支持number
}
let p: Product = {
name: "1",
price: 1,
account: 1,
describe: 'ok', // Ok
[Symbol('stockno')]: 33, // Ok
100: 1, // Ok
true: "o" // Ok
}
索引访问类型
- keyof
- keyof 类型
- 获取类型的所有属性名组成的联合类型
- keyof 类型
type symid = Symbol('productno')
interface Product {
[symid]: string
name: string
price: number
account: number
buy(): string
}
type A = Product['price']
type B = Product['price' | 'name']
type S = Product[typeof symid]
type PKeys = keyof Product // 获取所有属性名组成的联合类型
// "name" | "price" | "account" | "buy" | typeof symid
- typeof
- typeof variable
- 获取变量对应的类型
- typeof variable
void 类型
null 和 undefined
-
如果希望没变量没赋值还不报错,使用
undefined的联合类型 -
?会将字段的类型变成字段类型和undefined的联合类型 -
哪些类型可以接受
undefined- any
- unknown
- undefined
-
那些类型可以接受
null- any
- unknown
- null
typeof null // {}
typeof undefined // undefined
let str: string | undefined
console.log("str: ", str)
function func(data?: string) {
data?.toString()
data!.toString() // ! 会忽略 undefined
if (data) {
data.toString()
}
}
常见取值错误
let obj = { username: 'wu', age: 22 }
let username = "username" // 出问题
const username = "username"
let u = obj[username]
TS函数与JS函数
TS函数类型解构
type TypStuobj = { username: string, age: number, phone: string }
function info(stuInfo: TypStuobj) {
console.log("name: ", stuInfo.username, "age: ", stuInfo.age)
}
// 只需要username和phone,解构
function info({ username, phone }: TypStuobj) {
console.log("name: ", stuInfo.username, "age: ", stuInfo.age)
}
interface和type的区别
-
type和interface类似
- 都用来定义类型
-
区别
- 定义类型的范围不同
interface- 定义对象类型
- 接口当名字的函数类型
type- 可以定义任何类型
- 基础类型
- 联合类型
- 交叉类型
- 元组
- 可以定义任何类型
- 接口可以
extends一个或多个接口或实现一个或多个接口
- 也可以继承
type type类型没有继承功能interface可以继承type,但很少见
- 用
type交叉类型&
- 可让类型中的成员合并成一个新的
type类型 interface不能交叉合并
元组
- 满足下面3点的数组就是元组
- 在定义的时候每个元素的类型都确定
- 元素值的数据类型必须是当前元素定义的类型
- 元组值的个数必须和定义时个数相同