TypeScript是拥有类型的JavaScript超集,它可以编译成普通、干净、完整的JavaScript代码。我们可以将TypeScript理解成加强版的JavaScript。
简单来说:Ts是带类型语法的Js; Ts是Js的超集
TS官方网站:https://www.typescriptlang.org/
TS中文官网:https://www.tslang.cn/
一、基础语法
js已有类型:
基本类型: number, string, boolean, null, undefined, symbol,BigInt
引用数据类型:对象、数组、函数
ts新增类型:
联合类型、类型别名、接口、元祖、字面量类型、枚举、void、any、泛型等
(一) 原始类型
1.简单类型 :xx
let age: number = 18;let uname: string = "zhangsan";let flag: boolean = false;// null和und类型用的比较少let nullValue: null = null;let undefinedValue: undefined = undefined;
PS:其实最后.ts转为.js文件时void仍会变为undefined,TS中加上void一般只是为了将函数返回值和其他区分出来。
2.引用类型 :xx[]
a.数组
let arr1 = ["a", "b", "c"]let arr3: number[] = [1, 2, 3]let arr2: string[] = ["a", "b", "c"]console.log(arr1, arr2, arr3);let arr4: Array<string> = ["ok", "hello"]console.log(arr4);
思考:数组中是可以存放多种数据类型
联合类型:|(竖线)在TS中叫做联合类型
即:由两个或多个其他类型组成的类型,表示可以是这些类型中的任意一种
b.函数
// 函数 给参数和返回值 指定类型// 函数声明(具名函数)function add(a: number, b: number): number {return a + b}console.log(add(1, 2));// 函数表达式(匿名函数)let add2 = (a: number, b: number): number => {return a + b}console.log(add2(1, 2));// 箭头函数写法type AddFn = (a: number, b: number) => number// 通过类似箭头函数形式的语法为函数添加类型,只适用于函数表达式let add3: AddFn = (a, b) => {return a + b}console.log(add3(3, 3));
可选参数:?
使用 ? 将参数标记为可选
const fn = (n?: number) => {
}
fn()
fn(1)
函数返回值:
在js中默认返回值是und,在ts中默认返回的是void
如果指定返回值类型是 undefined 那返回值一定是 undefined
// void和undfined类型// 如果函数没有返回值,定义函数类型时返回值的类型为voidconst say = () => {// console.log('hello ts~');}console.log(say());console.log(typeof say());const say2 = (): void => {// console.log('hello ts~');}console.log(say2());console.log(typeof say2());// 区分:在js中默认返回值是und,在ts中默认返回的是void// 如果指定返回值类型是 undefined 那返回值一定是 undefinedconst say3 = (): undefined => {// console.log('hello ts~');}console.log(say3());console.log(typeof say3());
c.对象
// 空对象let obj1 = {}let obj2: {} = {}// 指定对象里面的属性和方法// let obj4: { name: string, say(): void } = {let obj4: { name: string; say(): void } = {name: "wc", // 对象里面写方法的两种写法 // say():void say: () => void}// 竖着写 可以换行let obj5: {// name: string,name: string;say(): void} = {name: "wc",say() { }}
(二) 类型别名 type
给某个指定类型起别名
定义类型别名,遵循大驼峰命名,类似于变量
什么时候是用类名别名?
当同一类型(引用)被多次使用,可以通过类型别名简化
// 语法:type 类型别名=具体类型type A = (string | number)[]let arr9: Aarr9 = [1, "a", 3]
交叉类型 &
// type 交叉类型type APoint2D = {x: number,y: number}type APoint3D = APoint2D & {z: number}let o: APoint3D = {x: 1,y: 2,z: 3}
(三) 接口 interface (可继承extends)
interface 后面跟的是接口名称
注意:接口的每一行只能有一个属性或者一个方法 每一行不需要加分号
interface Person {
name: string
age: number
say: () => void
}
let p: Person = {name: "wangcai",age: 18,say() { }}console.log(p);// 接口是可继承的// 2D坐标interface Point2D {x: numbery: number}let p2: Point2D = {x: 1,y: 2}console.log(p2);// 如何实现继承?// 使用extends实现接口继承,达到类型复用// 继承后 接口A 拥有了接口B的所有属性和函数的类型声明 interface Point3D extends Point2D { z: number}let p3: Point3D = {x: 1,y: 2,z: 3}
(四)interface和type的区别
1.type是起别名,interface 是自己发明类型 自定义类型
// 会报错// type APerson = {// name:string// }// type APerson = {// age:number// }interface Person1 {name1: string};interface Person1 {age1: number};// 类型合并const c1: Person1 = {name1: "wc",age1: 18}
2.type不可以重复定义,interface可以重复定义会合并
3.type支持对象类型和其他类型,interface只支持对象类型
4.type复用:交叉类型 &,interface复用:可以继承 extends
二、ts在vue3中的使用
(一)ref和ts
// 手动指定类型
const count =ref<number>(0)
<template><div>{{ count }}</div><ul><li v-for="item in list" :key="item.id">{{ item.name }}</li></ul></template><script setup lang="ts">import { ref, reactive } from "vue"// 手动指定类型const count =ref<number>(0)// 自动类型const count1=ref(0)type ToDoItem={id:number;name:string;done:boolean}// [{},{},{}]const list=ref<ToDoItem[]>([])setTimeout(()=>{list.value=[{ id: 100, name: "吃饭", done: false },{ id: 101, name: "睡觉", done: false },]},1000)</script>
(二)reactive和ts
type Book={
title:string;
year?:number
}
const book:Book=reactive({
title:"ts语法基础"
})
<template>{{ book.title }} -- {{ book.year }}</template><script setup lang="ts">import { ref, reactive } from "vue"// 1.手动指定类型type Book={title:string;year?:number}const book:Book=reactive({title:"ts语法基础"})book.year=2023// 2.自动类型推导const Book=reactive({title:"ts语法基础2"})</script>
(三)computed和ts
const doubleCountB = computed<string(() => (count.value * 2).toFixed(2))
<template>{{ count }} -- {{ doubleCount }} -- {{ doubleCountB }}{{ typeof count }} -- {{ typeof doubleCount }} -- {{ typeof doubleCountB }}</template><script setup lang="ts">import { ref, computed } from "vue"const count = ref(205)// 1.自动类型推导// toFixed(2)保留2位小数,且返回值类型为stringconst doubleCount = computed(() => (count.value * 2).toFixed(2))// 2.指定计算属性的类型const doubleCountB = computed<string>(() => (count.value * 2).toFixed(2))</script>
(四)defineprops和ts(父传子)
defineProps<{
money:number;
car?:string
}>()
Child.vue
<template><div class=""><p>{{ money }}</p><p>{{ car }}</p></div></template><script setup lang="ts">// vue3基本写法// defineProps({// money:{// type:Number,// required:true// }// })// ts基本语法// defineProps<{// money:number;// car?:string// }>()// ts+有默认值的写法withDefaults(defineProps<{money:number;car?:string}>(),{money:666,car:"xiaomi"})</script>
App.vue
<template><div><!-- 父传子 --><Child :money="money"></Child></div></template><script setup lang="ts">import { ref} from "vue"import Child from "./components/Child.vue"const money=ref(666)const car=ref('大众')</script>
(五)defineEmits和ts(子传父)
const emit =defineEmits<{
(e:"changeMoney",money:number):void;
(e:"changeCar",car:string):void;
}>()
Child.vue
<template><p>{{ money }}</p><button @click="emit('changeMoney', 800)">改money</button><p>{{ car }}</p><button @click="emit('changeCar', '宝马')">改car</button></template><script setup lang="ts">// vue3基本写法// const emit = defineEmits(["changeMoney", "changeCar"])// ts写法defineProps<{money: number;car?: string;}>()const emit =defineEmits<{(e:"changeMoney",money:number):void;(e:"changeCar",car:string):void;}>()</script>
App.vue
<template><!-- 子传父 --><Child:money="money":car="car"@change-money="money=$event"@change-car="car=$event"></Child></template><script setup lang="ts">import { ref} from "vue"import Child from "./components/Child.vue"const money=ref(666)const car=ref('大众')</script>
(六)事件处理和ts :Event
as 断言
e:Event
<template><input type="text" @change="handleChange" value="hi"></template><script setup lang="ts">// 不处理类型// const handleChange=(e)=>{// console.log(e.target.value)// }const handleChange=(e:Event)=>{// as 断言// e.target 事件源console.log((e.target as HTMLInputElement).value);}</script>
(七)ref写在标签上获取 :HTMLInputElement
const input = ref<HTMLInputElement | null(null)
<template><div><input type="text" ref="input"></div></template><script setup lang="ts">import { onMounted, ref } from 'vue'const input = ref<HTMLInputElement | null>(null)// 页面加载完毕调用钩子函数onMounted(()=>{input.value?.focus()})</script>
(八)非空断言 !
// ! 非空断言(方法一)
input.value!.value = "456" //可以赋值
// 类型守卫(方法二)
if (input.value) {
input.value.value = "789" //可以赋值
}
<template><div><input type="text" ref="input" value="123"></div></template><script setup lang="ts">import { onMounted, ref } from 'vue'const input = ref<HTMLInputElement | null>(null)// 页面加载完毕调用钩子函数onMounted(() => {// 自动获取焦点input.value?.focus()// 使用ES6 输入框没有获取到,对于可能出现null,console.log(input.value?.value);// ?可选参数 可选链 报错 因为不能赋值// input.value?.value = "456"// ! 非空断言(方法一)input.value!.value = "456" //可以赋值// 类型守卫(方法二)if (input.value) {input.value.value = "789" //可以赋值}})</script>