TypeScript
TypeScript的编译环境:
方法一
ts代码需要通过tsc (TypeScript Compiler)转换为js代码,才能在浏览器中运行
方法二
通过webpack,配置本地的TypeScript编译环境和开启一个本地服务,可以直接运行在浏览器上;
-
npm init生成package.json
-
安装webpack
-
在src文件里编写ts代码
-
新建webpack.config.js配置出入口文件和模块对应的加载规则(见代码)
-
tsc --init生成tsconfig.json文件
webpack-dev-server可以搭建本地服务器
方式三
通过ts-node库,为TypeScript的运行提供执行环境
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KbabRRhb-1656556677113)(E:\工作\产品经理\Vue3\class_image\TypeScript的编译环境.png)]
变量的声明
tslint 规范ts代码
tslint --init//安装tslint
类型推导:默认情况下进行赋值时,会将赋值的值的类型,作为前面标识符的类型,这个过程就是类型推导
var name: string = "why" name是字符串类型
var name: String = "why" name是String类
TypeScript的数据类型
- 数组
// 在TypeScript中 数组存放的内容的类型要一样的
const names: Array<string> = []//不推荐 会跟jsx冲突<button></button>
const names2: string[] = []//常用
names.push("123")
- null
null类型只能赋值为null,当一个变量为null时,要有类型注解,不要用类型推导
-
Symbol
const title1 = Symbol("title") const title2 = Symbol("title") const info = { [title1]: "程序员", [title2]: "老师" }
-
any
-
unknow
function foo() {return "abc"} function bar() {return 123} let flag = true // 没有类型推导就要写类型注解 // 不能明确函数返回什么类型 let result: unknown if (flag) {result = foo() } else {result = bar() }
// any类型可以赋值给任意类型
// unknown类型只能赋值给any和unknown类型
let message: any = result
let num: unknown = result
- void 当一个函数没有返回值的时候,返回值的类型就是void
- never 函数永远也不会返回结果 或者 函数只抛出异常
- tuple 元组 多种元素的组合
// 需求:知道数组里面的元素是什么类型
// 数组写法 无法知道元素类型
const info: any[] = ["why", 18, 1.88]
const name = info[0]
// 元组写法
const info2: [string, number, number] = ["why", 18, 1.88]
const name1 = info2[0]
console.log(name.length)
// tuple应用场景
function useState(state: any) {
let currentState = state
const changeState = (newState: any) => {
currentState = newState
}
// changeState 对应 (newState: any) => void 函数类型
const tuple: [any, (newState: any) => void] = [currentState, changeState]
return tuple
}
const [counter, setCounter] = useState(10)
setCounter(1000)
类型补充
- 参数和返回值
// 给参数加类型注解
// 给返回值加上类型注解,也可以不加,会自动推导
function sum(num1: number, num2: number): number {
return num1 + num2
}
sum(12, 23)
- 上下文中的函数 item可以根据上下文环境推导出来,可以不加类型注释
const names = ["abc", "cba", "nba"]
// 上下文中的函数 item可以根据上下文环境推导出来,可以不加类型注释
names.forEach((item) => {
console.log(item.split("0", 1))
})
-
对象类型
// 对象类型的类型注解
// point 形参
// z?:number 表示 z 是可选的
function printPoint(point: { x: number, y: number, z?: number }) { console.log(point.x) console.log(point.y) console.log(point.z) } printPoint({ x: 12, y: 76 }) printPoint({ x: 12, y: 76, z: 111 })
-
联合类型
使用联合类型的值id时,对id的操作要小心 注意类型判断
- 类型别名
上面对象类型作为类型注解可能太长,可以用类型别名抽取出来
type PointType = { x: number, y: number, z?: number }
- 类型断言
- 可以标明拿到的HTML元素是具体的哪种HTML元素
const el = document.getElementById("why") as HTMLImageElement
- 类型断言缩小范围,从而能够调用子类的方法
class Person {
}
class Student extends Person {
studying() { }
}
function sayHello(p: Person) {
// p.studying()
// 类型断言缩小范围,从而能够调用Student类的方法
(p as Student).studying()
}
const stu = new Student()
sayHello(stu)
-
非空类型断言
在可能为undefined的值后面加上 !
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vkw53ggw-1656556677115)(E:\工作\产品经理\Vue3\class_image\非空类型断言.png)]
-
可选链的使用 ?.
-
?? 是一个逻辑操作符,当操作符的左侧是 null 或者 undefined 时,返回其右侧操作数,
否则返回左侧操作数let message: string | null = null const content = message ?? "你好啊,李银河" // 如果message没有值 就取默认值"你好啊,李银河"
!! 操作符
const message = "Hello Message"
// const flag = Boolean(message)
// console.log(flag)
//等同于
const flag = !!message //!message message字符串本来对应的布尔值是true 加上!转为布尔值,同时值为false,所以要再取反
console.log(flag)
-
字面量类型
字符串也可以作为类型 这就是字面量类型
字面量类型要结合联合类型来使用才有意义
-
字面量推理
type Method = 'GET' | 'POST'//定义Method类 字面量类型 function request(url: string, method: Method) { } type Request = { url: string, method: Method } //给对象限制类型 const options:Request = { url: "http://www.baidu.com", method: "POST" } request(options.url, options.method )
类型缩小
-
typeof类型缩小
-
平等的类型缩小 === == !== switch
-
instanceof 检查一个值是否是另一个值的“实例”
-
in 如果指定的属性在指定的字面量对象中,则in 运算符返回true;
if ('swimming' in animal) { animal.swimming() } else { animal.running() }
函数的补充
函数的类型注解 () => void
function bar(fn: () => void) {
fn()
}
可选类型必须写在必选类型的后面
function foo(x: number, y?: number) {
}
foo(20, 30)
foo(20)
剩余参数
function sum(...nums: number[]) {
let total = 0
for (const num of nums) {
total = total + num
}
return total
}
sum(20, 10)
sum(20, 30, 40)
不确定的this类型
type NameType = {
name: string
sayHello: () => void
}
// 通常TypeScript会要求我们明确的指定this的类型
function sayHello(this: NameType) {
console.log(this.name)
}
const info: NameType = {
name: "why",
// 将其放到了info中,
sayHello
}
// 通过info去调用,this依然是指向info对象的
info.sayHello()
// 但是对于TypeScript编译器来说,这个代码是非常不安全的,因为我们也有可能直接调用函数,或者通过别的对象来但是对于TypeScript编译器来说,这个代码是非常不安全的,因为我们也有可能直接调用函数,或者通过别的对象来
// 调用函数
函数的重载
函数的名称相同,但是参数不同的几个函数,就是函数的重载
在函数的重载中,实现函数不能直接被调用,必须有对应的函数声明
// 函数的声明
function add(num1: number, num2: number): number;//没有函数体
function add(num1: string, num2: string): string;
// 函数的实现
function add(num1: any, num2: any): any {
return num1 + num2
}
const result = add(20, 30)
console.log(result)//50
// 在函数的重载中,实现函数不能直接被调用
// add({ name: 'why' }, { age: 18 })
注:优先使用联合类型,如果联合类型比较麻烦,再使用函数的重载