TS核心
联合类型 (string | number)[]
let arr: (string | number)[] = ['a',100]
类型别名(type关键词)
type 类型别名 = 具体类型
基本语法- 定义类型别名,遵循大驼峰命名规范,类似于变量
- 使用类型别名,与类型注解的写法一样即可
- type 有 = 号,interface无 = 号
type ItemType = (string | number)[]
let arr: ItemType = ['a',100]
let arr2: ItemType = [100,200,'a','b']
// 函数复用并同时指定
type AddFn = (a:number ,b:number) => number
const aFn: AddFn = (num1,num2) => {
return num1+num2
}
aFn(1,2)
type Person = {
name: string
age: number
gender?: string
}
let p: Person = {
name: 'aa',
age: 10
}
// 交叉类型(&)
type PersonA = Person & {
id: number
}
let p2: PersonA = {
name: 'aa',
age: 10,
id: 1
}
继承: 交叉类型(&)
- 使用
&
可以合并连接的对象类型,也叫:交叉类型
// 使用 type 来定义 Point2D 和 Point3D
type Point2D = {
x: number
y: number
};
type Point3D = {
x: number
y: number
z: number
};
// 使用 交叉类型 来实现接口继承的功能:
// 使用 交叉类型 后,Point3D === { x: number; y: number; z: number }
type Point3D = Point2D & {
z: number
};
let o: Point3D = {
x: 1,
y: 2,
z: 3,
};
接口(interface)
interface
接口名称,和类型别名的意思一样。- 指定
接口名称
作为变量的类型使用。 - 接口的每一行只能有
一个
属性或方法,每一行不需要加分号。 - type 有 = 号,interface无 = 号
interface Person {
name: string
age: number
gender?: string
}
const p: Person = {
name: 'gao',
age: 18
}
let list: Person[] = [
{
name: 'gao',
age: 18,
}
]
// 多层嵌套结构,定义先内层在外层
{
code: 200,
msg: '成功',
data: {
num: 1,
a: 'sss'
}
}
interface Data {
num: number
a: 'string'
ad?: 'string'
}
interface ResData {
code: number
msg: string
data: Data
}
继承(extends)
使用 extends 实现接口继承,达到类型复用
// 有两个接口,有相同的属性或者函数
interface Point2D {
x: number;
y: number;
}
interface Point3D {
x: number;
y: number;
z: number;
}
// 相同的属性或展示可以抽离出来,然后使用 extends 实现继承复用
interface Point2D {
x: number;
y: number;
}
// 继承 Point2D
interface Point3D extends Point2D {
z: number;
}
// 继承后 Point3D 的结构:{ x: number; y: number; z: number }
字面量类型(可选范围)
// 场景1
type Gender = '男' | '女'
let gender: Gender = '男'
// 场景2
type Res = {
code: 200 | 400 | 500
msg: string
}
let res: Res = {
code: 200,
msg: 'success'
}
let count: 100
count = 100
count = 200 // error
let name: 'gao'
泛型(Generics) <>不预先指定具体类型,使用的时候再来指定
// 场景
{
code: 200,
msg: '成功',
data: {
num: 1,
a: 'sss'
}
}
{
code: 200,
msg: '成功',
data: {
id: 1,
content: '内容'
}
}
type Res<T> = {
code: number
msg: string
data: T
}
type Data1 = {
num: number
a: string
}
type Data2 = {
id: number
content: string
}
let res: Res<Data1> = {
code: 200,
msg: 'success',
data: {
num: 1,
a: 'sss'
}
}
let res2: Res<Data2> = {
code: 200,
msg: 'success',
data: {
id: 1,
content: '内容'
}
}
泛型函数
// 函数的参数是什么类型,返回值就是什么类型
function getId<T>(id: T): T {
return id
}
let id1 = getId<number>(1)
let id2 = getId('2')
// TS会进行类型推断,参数的类型作为泛型的类型 getId<string>('2')
枚举
enum Direction {
Up,
Down,
Left,
Right,
}
// Up的值为 0, Down的值为 1等等
enum Direction {
Up = 1,
Down,
Left,
Right
}
如上,我们定义了一个数字枚举, Up
使用初始化为 1
。 其余的成员会从 1
开始自动增长。 换句话说, Direction.Up
的值为 1
, Down
为 2
, Left
为 3
, Right
为 4
。
// 字符串枚举
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
无返回值 void
const say = (): void => {
console.log('hi');
};
any
any 类型的作用是逃避 TS 的类型检查,不会有任何错误,也不会有代码提示,TS会忽略类型检查
let obj: any = { age: 18 }
obj.bar = 100
obj()
const n: number = obj
类型注解
let msg: string
msg = 'this is message'
let count: number
let isBoolean: boolean
let arr: number[] ====> // 泛型写法: let arr: Array<number> = [1,2,3]
arr = [1,2,3]
let arr2: string[]
arr2 = ['a','b','c']
// 联合类型
let arr3: (string | number)[] = ['a', 100]
// 函数声明
function add(num1: number, num2: number): number {
return num1 + num2;
}
// 箭头函数
const add = (num1: number, num2: number): number => {
return num1 + num2;
};
// 复用并同时指定
type AddFn = (num1: number, num2: number) => number;
const add: AddFn = (num1, num2) => {
return num1 + num2;
};
类型断言(as)
const aLink = document.getElementById('link') as HTMLAnchorElement
aLink.href = ''
三斜线指令
三斜线指令仅可放在包含它的文件的最顶端。 一个三斜线指令的前面只能出现单行或多行注释,这包括其它的三斜线指令。 如果它们出现在一个语句或声明之后,那么它们会被当做普通的单行注释,并且不具有特殊的涵义。
/// <reference path="..." />
/// <reference path="..." />指令是三斜线指令中最常见的一种。 它用于声明文件间的 依赖。
三斜线引用告诉编译器在编译过程中要引入的额外的文件。
Omit和Pick
Omit 是从对象中排除一些属性
用法: Omit<对象,属性|属性>
type Person = {
name: string
age: number
gender: 0|1
address: string
tel: number
}
type OmitPerson = Omit<Person, 'age'|'gender'>
// {
// age: number
// gender: 0|1
// }
type OmitUser = Omit<Person, 'age'>
type UserInfo = OmitUser & {
id: number
token: string
}
// {
// name: string
// gender: 0|1
// address: string
// tel: number
// id: number
// token: string
// }
Pick 是从对象中摘取一些属性
用法:Pick<对象, 属性|属性>
type Person = {
name: string
age: number
gender: 0|1
address: string
tel: number
}
type PickPerson = Pick<Person, 'name'|'age'>
// {
// name: string
// age: number
// }
V3中使用Ts
ref函数标注类型和泛型的使用
函数标注、模板引用标注
// 元素事件标注
const inputChange = (e: Event) => {
console.log((e.target as HTMLInputElement).value);
}
// 模板引用标注类型
const inputRef = ref<HTMLInputElement | null>(null)
function iptFocus() {
inputRef.value?.focus()
}
props标注类型
type Props = {
color: string // 必传参数
size?: string
}
const props = defineProps<Props>()
默认值( withDefaults(defineProps<Props>(), {默认值}))
type Props = {
color: string
size?: string
}
const props = withDefaults(defineProps<Props>(), {
size: 'middle'
})
emits标注类型
约束事件名称 + 参数类型
type Emits = {
(e: 'get-msg', msg: string): void
}
const emit = defineEmits<Emits>()
function clickHandler() {
emit('get-msg','this is value')
}
// 数组类型
type ListItem = {
id: number
name: string
}
type Emits = {
(e: 'get-list', list: ListItem[]): void
}
const emit = defineEmits<Emits>()
function clickHandler() {
emit('get-list', [{ id: 1, name: 'gao' }] )
}
类型声明文件 d.ts
为js模块提供类型信息支持。
TS会自动导入模块对应的d.ts文件,以提供类型提示
有些库本身不是ts编写的,无法直接生成配套的d.ts文件,可以使用DefinitelyTyped提供类型声明文件
yarn add @types/jquery -D
axios
axios要根据后端返回值写标注类型,泛型放在axios.request中
type DataItem = {
article_id: number
articel_name: string
}
type ArticleResData = {
code: number,
data: DataItem[],
msg: string
}
async function getList() {
const res = await axios.request<ArticleResData>({
url: '',
method: 'GET',
params: {
id: 1001
}
})
}
// 抽出公用部分
type CommonData<T> = {
code: number,
data: T,
msg: string
}
type ChannelItem = {
id: number
name: string
}
type ARes = CommonData<{
channels: ChannelItem[]
}>
type ArtItem = {
pic_id: number
url: string
}
type BRes = CommonData<{
arts: ArtItem[]
}>
Pinia
appInfo.ts
import { defineStore } from "pinia";
import { computed, ref } from "vue";
export const useInfoStore = defineStore('info', () => {
// state
const count = ref(0)
// function
function changeCount() {
count.value++
}
// getter
const doubleCount = computed(() => {
count.value * 2
})
// 定义类型
type ChannelItem = {
id: number
name: string
}
type ResData = {
data: {
channels: ChannelItem[]
}
message: string
}
// action
const list = ref<ChannelItem[]>([]) // list = [{id: 1001,name: '短袖'}]
async function getList() {
// const res = await xxx()
// list.value = res.data
}
return { count, doubleCount, list, getList, changeCount, }
})
使用pinia
storeToRefs:解构数据后,还保持数据(state+getter)的响应式
<script setup>
import { storeToRefs } from "pinia";
import { useInfoStore } from "@/store/app.js";
const store = useInfoStore();
// storeToRefs:解构数据后,还保持数据(state+getter)的响应式
let { count} = storeToRefs(store);
// 方法就是直接解构
const { changeCount } = store
</script>
pinia持久化存储
pnpm add pinia-plugin-persistedstate
用法:
// store>index.ts
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'
export * from './modules/userInfo'
// 创建pinia实例
const pinia = createPinia()
// 使用pinia插件
pinia.use(persist)
// 导出pinia实例,给main使用
export default pinia
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import pinia from './stores'
import router from './router'
import '@/styles/main.scss'
// toast
import 'vant/es/toast/style';
// Dialog
import 'vant/es/dialog/style';
// Notify
import 'vant/es/notify/style';
// ImagePreview
import 'vant/es/image-preview/style';
async function setupApp() {
// 创建vue实例
const app = createApp(App)
// 注册模块Pinia
await app.use(pinia)
// 注册模块 Vue-router
await app.use(router)
// 挂载
app.mount('#app')
}
setupApp()