TS语法以及类型
js和ts的区别
1 . 动态编程语言和静态编程语言的区别
- js属于动态类型的编程语言
- 边解析边执行的语言, 错误只能在运行阶段发现
- ts属于静态编程的语言
- 先编译(编译成js),再执行(不能直接执行, TSC工具将ts转换为js)
2 . 兼容性: ts包含js(js所有语法ts都支持)
3 . ts 有类型约束
- ts有类型的支持, 有强大的代码提示(在写代码的时候就能发现问题)
4 . ts的前端生态
- vue : vue3源码使用TS重写
- React : TS + Hooks
- Angular : 默认支持 TS
搭建 TypeScript 运行环境
全局安装编译 TS 的工具包
安装包:npm i -g typescript
- typescript 包:用来编译 TS 代码的包,提供了
tsc
命令,实现了ts -> js
的转化 - 验证是否安装成功:
tsc –v
(查看 typescript 的版本)
注意:Mac 电脑安装全局包时,需要添加 sudo
获取权限:sudo npm i -g typescript
编译并运行 TS 代码
步骤
创建ts文件。例如 hello.ts 文件(注意:TS 文件的后缀名为
.ts
)编译。将 TS 编译为 JS
在终端中输入命令,
tsc hello.ts
(此时,在同级目录中会出现一个同名的 JS 文件)执行 JS 代码。
- 在node中运行。在终端中输入命令,
node hello.js
- 在浏览器中运行。
- 在node中运行。在终端中输入命令,
拓展:在线运行
https://www.typescriptlang.org/play
环境变量
npm bin -g
可以查看全局安装的路径
环境变量 path 中有此路径即可
简化 ts 使用
每次修改代码后,都要重复执行两个命令,才能运行 TS 代码,太繁琐。
tsc 你的代码.ts
node 你的代码.js
简化方式
使用 ts-node
包,直接在 Node.js 中执行 TS 代码。它提供了 ts-node
命令,可以简化执行命令。
安装命令
npm i -g ts-node
使用方式:ts-node hello.ts
相当于:1 tsc 命令 2 node(注意:ts-node 不会生成 js 文件)
解释:ts-node 命令在内部偷偷的将 TS -> JS,然后,再运行 JS 代码
类型注解
语法: let 变量 : 类型 = 值
约定了变量的类型 : 类型
ts 中的类型
1 . js中已有的类型
- 原始类型 :
number/string/boolean/null/undefined/symbol
- 对象类型 :
object
(包括,数组、对象、函数等对象)
2 . ts 新增的类型
- 联合类型
- 自定义类型(类型别名)
- 接口
- 元组
- 字面量类型
- 枚举
- void
- any
- unkown
- 等
注意:
- 原始类型在 TS 和 JS 中写法一致
- 对象类型在 TS 中更加细化,每个具体的对象(比如: 数组、对象、函数…)都有自己的类型语法
原始类型
直接使用
语法: let 变量 : 类型 = 值
// 数值类型
let age: number = 18
// 字符串类型
let myName: string = '小花'
// 布尔类型
let isLoading: boolean = false
// undefined
let un: undefined = undefined
// null
let timer:null = null
// symbol
let uniKey:symbol = Symbol()
类型推论
在 ts 中没有明确指定类型时, 有些时候 ts 会帮助推断类型 ,不用指定类型
会推断类型的两种情况:
- 声明变量并初始化时
- 决定函数返回值时
// 变量 age 的类型被自动推断为:number
let age = 18
// 函数返回值的类型被自动推断为:number
function add(num1: number, num2: number) {
return num1 + num2
}
为什么 vscode 上写 ts 代码有类型推论
vscode 和 ts 都是微软的, 两者直接高度集成
联合类型
语法 : let 变量: 类型1 | 类型2 | 类型3 .... = 初始值
解释:|
(竖线)在 TS 中叫做联合类型,即:由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种
类型别名
type 关键字
作用:
- 给类型取别名
- 定义一个新的类型
语法 : type 别名 = 类型
搭配联合类型使用
语法 : type 别名 = 类型 | 类型1 | 类型2
数组类型
两种定义格式
语法1 : let 变量 : 类型[ ] = [ 值...]
语法2 : let 变量 : Array<类型> = [ 值...]
函数类型
函数的类型
函数涉及的类型实际上指的是:函数参数
和返回值
的类型
格式
// 普通函数
function 函数名(形参1: 类型=默认值, 形参2:类型=默认值,...): 返回值类型 { }
// 箭头函数
const 函数名(形参1: 类型=默认值, 形参2:类型=默认值, ...):返回值类型 => { }
type 自定义类型简化
type Fn = (参数:类型,参数2:类型)=>类型
函数的返回值类型 void
如果一个函数没有返回值 在js中是 undefined , 在ts中需要约定void
约定 void 类型 的三种情况
- 函数没有返回值 (没有return 没有值)
- 返回 undefined
- 只有 return 没有值
函数的可选参数
调用时可以不传递的参数
例如:数组的 slice 方法,可以 slice()
也可以 slice(1)
还可以 slice(1, 3)
语法 : function 函数名(形参1?: 类型, 形参2?:类型): 返回值类型 { }
function mySlice(start?: number, end?: number): void {
console.log('起始索引:', start, '结束索引:', end)
}
注意: 必选参数要在可选参数之前
默认参数
语法 : function 函数名(形参1:类型=默认值, 形参2:类型=默认值): 返回值类型 { }
默认和可选参数不能一起使用
对象类型
定义对象的语法 :
const 对象名: {
属性名1:类型1,
属性名2:类型2,
方法名1(形参1: 类型1,形参2: 类型2): 返回值类型,
方法名2:(形参1: 类型1,形参2: 类型2) => 返回值类型
} = { 属性名1: 值1,属性名2:值2 }
可选属性
const 对象名: {属性名1?:类型1,属性名2:类型2 } = { 属性名2:值2 }
接口
当一个对象类型需要被多次使用, 两种方法
- type : 类型别名
- interface : 接口
interface 使用
语法 :
interface 接口名 {
属性1: 类型1, 属性2: 类型2,
}
注意 : 接口名 要 I
(大写I
)开头
接口和类型的区别
interface(接口)和 type(类型别名)的对比:
- 相同点:都可以给对象指定类型
- 不同点:
- 接口,只能为对象指定类型。它可以继承。
- 类型别名,不仅可以为对象指定类型,实际上可以为任意类型指定别名
推荐:能使用 type 就用 type
接口的继承
两个接口之间有相同的属性或者方法, 可以通过继承实现
继承的实现 extends 关键字
语法 : interface 接口2 extends 接口1 {属性: 类型}
继承后 , 接口2 ,会拥有 接口1 的所有属性
元组
是一个特殊的数字
两个特殊点
- 约定了个数
- 约定了每个数字所对应的类型
语法 : [类型,类型]
React 中 useState()
的返回值类型就是一个元组
字面量类型
const 定义出来的字符串或者数字, 或者正则 都是字面量类型
任意一个字面量都可以当有个类型来使用
字面量的作用
单个字面量没有什么用处,它一般和联合类型 一起使用, 用来表示一组明确的可选值列表。
例如:约定 Gender类型只能取girl和boy这两个字符串其中之一。
type Gender = 'girl' | 'boy'
let g1: Gender = 'girl' // 正确
let g2: Gender = 'boy' // 正确
let g3: Gender = 'man' // 错误
应用场景:
- redux 中 ActionType 的设置可以使用 字面量配合组合类型使用
- 游戏中,游戏的方向键值只能是上、下、左、右中的任意一个
- 解释:参数 direction 的值只能是 up/down/left/right 中的任意一个
- 优势:相比于 string 类型,使用字面量类型更加精确、严谨