前端基础知识点(2)

160 阅读3分钟

浅谈interface 与 type的区别

1.interfacetype都能用来描述对象和函数的类型

  name: string,
  age: number,
  say(s:string,y:string): string,
};
interface People {
  name: string,
  age:number,
  say(x:string,y:string):string
}
let testObj:User = {
  name: '李四',
  age: 23,
  say(x,y){ return x + y}
}
console.log(testObj.say('你','我'));

2.interfacetype都能进行类型扩展

不过需要注意的是 interface用的是extends, 而type用的是 & 符号

  name: string;
}
interface User extends Name {
  age: number
}
let stu:User = {name: 'wang', age: 10}
//interface的扩展可以通过type交叉(&)类型实现
type Name = {
   name: string;
}
type User = Name & {age: number}
let stu:User={name: 'wang', age: 18}
//interface 扩展 type
type Name = {
  name: string;
}
interface User extends Name {
  age: number;
}
let stu:User={name: 'wang', age: 89}
//type与interface交叉
interface Name {
  name: string;
}
type User = Name & {
  age: number;
}
let stu:User={name:'wang', age: 18}

3.类型名定义相同时,interface 会合并而 type 会报错

interface Name {
  name: string
}
interface Name {
  age: number
} // 正常运行切回合并

type Name = {
  name: number
}
type Name = {
  age: number
} // 报错

image.png

字面量与联合类型的使用

1.字面量类型

let str1 = 'abc'
const str2 = 'abc'

通过 TS 类型推论机制,可以得到答案:

  1. 变量 str1 的类型为:string
  2. 变量 str2 的类型为:'abc'

解释:

  1. str1 是一个变量(let),它的值可以是任意字符串,所以类型为:string
  2. str2 是一个常量(const),它的值不能变化只能是 'abc',所以,它的类型为:'abc'

注意:此处的 'abc',就是一个字面量类型,也就是说某个特定的字符串也可以作为 TS 中的类型,任意的 JS 字面量(比如,对象、数字等)都可以作为类型使用

2.字面量类型的实际应用

type Gender = '男' | '女'
let gender: Gender = '女'

image.png

3.联合类型

联合类型和交叉类型比较相似,联合类型通过|符号连接多个类型从而生成新的类型。它主要是取多个类型的交集,即多个类型共有的类型才是联合类型最终的类型。联合类型可以是多个类型其中一个,可做选择,比如:string | number,它的取值可以是string类型也可以是number类型。

3.1 声明变量的时候设置变量类型
let a:string|number|boolean;
a = 's';
a = 1;
a= false;
3.2 多个接口类型进行联合
interface X{
	q:number,
	w:string,
	r:string
}
interface Y{
	q:number
	r:string,
}
type XY = X | Y
let value:XY = {
    q:1,
    r:'r'
}
3.3 函数接口类型联合
interface X{
	x:()=>string;
	y:()=>Number;
}
interface Y{
	x:()=>string;
}
type XY = X|Y;
function func1():XY{
//此处不进行类型断言为XY在编辑器中会报类型错误
  return {} as XY

}
let testFunc = func1();
testFunc.x();
testFunc.y(); //Error:类型“XY”上不存在属性“y”,类型“Y”上不存在属性“y”。

axios 在 TypeScript 的使用

import axios from 'axios'
import type { AxiosInstance, AxiosRequestConfig, AxiosResponse, InternalAxiosRequestConfig } from 'axios'

// 定义一个常见后端请求返回
type BaseApiResponse<T> = {
  code: number
  message: string
  result: T
}
// 拓展 axios 请求配置,加入我们自己的配置
interface RequestOptions {
  // 是否全局展示请求 错误信息
  globalErrorMessage?: boolean
  // 是否全局展示请求 成功信息
  globalSuccessMessage?: boolean
}

// 拓展自定义请求配置
interface ExpandAxiosRequestConfig<D = any> extends AxiosRequestConfig<D> {
  interceptorHooks?: InterceptorHooks
  requestOptions?: RequestOptions
}

// 拓展 axios 请求配置
interface ExpandInternalAxiosRequestConfig<D = any> extends InternalAxiosRequestConfig<D> {
  interceptorHooks?: InterceptorHooks
  requestOptions?: RequestOptions
}

// 拓展 axios 返回配置
interface ExpandAxiosResponse<T = any, D = any> extends AxiosResponse<T, D> {
  config: ExpandInternalAxiosRequestConfig<D>
}

export interface InterceptorHooks {
  requestInterceptor?: (config: InternalAxiosRequestConfig) => InternalAxiosRequestConfig
  requestInterceptorCatch?: (error: any) => any
  responseInterceptor?: (response: AxiosResponse) => AxiosResponse | Promise<AxiosResponse>
  responseInterceptorCatch?: (error: any) => any
}

// 导出Request类,可以用来自定义传递配置来创建实例
export default class Request {
  // axios 实例
  private _instance: AxiosInstance
  // 默认配置
  private _defaultConfig: ExpandAxiosRequestConfig = {
    baseURL: '/api',
    timeout: 5000,
    requestOptions: {
      globalErrorMessage: true,
      globalSuccessMessage: false
    }
  }
  private _interceptorHooks?: InterceptorHooks

  constructor(config: ExpandAxiosRequestConfig) {
    // 使用axios.create创建axios实例
    this._instance = axios.create(Object.assign(this._defaultConfig, config))
    this._interceptorHooks = config.interceptorHooks
    this.setupInterceptors()
  }

  // 通用拦截,在初始化时就进行注册和运行,对基础属性进行处理
  private setupInterceptors() {
    this._instance.interceptors.request.use(this._interceptorHooks?.requestInterceptor, this._interceptorHooks?.requestInterceptorCatch)
    this._instance.interceptors.response.use(this._interceptorHooks?.responseInterceptor, this._interceptorHooks?.responseInterceptorCatch)
  }

  // 定义核心请求
  public request(config: ExpandAxiosRequestConfig): Promise<AxiosResponse> {
    // !!!⚠️ 注意:axios 已经将请求使用 promise 封装过了
    // 这里直接返回,不需要我们再使用 promise 封装一层
    return this._instance.request(config)
  }

  public get<T = any>(url: string, config?: ExpandAxiosRequestConfig): Promise<AxiosResponse<BaseApiResponse<T>>> {
    return this._instance.get(url, config)
  }

  public post<T = any>(url: string, data?: any, config?: ExpandAxiosRequestConfig): Promise<T> {
    return this._instance.post(url, data, config)
  }

  public put<T = any>(url: string, data?: any, config?: ExpandAxiosRequestConfig): Promise<T> {
    return this._instance.put(url, data, config)
  }

  public delete<T = any>(url: string, config?: ExpandAxiosRequestConfig): Promise<T> {
    return this._instance.delete(url, config)
  }
}