TypeScript+Vue3.2知识预备
查看nodeb
node -v
查看typeScript版本
tcs -v
查看
mvn -v
let和const区别
let str ='1' // str:string 初始值决定它的类型
const num =1; // 常量不可修改,它的值就是类型
① var声明的变量属于函数作用域;let 和 const 声明的变量属于块级作用域,不能跨函数访问;
② var存在变量提升现象,而 let 和 const 没有;
③ var变量可以重复声明,值可改变;在同一个块级作用域下:let变量不能重新声明;const定义的变量是常量,声明时必须赋值,但不允许重复赋值,如果定义的是引用类型,可以修改数据内部结构。
1、TS的原始类型:就是JS的基础数据 number\string\boolean\undefined\null\symbol
symbol('值'): a=123;b=123; a===b 是成立的, 但symbol的值都是新地址,所以值相同a===b也不成立。
2、ts的非原始类型
3、数组类型
4、联合类型
5、交叉类型
6、any绕过类型校验和unknown.ts
7、接口类型interface.ts
8、接口继承、同名、缺省、只读
缺省、只读
9、联合交叉类型
10、类型别名
11、ts函数
export {} // fn(a,b:number值类型):number返回值类型 function fn(a:number,b:number):number{ return a+b } // 接口定义函数类型 interface Fnltf{ (p:string):number } let fn1:Fnltf = (p:string)=>{ return 1 } fn1('') //类型别名定义函数类型 type FnType = (p:string)=>void //全局写法 let fn2:FnType = (p:string):void=>{} fn2('') // 函数作为对象的属性出现的时候 interface Object{// 接口对象 fn:Fnltf // 套用接口:遵循 } let obj:Object={ // 局部写法:对象内 fn:(str)=>{ // 遵循套用接口 return 1 } } obj.fn('') // 定义type类型别名objType= {类型别名对象fn: type ObjType ={fn:(p:string)=>number} let obj2:Object = { fn:(str)=>{ return 1 } } obj.fn('')
12、ts函数参数的写法
export {} // 默认参数:参数名b:number=3 function fn(a:number,b:number=3){ return a+b } console.log(fn(1,2)); console.log(fn(5)); // 缺省参数:参数名b? 表示可以被缺省的参数 function fn1(a:number,b?:number){ return 1 } fn1(1,2); fn1(1); // 由于缺省:不报错 // 接收剩余参数: es6样式 ...参数名:[]数组接收剩余所有参数 function fn2(a:number,b:number,...arr:number[]){ return 1 } fn2(1,2,3,4,5,) let arr1 = [1,2,3]; let arr2 = [...arr1]; // 接收arr1所有参数 arr1[0] = 4; // 修改数组下标0 = 4 console.log(arr1); // [4,2,3] console.log(arr2); // [1,2,3] 执行顺序 console.log('-----------------') let obj1 = {a:1,b:2,c:[1,2,3]}; let obj2 = {...obj1}; // 浅拷贝 obj1.a = 100; obj1.c[0] = 1000; // 判断下obj2深拷贝还是浅拷贝 console.log(obj1); // {a:100,b:2,c:[1000,2,3] console.log(obj2); // {a:1,b:2,c:[1000,2,3]
13、ts中Promise
export {} // 接口扩展:Resltf{data:{a:number,b:number}[], interface Dataltf{ a:number; b:number; } // 解决 js不会报错,ts报错缺少接口 interface Resltf{ // 定义数据类型 code:number, // data:{a:number,b:number}[], data:Dataltf[] //接口扩展 message:string, } // 此处要使用泛型指定Resltf接口 // let p = new Promise((resolve,reject)=>{ // Promise对象: p对象名:Promise<res的类型>泛型 let p:Promise<Resltf>= new Promise((resolve,reject)=>{ resolve({ // resolve决定,reject拒绝 code:0, data:[{a:1,b:2},{a:11,b:12}], message:'', }) }) p.then(res=>{ // res接收 if (res.code==0){ // js中不会报错,ts缺少接口 res.data.map(item=>item.a) } })
14、shis的指向
02-this指向自定义对象
03-this指向的联合写法
15、枚举---也叫列举
16、泛型
export {} // (n:number形参类型):number返回值类型{} function fn(n:number|boolean):number|boolean{ return n } fn(100); fn(true); // 报错:形参和返回值添加boolean类型 // 泛型 可以理解为类型的形参,T是一个标识符,可以自定义,T表示某种类型 function fn1<T>(n:T):T{ return n } fn1<number>(100); fn1<boolean>(true); fn1<'hello'>('hello'); // 泛型是常量,参数必需是常量,值只能常量自己 // 泛型 类型参数化 function fn2<T,G>(n:T,m:G):T{ return n } fn2<number,string>(100,'x'); fn2<boolean,number>(true,10); fn2<'hello',string>('hello','lja'); // 泛型是常量,参数必需是常量,值只能常量自己
17、泛型在类型别名和接口上的应用
export {} // 定义类型别名,约束规范 // type ObjType ={name:string,getName:()=>string} type ObjType<N,G> ={name:N,getName:()=>G} // 对泛型中的类型 进行类型别名提取 type StrOrNum = string|number; // let obj:ObjType<string,number|string>={ let obj:ObjType<StrOrNum,StrOrNum>={ // name:'', name:23, // 类型定义后可数字和字符串 getName(){ // return 'x' return 1 } } // 泛型-接口 /*interface Personltf{ name:string, getName:()=>string }*/ interface Personltf<N,G>{ name:N, getName:()=>G } let obj2:Personltf<StrOrNum,number>= { name:'2', getName(){ // return 'x' // 报错:接口规范为G,number return 2 } }
18、泛型-约束:使用继承extends
export{} // 定义类型别名 type StrOrNum = string|number // 泛型中设置默认值类型,使用时可以省略不传,但不能约束。 // type ObjType<N,G=string> ={name:N,getName:()=>G} // 约束:extends进行约束 interface Personltf<N extends string|number,G>{ name: N; //需求: N值接收字符串或者数字 getName:()=>G } // let obj:Personltf<any, any>=>{ // any:任意类型 let obj:Personltf<StrOrNum, number>={ // any:任意类型 name: 1, getName(){ return 1 } }
19、类的构造函数
export {} // 2.定义类的同时,相当于定义了相同名称的接口 class Person{ // 1.定义属性前,应该先声明这个属性的类型,也可以同时设置默认值 myName:string="默认名称" //声明类型 constructor (n:string) { this.myName = n } getName(){ return this.myName } } let p = new Person('张三') console.log(p.myName) console.log(p.getName()) // 以上这个类,相当于下面这个接口 /*interface Person{ myName:string; getName:()=>string; }*/ let obj:Person={ myName:'', getName (): string { return '' } }
class Dog { // 需要先定义,才能在constructor中this指向 name: string; age: number; // 构造函数,会在对象创建时调用 // new Dog() 的时候,就会调用constructor constructor(name:string, age:number) { /** * 在实例方法中,this就表示当前的实例 * 在构造函数中当前对象就是当前新建的那个对象 * 可以通过this指向新建的对象中添加属性 */ this.name = name; this.age = age; } bark(){ console.log(this.name + " is barking, woofing ") } } const dog = new Dog('Tom', 4); console.log(dog); const dog2 = new Dog('Max', 2); console.log(dog2); dog2.bark();
20、类的继承
export {} // 2.定义类的同时,相当于定义了相同名称的接口 class Person{ // 1.需要先定义,才能在constructor中this指向 myName:string // 构造函数,会在对象创建时调用 constructor (n:string) { /** * 在实例方法中,this就表示当前的实例 * 在构造函数中当前对象就是当前新建的那个对象 * 可以通过this指向新建的对象中添加属性 */ this.myName= n } getName(){ return this.myName } } class Male extends Person{ age:number // 定义age constructor (name:string,age:number) { // 接收参数 super(name) // 继承父类,调用父类方法:m.myName // super()实际执行了父类中constructor (n:string) { this.myName= n } this.age = age // age需要先定义才能在constructor中this指向 } getName (): string { // 重写:方法名一致 // return super.getName() return '我叫'+this.myName } } let m = new Male('张三',17) console.log(m.myName) console.log(m.age) console.log(m.getName())
21、
权限修饰符
1. private ( 当前类访问权限 )
使用 private 修饰的 成员 只能在 当前类的内部 被访问。常用于修饰 成员变量 ( 封装 )。
2. default ( 包访问权限 )
默认权限修饰符。使用 default 修饰的 成员或外部类 可以被 相同包下的其他类 访问。
3. protect ( 子类访问权限 )
使用 protect 修饰的 成员 既可以被 同一个包中的其他类 访问,也可以被 不同包中的子类 访问。常用于修饰 希望被子类重写的方法 ( override )。
4. public ( 公共访问权限 )
使用 public 修饰的 成员或者外部类 可以被 所有类 访问。
5. 访问控制级别表
private | default | protect | public | |
---|---|---|---|---|
同一个类中 | Y | Y | Y | Y |
同一个包中 | Y | Y | Y | |
子类中 | Y | Y | ||
全局范围内 | Y |
22、实用工具类型
1、Partial:将<>泛型中接口类型的属性设置:可缺省的属性。
Partial 作用是将传入的属性变为可选项。适用于对类型结构不明确的情况。它使用了两个关键字:keyof和in
keyof 可以用来取得接口的所有 key 值: keyof 是取 interface 的键,而且 keyof 取到键后会保存为联合类型。
// T 类型为: "name" | "age" | "number"
type Person = { name: string; age: number; height: number; } type T = keyof Person // T 类型为: "name" | "age" | "number"
in关键字可以遍历枚举类型,:
in
in用于取联合类型的值。主要用于数组和对象的构造。
但切记不要用于 interface,否则会出错
type Person = "name" | "age" | "number" type Obj = { [p in Person]: any } // Obj 的类型为: { name: any, age: any, number: any }
这里,keyof T 用来获取 T 所有属性名, 然后使用 in 进行遍历, 将值赋给 P, 最后 T[P] 取得相应属性的值。中间的?就用来将属性设置为可选。
来看下面的例子:
type Person = { name: string; age: number; height: number; } type PartialPerson = Partial<Person>; // PartialPerson 的类型为 {name?: string; age?: number; height?: number;} const person: PartialPerson = { name: "zhangsan"; }
2、工具类型-Required:将<>中接口类型的属性设置:不可缺省的属性
Required 的作用是将传入的属性变为必选项,和上面的Partial恰好相反,其声明如下:
/** * Make all properties in T required * 将T中的所有属性设置为必选 */ type Required<T> = { [P in keyof T]-?: T[P]; };
可以看到,这里使用-?将属性设置为必选,可以理解为减去问号。使用形式和上面的Partial差不多:
type Person = { name?: string; age?: number; height?: number; } type RequiredPerson = Required<Person>; // RequiredPerson 的类型为 {name: string; age: number; height: number;} const person: RequiredPerson = { name: "zhangsan"; age: 18; height: 180; }
这里就使用Required将Person类型中的属性都指定为必选属性。
3. Readonly
将T类型的所有属性设置为只读(readonly),构造出来类型的属性不能被再次赋值。Readonly的声明形式如下:
/** * Make all properties in T readonly */ type Readonly<T> = { readonly [P in keyof T]: T[P]; };
来看下面的例子:
type Person = { name: string; age: number; } type ReadonlyPerson = Readonly<Person>; const person: ReadonlyPerson = { name: "zhangsan", age: 18 } person.age = 20; // Error: cannot reassign a readonly property
可以看到,通过 Readonly 将Person的属性转化成了只读,不能再进行赋值操作。Readonly 类型对于冻结对象非常有用。
4. Pick<Type, Keys>
从 Type类型中挑选部分属性 Keys 来构造新的类型。它的声明形式如下:
/** * From T, pick a set of properties whose keys are in the union K */ type Pick<T, K extends keyof T> = { [P in K]: T[P]; };
来看下面的例子:
type Person = { name: string; age: number; height: number; } const person: Pick<Person, "name" | "age"> = { name: "zhangsan", age: 18 }
这样就使用Pick从Person类型中挑出来了name和age属性的类型,新的类型中只包含这两个属性。
5. Record<Keys, Type>
Record 用来构造一个类型,其属性名的类型为Keys中的类型,属性值的类型为Type。这个工具类型可用来将某个类型的属性映射到另一个类型上,下面是其声明形式:
/** * Construct a type with a set of properties K of type T */ type Record<K extends keyof any, T> = { [P in K]: T; };
来看下面的例子:
type Pageinfo = { title: string; } type Page = 'home' | 'about' | 'contact'; const page: Record<Page, Pageinfo> = { about: {title: 'about'}, contact: {title: 'contact'}, home: {title: 'home'}, }
6. Exclude<Type, ExcludedUnion>
Exclude 用于从类型Type中去除不在ExcludedUnion类型中的成员,下面是其声明的形式:
/** * Exclude from T those types that are assignable to U */ type Exclude<T, U> = T extends U ? never : T;
来看下面的例子:
type Person = { name: string; age: number; height: number; } const person: Exclude<Person, "age" | "sex"> = { name: "zhangsan"; height: 180; }
这里就使用Exclude将Person类型中的age属性给剔除了,只会剔除两个参数中都包含的属性。
7. Extract<Type, Union>
Extract 用于从类型Type中取出可分配给Union类型的成员。作用与Exclude相反。下面是它的声明形式:
/** * Extract from T those types that are assignable to U */ type Extract<T, U> = T extends U ? T : never;
来看下面的例子:
type ExtractedType = Extract<"x" | "y" | "z", "x" | "y">; // "x" | "y"
该工具类型对于找出两种类型的公共部分很有用:
interface Human { id: string; name: string; surname: string; } interface Cat { id: string; name: string; sound: string; } // "id" | "name" type CommonKeys = Extract<keyof Human, keyof Cat>;
8. Omit<Type, Keys>
上面的 Pick 和 Exclude 都是最基础的工具类型,很多时候用 Pick 或者 Exclude 可能不如直接写类型更直接。而 Omit 就基于这两个来做的一个更抽象的封装,它允许从一个对象中剔除若干个属性,剩下的就是需要的新类型。下面是它的声明形式:
/** * Construct a type with the properties of T except for those in type K. */ type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
来看下面的例子:
type Person = { name: string; age: number; height: number; } const person: Omit<Person, "age" | "height"> = { name: "zhangsan"; }
这样就使用Omit从Person类型中剔除了 age 和 height 属性,只剩下 name 属性。
9. ReturnType
ReturnType会返回函数返回值的类型,其声明形式如下:
/** * Obtain the return type of a function type */ type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
来看下面的例子:
function foo(type): boolean { return type === 0 } type FooType = ReturnType<typeof foo>
这里使用 typeof 是为了获取 foo 的函数签名,等价于 (type: any) => boolean。
10. InstanceType
InstanceType 会返回 Type 构造函数类型的实例类型。其声明形式如下:
/** * Obtain the return type of a constructor function type */ type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: any) => infer R ? R : any;
来看下面的例子:
class Person { name: string; age: number; constructor(person: { name: string; age: number }) { this.name = person.name; this.age = person.age; } } type PersonInstanceType = InstanceType<typeof Person>; // PersonInstanceType 的类型:{ name: string; age: number }
当然,你可能不会这么写,因为可以直接使用UserManager类型:
class Person { name: string; age: number; constructor(person: { name: string; age: number }) { this.name = person.name; this.age = person.age; } } const person: Person = { name: "zhangsan", age: 18, };
这就等价于:
class Person { name: string; age: number; constructor(person: { name: string; age: number }) { this.name = person.name; this.age = person.age; } } type PersonInstanceType = InstanceType<typeof Person>; const person: PersonInstanceType = { name: "zhangsan", age: 18, };
当我们在 TypeScript 中创建动态类时,InstanceType可以用于检索动态实例的类型。
11. Parameters
Parameters 可以从函数类型Type的参数中使用的类型构造一个元组类型。其声明形式如下:
/** * Obtain the parameters of a function type in a tuple */ type Parameters<T extends (...args: any) => any> = T extends (...args: infer P) => any ? P : never;
来看下面的例子:
const add = (x: number, y: number) => { return x + y; }; type FunctionParameters = Parameters<typeof add>; // FunctionParameters 的类型:[x: number, y: number]
除此之外,还可以检测单个参数:
// "number" type FirstParam = Parameters<typeof add>[0]; // "number" type SecondParam = Parameters<typeof add>[1]; // "undefined" type ThirdParam = Parameters<typeof add>[2];
Parameters 对于获取函数参数的类型以确保类型安全很有用,尤其是在使用第三方库时:
const saveUser = (user: { name: string; height: number; age: number }) => { // ... }; const user: Parameters<typeof saveUser>[0] = { name: "zhangsan", height: 180, age: 18, };
12. ConstructorParameters
ConstructorParameters 可以从构造函数的类型来构造元组或数组类型。其声明形式如下:
/** * Obtain the parameters of a constructor function type in a tuple */ type ConstructorParameters<T extends abstract new (...args: any) => any> = T extends abstract new (...args: infer P) => any ? P : never;
它类似于参数,但适用于类构造函数:
class Person { private name: string; private age: number; constructor(person: { name: string; age: number }) { this.name = person.name; this.age = person.age; } } type ConstructorParametersType = ConstructorParameters<typeof Person>; // ConstructorParametersType 的类型:[person: { name: string, age: number}]
与 Parameters 类型一样,当使用外部库时,它有助于确保构造函数接受我们传入的参数:
class Person { private name: string; private age: number; constructor(person: { name: string; age: number }) { this.name = person.name; this.age = person.age; } } const params: ConstructorParameters<typeof Person>[0] = { name: "zhangsan", age: 18, };
13. NonNullable
NonNullable 通过从Type中排除null和undefined来创建新类型。它就等价于Exclude。其声明形式如下:
/** * Exclude null and undefined from T */ type NonNullable<T> = T extends null | undefined ? never : T;
来看下面的例子:
type Type = string | null | undefined; // string type NonNullableType = NonNullable<Type>;
这里就使用NonNullable将Type中的null和undefined剔除掉了。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)