系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
例如:第一章 Python 机器学习入门之pandas的使用
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 系列文章目录
- 前言
- 一、接口的作用
- 二、类型断言
- 三、type关键字
- 四、 declare 关键字
- 五、常用工具类
- 六、keyof和in
- 七、 & \
- 八、 extends
- 九、 对象动态添加属性
- 十、方法的重载和重写
- 十一、装饰器的作用
- 十二、类
- 十三、抽象类
- 十四、命名空间
- 十五、泛型
- 十六、never
- 十七、接口限制对象
- 十八、映射和重映射
- 十九、&实现过滤
- 二十、promise泛型
- 二十一、函数
- 二十二、接口中使用泛型
- 二十三、infer
- 二十四、typeof
- 二十五、as const
- 二十六、数组
- 二十七、获取数组或对象的索引签名
- 二十八、元组
- 二十九、协变和逆变
- 三十、x extends y? a:b
- 三十一、type
- 三十二、import type 和 import
- 三十三、声明合并
- 三十四、InstanceType
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、接口的作用
点击查看参考csdn
接口可多继承(接口内有同样类型名,但类型不同,则不可继承),类不行
- 限制对象
- 限制数组
- 限制函数
- 类实现接口
- 接口继承接口
- 接口可继承类,类再实现接口
class School{
private b:string='ss'
}
//报错
// class Student implements test1{
// c=2
// a=''
// }
//正常
class Student extends School implements test1{
c=2
a=''
}
interface test1 extends School{
a:string
}
二、类型断言
点击查看参考csdn
语法格式:
(1) <类型>值
(2)值 as 类型
注意:
1. 类型断言更像是类型的选择,而不是类型的转换
2. 联合类型:我们只能访问此联合类型的所有类型里共有的成员。
//这是错误的代码
//那么就是说,length应该是string和number共有的属性才对,
//但是number没有length的属性,所以上述代码放在ts文件里,
//if语句中的length就会报错(“number”上不存在属性“length”)
function func(val: string | number) :number {
if (val.length) {
return val.length
} else {
return val.toString().length
}
}
//正确要先判断类型
function func(val: string | number) :number {
if (typeof val == 'string' && val.length) {
return val.length
} else {
return val.toString().length
}
}
interface a{
b:string
}
interface b{
c:string
}
interface c extends a,b{
d:string
}
class e implements c{
d=''
b=''
c=''
}
//使用类型断言可以初始化空,后面可以单独初始化
let f:c=<c>{}
f.b=' '
//会报错
let f:c={}
三、type关键字
//type是用来定义新类型,常结合typeof使用
type FType = boolean | string | number;
type Shape = { name: string }
type Circle = Shape & { radius: number }
function foo(circle: Circle) {
const name = circle.name
const radius = circle.radius
}
四、 declare 关键字
点击查看参考csdn
类型声明的作用?
- 用来为已存在的 JS 库提供类型信息;声明文件可以让我们不需要将JS重构为TS,只需要加上声明文件就可以使用系统。
添加链接描述
定义.vue文件或模块 - 定义纯粹的类型
下面是对原有的js提供类型
declare let age: number;
declare function getAge(): number | string;
declare class Person { };
下面是定义纯粹的类型
//纯粹定义类型,要结合type,declare 可有可无
declare type dd = {
a:string
}
declare type sd = string
如果.d.ts文件过多或类型过多,可以使用module,
utilTypes.d.ts文件
declare module "cc"{
export declare type dd = {
a:string
}
export declare type sd = string
}
test.ts文件
import { dd } from "cc"
let aa:dd= {
a:"11"
}
如果不使用module,可以直接使用,不用导入
如果.d.ts文件不在根目录下,需要在tsconfig.ts配置include
{
"compilerOptions": {
},
"include": ["src/**/*.ts", "src/**/*.vue", "src/**/*.tsx", "src/**/*.d.ts"], // **Represents any directory, and * represents any file. Indicates that all files in the src directory will be compiled
"exclude": ["node_modules", "dist"] // Indicates the file directory that does not need to be compiled
}
五、常用工具类
添加链接描述
重点记住下面几个
- Record
//Record:生成接口类型,然后我们使用传入的泛型参数分别作为接口类型的属性和值
//源码
type Record<K extends keyof any, T> = {
[P in K]: T;
};
//使用
type MenuKey = 'home' | 'about' | 'more';
interface Menu {
label: string;
hidden?: boolean;
}
const menus: Record<MenuKey, Menu> = {
about: { label: '关于' },
home: { label: '主页' },
more: { label: '更多', hidden: true },
};
- 接口类型(对象)
Pick
//可以从类型中选取出指定的键值,然后组成一个新的类型
//源码
type Pick<T, K extends keyof T> = {
[P in K]: T[P];
};
//使用
// 定义一个通用的 Person 类
interface Person {
name: string;
age?: number;
weight?: number;
}
type NewPerson = Pick<Person, 'name' | 'age'>;
// 相当于
interface NewPerson {
name: string;
age?: number;
}
Omit
//返回去除指定的键值之后返回的新类型
//源码
type Omit<T, K extends keyof any> = Pick<T, Exclude<keyof T, K>>;
//使用
// 定义一个通用的 Person 类
interface Person {
name: string;
age?: number;
weight?: number;
}
type NewPerson = Omit<Person, 'weight' | 'name'>;
// 相当于
interface NewPerson {
age?: number;
}
为接口或type增加新key
//一
type user ={
name:string
age:number
sex:string
}
type newuser ={dqwd:number} & user
//二
//
type MyType {
key: string;
value: number;
}
// 新类型必须使用interface,type无法使用继承
interface NewMyType extends MyType {
newKey: number;
}
扩展:使用&不当可能会出现错误
type aa=string | number
type c=aa & string //string
interface aa{
a:number
b:string
}
interface cc{
a:string
}
//a属性编程never无法赋值,报错
let c:aa & cc={
b:'',
}
接口修改key或keyi的类型
思路:新的key名字随意,直接修改不太好做到,可以先剔除需要修改的key在增加即可
type user ={
name:string
age:number
sex:string
}
//写成通用函数有难度,下面的简单
type Sx = Omit<user,"name"> &{"hahah":number}
新的key名字包含原来修改的key名字
修改一个
//T是接口,K是修改的key,写死getkey
type ChangeOneKey<T extends {[p :string]:any},K extends keyof {[p :string]:any}> = {
[p in keyof T as `get${keyof Pick<T,K>}` | keyof Omit<T,K>]: T[p]
}
- Exclude
//从 T 中剔除可以赋值给 U 的类型,如果 T 是 U 的子类型,则返回 never 不是则返回 T
//源码
type Exclude<T, U> = T extends U ? never : T (会遍历T的每一个类型进行判断)
普通判断不会遍历,注意区分
```javascript
type A = number | string | boolean
type B = number | boolean
type ssss= A extends B ? never : A
//ssss: number | string | boolean
//使用
type A = number | string | boolean
type B = number | boolean
type Foo = Exclude<A, B>
// 相当于
type Foo = string
或使用 extends
```javascript
type sadqwq = "1"|"2"|"333"
function pluck<T, K extends sadqwq>(a:T,b:K):void{
console.log(b);
}
pluck(2,"2")
六、keyof和in
keyof和in
keyof
前言:类型不可以作为值传递,即不可以打印,想要查看可以先注解一个变量,鼠标放上去就可以看到类型
type Person = {
id: number;
name: string;
age: number;
};
type P1 = keyof Person; //'id' | 'name' | 'age'
type P2 = Person[keyof Person]; // number | string
1. Person['key'] 是查询类型(Lookup Types), 可以获取到对应属性类型的类型;
2. Person[keyof Person]本质上是执行 Person['id' | 'name' | 'age'];
3. 由于联合类型具有分布式的特性,Person['id' | 'name' | 'age'] 变成了 Person['id'] | Person['name'] | Person['age'];
4. 最后得到的结果就是 number | string.
in看成forin循环,被 in 进行(遍历)运算的都是联合类型
type cc= { [P in 'x' | 'y']:P }//P进行了两次遍历,每次遍历P都不一样
//结果
type cc = {
x: "x";
y: "y";
}
七、 & \
& | 都可以看做联合类型,&用于接口联合,| 可以用做普通类型
string | number
string & number //错误
type z= {a:string} & {b:string} //自定义类型z必须要有a b 两个属性
联合类型 |
当联合类型是类的联合时,One | Two 只能使用两个类中共同的方法
class One{
public up(){
console.log("up");
}
public say(){
console.log("One say");
}
}
class Two{
public down(){
console.log("down");
}
public say(){
console.log("Two say");
}
}
let one=new One()
let two = new Two()
let three:One|Two=<One| Two>{}
three['say']=one['say']
//three.say=one['say'] 共有方法怎么定义都可以
three["up"]=one['up']
//three.up=one['up'] 会直接爆红,上面定义不会爆红,调用时才爆红
three.say()
八、 extends
extends 较为复杂,不仅仅代表继承
type c= string | number
type a=number
type b=string | number
type g= object
//左边小类型可以赋给右边大类型,取值第一个
type d= a extends c? never: ' ' //never
type e= b extends c? never: ' ' //never
type f= b extends c? never: ' ' //never
type h= g extends c? never:'' //''
//注意是接口类型或对象类型时,只有相同时,左边才能赋值给右边
九、 对象动态添加属性
添加链接描述
ts不允许对象动态
let studet={
a:2
}
studet.cc=3 //报错
studet['cc']=3 //虽然不报错,但访问还是会报错,不存在改属性
log(studet.cc)//不存在改属性
可以加一个接口,实现自定义增加属性
interface studet{
[key:string]:number
}
let studet:studet={
a:2
}
studet.cc=3 //不会报错
十、方法的重载和重写
添加链接描述
添加链接描述
1.重写方法名和参数(包括类型)不能改变,
2.重载方法名相同,参数必须不同(可以仅仅类型不同)注意:必须要把精确的定义放在前面,最后函数实现时,需要使用 |操作符或者?操作符,把所有可能的输入类型全部包含进去,以具体实现。 即最下面的方法需要兼容上面的方法
//重载
function run(num:number):void;
function run(str:string,flag:boolean):void;
function run(str:string,flag?:boolean):void;
function run(str:number|string,flag?:boolean):void{
if(typeof str === 'string'){
console.log("fur")
}else{
console.log(1)
}
}
run(1)
run("fur")
run("fur",true);
十一、装饰器的作用
添加链接描述
结论:类装饰和属性装饰器同是在运行时调用,方法装饰器是在方法调用时调用
类装饰
例如声明一个函数 addAge 去给 Class 的属性 age 添加年龄.
function addAge(constructor: Function) {
constructor.prototype.age = 18;
}
@addAge
class Person{
name: string;
age!: number;
constructor() {
this.name = 'huihui';
}
}
let person = new Person();
console.log(person.age); // 18
方法装饰:类似Object.defineProperty(几乎一样),在方法调用时调用(方法调用之前)。
接受三个参数
target :
静态成员 :类的构造函数
实例成员 :类的原型对象
method : 成员的名字
descriptor : 成员的属性描述符
应用:函数调用日志
class Techer extends Proper{
constructor(){
super()
}
@log
a(c:number|string):string{
console.log("aaa");
return '1111'
}
}
function log(target:Object, name:string, descriptor:any) {
var oldValue = descriptor.value;
console.log(" descriptor.value", descriptor.value);
descriptor.value = function () {
//arguments是name函数的参数
console.log(`Calling "${name}" with`, arguments);
//注意此时修改了原函数this指向,实例调用带有此注解的方法,this指向null
oldValue.apply(null, arguments);
}
// return descriptor;
}
let techer=new Techer()
techer.a('c') //调用见图
techer.a('d')
装饰器工厂需要调用并返回一个装饰器
执行顺序
当多个装饰器应用于一个声明上,将由上至下依次对装饰器表达式求值,求值的结果会被当作函数,由下至上依次调用,例如如下:
function f() {
console.log("f(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("f(): called");
}
}
function g() {
console.log("g(): evaluated");
return function (target, propertyKey: string, descriptor: PropertyDescriptor) {
console.log("g(): called");
}
}
class C {
@f()
@g()
method() {}
}
// 输出
f(): evaluated
g(): evaluated
g(): called
f(): called
十二、类
类可以作为类型,(包括继承父类)
如果类有私有属性或私有方法,则只能用来限定该类的实例
只读属性
class Mytest{
readonly a:number=2
}
十三、抽象类
抽象类继承抽象类,子抽象类可以实现父类抽象方法也可以不实现(实现没啥用),但具体类必须实现
抽象类和类可访问性都是父级大于等于子集
十四、命名空间
注意:编译后的js都要引入
添加链接描述
十五、泛型
//官网例子
function pluck<T, K extends keyof T>(o: T, names: K[]): T[K][] {
return names.map(n => o[n]);
}
interface Person {
name: string;
age: number;
}
let person: Person = {
name: 'Jarid',
age: 35
};
let strings: string[] = pluck(person, ['name']); // ok, string[]
function pluck<T, K extends keyof T>(o: T, names: K[]): T[] {
// return names.map(n => o[n]);
//会报错,数组里的类型不能写死
return [{name:'11',age:1}]
}
interface Person {
name: string;
age: number;
}
let person: Person = {
name: 'Jarid',
age: 35
};
let strings = pluck(person, ['name']); // ok, string[]
十六、never
nver类型不可以被赋值
//初始化数组时,没有定义每一项的类型,则被初始化成never类型,后面无法赋值
const bann = []
bann[1] = 2 //不能将类型“number”分配给类型“never”。
never用于对象(接口)等的属性(属性非属性值,例如:{a:1} 即a使never)时,属性被删除
type VariantA = {
a: string,
}
type VariantB = {
b: number,
}
declare function fn(arg: VariantA | VariantB): void
const input = {a: 'foo', b: 123 }
fn(input) // 这违背了我们的设计,但是 TypeScript 不会报警
type VariantA = {
a: string
b?: never
}
type VariantB = {
b: number
a?: never
}
declare function fn(arg: VariantA | VariantB): void
const input = {a: 'foo', b: 123 }
fn(input) // ❌ Types of property 'a' are incompatible
十七、接口限制对象
//无限个属性
interface objectInter{
//会报错
// name:string
[key:string]:number
}
let myobj:objectInter={
a:1,
b:2
}
//有限属性
interface Person {
name: string;
age: number;
}
type Optional<T> = {
[K in keyof T]?: T[K]
};
const person: Optional<Person> = {
name: "Tobias"
};
// in 它的语法与索引签名的语法类型,内部使用了 for .. in。 具有三个部分
type Nullable<T> = { [P in keyof T]: T[P] | null }
type Partial<T> = { [P in keyof T]?: T[P] }
十八、映射和重映射
映射:in 与 联合类型连用
视频
笔记
as 对映射类型中的键进行重新映射
十九、&实现过滤
type aa=string | number
type c=aa & string //string
interface aa{
a:number
b:string
}
interface cc{
a:string
}
//a属性编程never无法赋值,报错
let c:aa & cc={
b:'',
}
二十、promise泛型
Promise:Promise的泛型T代表promise变成成功态之后resolve的值,resolve(value)
添加链接描述
二十一、函数
type sayType = <T>(operate: T, person: string, content: string) => boolean;
var say: sayType = function (operate, person, content) {
if (person === '' || content === '') return false;
console.log(`${person} ${operate}:${content}`);
return true;
};
say<string>('','','')
const foo = <T>(x: T): T => x;
const foo = <T extends {}>(x: T): T => x;
const foo = <T extends Record<string, unknown>>(x: T): T => x;
//<T>(x: T) => T类型 x => x函数
const foo: <T>(x: T) => T = x => x;
const identity = <T>(arg: T): T => {
console.log(arg);
return arg;
};
const renderAuthorize = <T>(Authorized: T): ((currentAuthority: CurrentAuthorityType) => T) => (
currentAuthority: CurrentAuthorityType,
): T => {
return
};
函数表达式
ts中的 =>用来表达函数的定义: 左边是输入类型,需要用括号括起来,右边是输出类型
let kate3: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
}
// ts中的 =>用来表达函数的定义: 左边是输入类型,需要用括号括起来,右边是输出类型
函数声明
function sayHi3(x:number,y:number): number {
return x + y
}
sayHi3(1,5)
// sayHi3(2,5,7) //Expected 2 arguments, but got 3.
// sayHi3(5) // An argument for 'y' was not provided.
接口限制函数
interface SayHi4 {
(x: number, y: number): number;
}
let sayhi6: SayHi4 = function(x, y) { return x+y}
泛型接口
interface Search {
<T,Y>(name:T,age:Y):T
}
let fn:Search = function (name id){
console.log(name, id)
return name;
}
fn('li',11);//编译器会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型
剩余参数
可以使用 ...rest 的方式获取函数中的剩余参数(rest 参数)
function push(array: any[], ...items:any []) {
items.forEach(item => {
array.push(item)
})
}
let a: any[] = []
push(a, 1,2,3,4)
二十二、接口中使用泛型
// 注意,这里写法是定义的方法哦
interface Search {
<T,Y>(name:T,age:Y):T
}
let fn:Search = function <T, Y>(name: T, id:Y):T {
console.log(name, id)
return name;
}
fn('li',11);//编译器会自动识别传入的参数,将传入的参数的类型认为是泛型指定的类型
//写法定义的是属性
interface objType {
money: (value: number) => number
arr: () => string[]
}
const obj2: objType = {
money: (val) => val,
arr: () => ['1'],
}
console.log(obj2.money(2))
console.log(obj2.arr())
//接口使用泛型
interface objType<T1, T2> {
money: (value: T1) => T1
arr: () => T2[]
}
const obj2: objType<number, string> = {
money: (val) => val,
arr: () => ['1'],
}
console.log(obj2.money(2))
console.log(obj2.arr())
二十三、infer
infer语法的限制如下:
infer只能在条件类型的 extends 子句中使用
infer得到的类型只能在true语句中使用, 即X中使用
/**
* Obtain the return type of a function type
*/
type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
type Last<Arr extends unknown[]> = Arr extends [...infer rest,infer Ele]? Ele : never;
二十四、typeof
添加链接描述
typeof作用:
1、可以拿到某个js文件类型
import XtxSwiper from './XtxSwiper.vue’
type xx = typeof XtxSwiper
2、可以拿到某个变量类型
typeof和数组使用
const arr12=[1,2,'s']
//type lei1 = (string | number)[]
type lei1= typeof arr12
typeof和数组使用
const arr123=[1,2,'s'] as const
//type lei2 = readonly [1, 2, "s"]
type lei2= typeof arr123
typeof和函数使用
function add(a: number, b: number) {
return a + b;
}
// (a: number, b: number) => number
type AddType = typeof add;
typeof和对象使用
const lolo = {
name: "lolo",
age: 7,
address: {
province: "福建",
city: "厦门",
},
};
interface Person {
name: string;
age: number;
address: {
province: string;
city: string;
};
}
//type Person = {
// name: string;
// age: number;
// address: {
// province: string;
// city: string;
// };
//}
type Person = typeof lolo;
// type Address = {
// province: string;
// city: string;
// }
type Address = typeof lolo["address"];
二十五、as const
不加as const
const arr123=[1,2,'s']
//(number | string) [1, 2, "s"]
type sadas=typeof arr123
加as const
const arr123=[1,2,'s'] as const
//readonly [1, 2, "s"]
type sadas=typeof arr123
不加as const
let aaa:string='sdad'
//string
type asdqda=typeof aaa
加as const
let aaa:string='sdad' as const
//'sdad'
type asdqda=typeof aaa
二十六、数组
二十七、获取数组或对象的索引签名
数组的索引只能是number
数组
type asweq=(number|string)[]
// string | number
type dsad=asweq[number]
// 1 | 2
type cds = [1,2][number]
接口
interface AnyObject {
[key: string]: number
}
//number
type dasdqwe=AnyObject[string]
interface P{
a:string
b:number
}
//报错
type dasdqwe2131=P[string]
//1
type cdssad={
a:1
}['a']
二十八、元组
type tesla = ['tesla', 'model 3', 'model X', 'model Y']
let ccsda:tesla=['tesla', 'model 3', 'model X', 'model Y']
ccsda.push('model Y')
ccsda.push('model 3')
//报错,元祖里面没有number类型
ccsda.push(3)
二十九、协变和逆变
添加链接描述
逆变和协变都是型变,是针对父子类型而言的,非父子类型自然就不会型变,也就是不变
像 java 里面的类型都是通过 extends 继承的,如果 A extends B,那 A 就是 B 的子类型。这种叫做名义类型系统(nominal type)。而 ts 里不看这个,只要结构上是一致的,那么就可以确定父子关系,这种叫做结构类型系统(structual type)。
协变和逆变都是指可以成功的
协变:子可以赋值给父
逆变:函数才能实现(非官方,个人理解)
但是在 ts2.x 之前,也就是父类型可以赋值给子类型,子类型可以赋值给父类型,既逆变又协变,叫做“双向协变”
// 协变
interface Person {
name: string;
age: number;
}
interface Son {
name: string;
age: number;
hobbies: string[]
}
let peo:Person={
name:'',
age:1,
}
let son:Son={
name: '',
age: 2,
hobbies: ['']
}
//协变
peo=son
//报错
son=peo
//函数可以实现逆变
看链接
三十、x extends y? a:b
type A1 = 'x' extends 'x' ? string : number; // string
type A2 = 'x' | 'y' extends 'x' ? string : number; // number
type P<T> = T extends 'x' ? string : number;
type A3 = P<'x' | 'y'> // ?
分配条件类型:
意思就是对于使用extends关键字的条件类型(即上面的三元表达式类型),如果extends前面的参数是一个泛型类型,当传入该参数的是联合类型,则使用分配律计算最终的结果。分配律是指,将联合类型的联合项拆成单项,分别代入条件类型,然后将每个单项代入得到的结果再联合起来,得到最终的判断结果。
- 防止条件判断中的分配
type P<T> = [T] extends ['x'] ? string : number;
type A1 = P<'x' | 'y'> // number
//层级 unknown 是顶层,never是最底层,any是墙头草
type A2 = P<never> // string
三十一、type
type:
- 起类型别名
2.以原有类型的具体值(‘ss’,1 , true , {a:1})增加新类型
type aa= 1
let c:aa=1
//报错
// aa=2
type z={
a:1
}
let zz:z={
a:1,
//报错
// b:2
}
type xx=true
let flage:xx=true
//报错
// flage=false
//可以使用扩展运算符,但不能使用运算符,类型不能运算
type arr1=unknown[]
type arr2=unknown[]
type Concat<T extends arr1,U extends arr2>=[...T,...U]
//[1, 2]
type xs=Concat<[1],[2]>
//type限制函数,
type typ2={
option<T>(c:T,d:number):number
option1:<T>(a:T)=>string
}
type typ1={
option(c:string):number
option1:<T>(a:T)=>string
}
//参数可加可不加,如果加必须符合类型
let casdzx:typ1={
option:()=>1,
option1:()=>""
}
三十二、import type 和 import
import type 是 TypeScript 2.9 版本引入的一种新的类型导入语法。虽然在某些情况下 import 和 import type 可以互换使用,但它们并不完全等价。具体来说,import type 只能用于导入类型,而 import 则可以用于导入任何类型的值(变量、函数、类等)。
如果你使用 import 导入一个模块中的变量、函数或类,那么这些值会被加载到当前文件的命名空间中,可以随时使用它们。而如果你使用 import type 导入一个模块中的类型,则仅在编译阶段使用该类型,并且不会在运行时加载任何额外的代码。
通常情况下,建议尽可能使用 import type 来导入类型,因为它可以帮助减小生成的 JavaScript 文件的大小,并且更加明确地表达你的意图。但是如果你需要同时导入类型和值,或者需要动态导入模块,那么就必须使用 import。
三十三、声明合并
注意是接口声明合并,declare type 不能合并
例如合并接口sdd
untils.d.ts文件
declare module "helo"{
export interface sdd {
a:string,
b:string,
c:1
}
}
tee.d.ts文件
import * as untils from "helo"
declare module 'helo'{
export interface sdd {
c:number
}
export declare type ss= {
e:number
}
}
利用接口合并可以对npm包进行扩展
/* eslint-disable */
import * as axios from 'axios';
// 扩展 axios 数据返回类型,可自行扩展
declare module 'axios' {
export interface AxiosResponse<T = any> {
code: number;
data: T;
message: string;
type?: string;
[key: string]: T;
}
}
还可以对原对基本类型进行扩展,例如string(文件只要有一个export或import就是模块话文件)
这样可以骗过编译器,但是编译后的js无法运行
interface String{
'b':()=>void;
}
let a = "a"
a.b= ()=>{
console.log(1111);
}
a.b()