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. 访问控制级别表

privatedefaultprotectpublic
同一个类中 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剔除掉了。

 

posted @   爵岚  阅读(248)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示