TypeScript
一、ts与js的区别
-
ts是js的升级版,是一种js的超集,对数据的类型约束更加严格
-
语法不同,ts的变量声明时需要加上数据类型,之后的该变量必须为同类型的
let 变量名:数据类型=值 ==>let a:number=2
二、数据类型(13个)
基本数据类型(5个)
string、number、boolean、undefined、null
引用数据(2个)
数组
let arr:number[]=[1,2,3]//在ts中数组中只能保存同类型的数据
对象
let student:{name:string,age:number}={name:"张三",age:20}//在ts中约束对象时,需要针对对象每个属性进行类型约束
let student:{name:string,age:number,gender?:string}={name:"张三",age:20}//?问号表示当前属性可有可无
any和unknow(2个)
在ts中any和unknow都可以用来表示“任意类型”的数据
区别
any的数据可以重新赋值给其他任意类型,unknown只能重新赋值给any或unknow类型
元组(1个)
ts中的数组类似于js中的数组。区别在于元组中的数据可以不同类型
let arr:[number,string]=[2,"q"]
枚举(1个)
当用数字0/1表示男女性别的时候,事件久了可能忘记0/1代表的含义,因此ts中提供枚举数据类型
定义://在枚举中,enum是关键字 在{}中写出了每个数字对应的含义
enum Gender {
female=0,
male=1,
unknown=2
}
使用://使用时Gender.male表示的就是数字1
const person:{name:string,gender:Gender/number} ={
name:"张三",gender:Gender.male
}
void(1个)
void表示没有任何类型。在TS中,函数的返回值也需要类型约束,因此当一个函数无返回值时,将其返回值类型设置为void
never(1个)
never 表示永不存在的值的类型
三、函数
函数的参数和返回值类型约束
创建调用无区别,主要是类型约束方面。在ts中需要对函数的参数和返回值的类型进行约束
声明式函数:
function fn(a:参数类型):返回值类型约束{
return 返回值
}
函数表达式:
const fn=(参数:类型):返回值类型=>返回值
参数为对象/返回值为对象:
function fn(params:{a:类型,b:类型}):{x:类型,y:类型}{
return 返回值
}
无参无返回值
function fn():void{}
- 参数默认值,可通过赋值方式给参数设置默认值,必须在所有形参之后
function fn(a:number,b:string="hello"):void{}
fn(1)//b默认hello
- 可选参数,也必须写在所有形参的最后
function fn(a:number,b?:number):void{}
fn(1)//?b可有可无
- 不定参数(一定是个数组)…rest,当不确定实参有多少个时,可以使用不定参数来接收实参。不定参数只能在所有参数最后
function fn(...rest:number[]):void{}
fn(1,2,3)
函数的类型约束(函数表达式)
针对函数表达式:const 函数名:函数类型约束 = 函数
const fn:(x:number,y:number)=>void =(x,y)=>{}
//(x:number,y:number)=>void 是函数类型约束
//(x,y)=>{}是函数
四、联合类型和类型别名
联合类型(|)
表示数据的类型可以取多个类型中的其中一种
//let 变量名:类型一 | ... | 类型n = 值
let a :number|string|boolean=1
类型别名(type)
通过type给其他类型设置一个名称
//type 类型名称=类型
type StrNum=string|number
let a:StrNum=1
a="hello"
function fn(x:StrNum):StrNum{
return x
}
fn(1)
五、接口(interface)
1、接口和对象
用接口定义对象的类型约束
基本语法
interface Student {
readonly name:string;//只读属性,无法通过student.name修改该属性值
gender:string;
age?:number;//可以选属性
}
const student :Student={
name:"张三",
gender:"男"
}
可选属性(?)
只读属性(readonly)
2、接口和函数
用接口去定义函数的类型约束
基础语法
interface Fn{
(x:number):void
}
const fn:Fn=(x)=>{}
fn(1)
3、接口和接口
在一个接口中使用另一个接口
基础语法
interface Param{//对象
x:number;
y:number;
}
interface Add{//参数为一个对象,返回值为一个数字类型的函数
(data:Param):number
}
const add:Add=(data)=>{
return data.x+data.y
}
add(1,2)
六、type和interface
大部分情况下,两者是可以通用的
但还是有区别:
- type不能被继承,interface可以被继承
- 定义两个同名的type会报错,而interface会合并
- type可以定义联合类型,interface不可以
七、断言(as)
作用:某些情况下ts会报错,而开发人员确定不会有误。因此,我们可通过断言的方式,告诉TS我们确定的结果
示例:
const arr:number[]=[1,2,3,4];
const re:number=arr.find(item=>item>3)//此时会报错:ts会认为在数组中查找的结果的类型除了number外还会有undefined,但我们可以明确,在数组【1,2,3,4】中查找大于3 的结果re肯定是4,类型就是number,此时我们就可以使用断言
const re:number=arr.find(item=>item>3) as number;
八、泛型(<大写字母>)
作用(概念):约束类型时,类型可能是不固定的,变化的。那么此种类型就可以用泛型来表示
1、基础语法
//此处的类型变量相当于是类型的形参
function 函数名<类型变量>(参数名:类型变量):类型变量 {
return 返回值;
}
//此处的数据类型相当于是类型的实参
函数名<数据类型>();
//案例
function fn<T>(x:T):T{
return x;
};
fn<number>(1);
fn<string>("hello");
2、多个泛型变量
function fn<S,T>(x:S,y:T):T{
return y
}
fn<number,string>(1,"hello")
3、泛型与接口
interface 接口名<类型变量>{
属性名:类型变量
}
案例:
interface Student<T>{
id:number;
name:string;
age:T
}
let zhangsan:Student<number>={
id:1,
name:"张三",
age:22
}
let lisi:Student<string>={
id:2,
name:"李四",
age:“22”
}
九、ts的内置工具类型
Record、Partial 、 Required 、 Readonly、 Pick 、 Omit、 Exclude 、 Extract
1.Record(定义对象)
-
作用:定义一个对象的key与value的类型
-
源码:
Record<key type, value type>
-
使用:
// Record<string, never> 空对象 // Record<string, unknown> 任意对象 // {} 任何不为空的对象 #例1 type Obj = Record < string , number | string >//表示Obj对象中 key的类型为string, value的类型为number或string let obj : Obj = { name : "张三". age : 12 } let obj2 = {} as Record < string , number | string > obj2 = { name : "李四". age : 32 } #例2 interface Item {//定义Item对象接口,其中name、age都是必填属性,值类型分别为string和number name:string; age:number; } type Person = Recore < string , Item >//定义一个Person对象,key类型为string,value的类型为Item let person : Person = { somebody : { name : "张三", age : 22 } }
2.Partial (变为可选)
-
作用:生成一个新类型,该类型与 T(传入的泛型) 拥有相同的属性,但是所有属性皆为可选项
-
源码:
type Partial<T> = { [P in keyof T]?: T[P]; }; //解析 ?表示可选 [P in keyof T]表示遍历T中的所有属性名 T[P]表示T中对应属性的值
-
使用:
interface Obj { name : string; age : number; id : number; } type NewObj = Partial<Obj> //此时NewObj相当于 interface NewObj { name ?: string; age ?: number; id ?: number; }
3.Required (变为必选)
-
作用:生成一个新类型,该类型与 T 拥有相同的属性,但是所有属性皆为必选项
-
源码:
type Require<T> = { [P in keyof <T>]-?: T[P] }
-
使用:
interface Obj { name : string; age ?: number; id : number; } type NewObj = Required<Obj> //此时NewObj相当于 interface NewObj { name : string; age : number; id : number; }
4.Readonly (变为只读)
-
作用:生成一个新类型,该类型与 T 拥有相同的属性,且属性是只读的,不可修改的。
-
源码:
type Readonly<T> = { readonly [P in keyof T]: T[P]; };
-
使用:
interface Obj { name : string; age : number; id : number; } type NewObj = Readonly<Obj> //此时NewObj相当于 interface NewObj { readonly name : string; readonly age : number; readonly id : number; }
5.Pick(选取部分)
-
作用:从一个对象类型中,取出某些属性,生成一个新类型 ;
-
源码:
type Pick<T, K extends keyof T> = { [P in K]: T[P]; };
-
使用:Pick<要拾取的类型,要拾取的属性1,…,要拾取的属性n>
interface Obj { name : string; age : number; id : number; } type NewObj = Pick<Obj , "name" , "age" >//可以用或| //此时NewObj相当于 interface NewObj { name : string; age : number; }
6.Omit (排除部分)
-
作用:从一个对象类型中,排除某些属性,生成排除后的一个新类型 ;
-
源码:
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>
-
使用:Omit<类型,要排除的属性1,…,要排除的属性n>
interface Obj { name : string; age : number; id : number; phone : string; } type NewObj = Omit<Obj , "name" , "age" >//可以用或| //此时NewObj相当于 interface NewObj { id : number; phone : string; }
7.Extract (包括)
-
作用:生成一个T中有,U中也有的类型
-
源码:
type Extract<T, U> = T extends U ? T : never;
-
使用:
type TExtract1 = Extract<"a" | "b", "a" | "c"> // 等同于 type TExtract1 = "a" type TExtract2 = Extract<number | string | boolean, string> // 等同于 type TExtract2 = string type TExtract3 = Extract<number | string | boolean, object> // 等同于 type TExtract3 = never
8.Exclude(不包括)
-
作用:生成一个T中有,U中没有的类型
-
源码:
type Exclude<T, U> = T extends U ? never : T
-
使用:
type TExclude1 = Exclude<"a" | "b", "a" | "c"> // 等同于 type TExclude1 = "b" type TExclude2 = Exclude<number | string | boolean, string> // 等同于 type TExclude2 = number | boolean
9.NonNullable
-
作用:去除 null 和 undefined 后的新类型
-
源码:
type NonNullable<T> = T extends null | undefined ? never : T
-
使用:
type TType= number | null | undefined type TNonNullable = NonNullable<TType> // 等同于 type TNonNullable = number
十、源码中的关键字
keyof:获取类型内所有的 key,即所有属性名 , 获取到的是一个 联合类型
-
用法:keyof 后面必须接类型,返回的是联合类型
interface Obj { name:string, age?: number, sex: string, } type T = keyof Obj // 等同于 type T = "name" | "age" | "sex"
-
注意:keyof any
type TAny = keyof any // 等同于 type TAny = string | number | symbol //不包括 boolean object等
in:把联合类型中每一个属性名赋值给 P,结果为对象类型
-
用法:
type T = "name" | "age" | "sex" type TObj = { [P in keyof T]: any } // 等同于 type TObj = { name: any; age: any; sex: any; }
typeof : 获取数据的类型,常用用于获取 对象、数组、函数、class、枚举等类型
-
用法:typeof后面接具体的对象 数组 函数等,返回的是类型
const people = { name: 'liuyz', age: 18, } type INewPeople = typeof people // 等同于 type INewPeople = { name: number; age: number; } const newPeople: INewPeople = { name: "zhi", age: 18, } type TKeys = keyof typeof newPeople // 等同于 type TKeys = "name" | "age"
十一、拓展
1、提取ts公共类型文件
创建----名.d.ts文件
在类型文件中写类型,并暴露
在组件中引入类型文件,并使用
//在demotype.d.ts文件中暴露
export interface TodoItem{
id:number;
value:string;
done:boolean
}
//在某组件中引入并使用
import { TodoItem } from "./demotype"
defineProps<{值:TodoItem[ ] }>()