写在结尾
- 我写了一年多
TypeScript
,总结了以下几个点,心愿能够帮到大家 - 如果感觉写得不错,记得来个
关注/在看
比拟容易遇到的问题
给一个对象增加属性
interface Obj { a: string;}const obj: Obj = { a: "1",};obj.b = 2;
- 此时会呈现谬误提醒:
类型“Obj”上不存在属性“b”。
- 要想解决这个问题,要应用索引签名
interface Obj { a: string; [index: string]: string | number;}const obj: Obj = { a: "1",};obj.b = 2;
- 大家很好奇,为什么我这里会退出
[index: string]: string | number;
,类型是字符串或者数字。因为:
当你申明一个索引签名时,所有明确的成员都必须合乎索引签名
函数重载
- 场景:函数有多个参数,而且参数不确定时,函数运行逻辑不统一
// 重载function padding(all: number);function padding(topAndBottom: number, leftAndRight: number);function padding(top: number, right: number, bottom: number, left: number);// Actual implementation that is a true representation of all the cases the function body needs to handlefunction padding(a: number, b?: number, c?: number, d?: number) { if (b === undefined && c === undefined && d === undefined) { b = c = d = a; } else if (c === undefined && d === undefined) { c = a; d = b; } return { top: a, right: b, bottom: c, left: d };}
这样函数兼容 传 1、2、4个参数。 然而只有传三个,就会报错。
- 函数重载最重要的是,最终申明(从函数外部看到的真正申明)与所有重载兼容(与下面的索引签名统一)
下载的第三方npm库没有ts申明文件
- 例如:
npm i somePackage --save import somePackage from 'somePackage';
- 然而此时提醒:
找不到模块“somePackage”或其相应的类型申明。
- 此时你能够在我的项目根目录下新建index.d.ts,编写如下代码:
declare module 'somePackage';...
这个问题迎刃而解
泛型
- 这个问题很容易困扰小白,其实泛型简略来说,就是一个
类型变量
,如下所示:
class Peter { niubi<T>(a: T): T[] { return [a]; }}
此时的T就是一个泛型,它是一个可变的类型。依据你传入niubi
这个办法的参数对象来确定的,当咱们传入的a
是字符串,那么T就为string
.返回的就是一个item
为字符串的数组
class Peter { niubi<T>(a: T): T[] { return [a]; }}const obj = new Peter();let res = obj.niubi("hehe");res = 1;res = ["2"];
此时res = 1会报错不能将类型“number”调配给类型“string[]”
, 因为此时TS推断进去,res必然为一个数组,且外面的item是一个字符串.
res = ["2"]
则不会报错
- 泛型能够说是TS外面的一个难点,然而其实它只是一个可变的类型变量。
- 调整参数后:
let res2 = obj.niubi(2);res2 = 2;
- 会报错:
不能将类型“number”调配给类型“number[]”。
最初要记住的是,既然是类型变量。那么这个变量也能够是一个泛型。
class Peter { niubi<T>(a: T): T[] { return [a]; }}const obj = new Peter();function test<T>(b: T): T { return b;}let res = obj.niubi(test(1));
- 看到这里必定有人会说,Peter你脱裤子放屁啊。这个还不如用any.那你再看上面这段代码,咱们封装api申请的时候。
- 首先定义好返回的接口。(返回的接口个别都是有对立的格局,状态码和result,data等)
// 申请接口数据export interface ResponseData<T = any> { /** * 状态码 * @type { number } */ code: number; /** * 数据 * @type { T } */ result: T; /** * 音讯 * @type { string } */ message: string;}
- 这里的
data
数据是动静的格局,咱们能够用泛型来定义。 - 这里用了两次泛型,先定义好返回的
data
数据,再用泛型形式传入,组装好返回的整个返回数据接口(蕴含code,result,data
)。再接着传入到真正的申请函数中
// 在 axios.ts 文件中对 axios 进行了解决,例如增加通用配置、拦截器等import Ax from './axios';import { ResponseData } from './interface.ts';export function getUser<T>() { return Ax.get<ResponseData<T>>('/somepath') .then(res => res.data) .catch(err => console.error(err));}
- 在真正的申请函数中应用了泛型,即传入任意类型参数
<T>
,那么便返回一个Promise
格调的Promise<T>
数据 :
const get = <T>(config: { url: string; headers?: { [key: string]: string } }): Promise<T> => { const fetchConfig = { method: 'GET', Accept: 'application/json', 'Content-Type': 'application/json', ...(config.headers || {}) }; return fetch(config.url, fetchConfig).then<T>(response => response.json());};
总结两次泛型的间断应用:
1.应用data
作为泛型,传入
2.组装成{code,result,data}
这种类型接口
3.将第二步的组装后类型作为泛型<T>
传入get
办法中
4.返回一个Promise
格调的Promise<T>
数据
这样做的意义,提取可变的数据类型data
,让TS推断出这个接口返回的数据是怎么样的。缩小不必要的反复代码,即每次接口调取都会返回的数据格式类型:code
和result
- 置信你通过这段代码和文字,能真正了解
TS
的泛型如何用,什么中央应用,以及应用的意义了。
颗粒度定义类型后的问题
- 当咱们颗粒度比拟细定义了接口当前,可能存在接口复用的问题,例如:
interface test1 { a: string;}interface test2 { b: string;}
- 此时我想要定义一个两个属性都领有的对象,那么能够应用联结类型。
const obj: test1 & test2 = { a: "1", b: "2",};
- 如果我想定义一个只有
a/b
的对象,能够应用
const obj: test1 | test2 = { a: "1",};
可能有人会说,怎么会写这么简略的货色。
- 这里是为了接下来的类型兼容性打基础,TS外面最重要的就是
type类型
,类型零碎就是它的外围。 - 咱们能够用两个不同的变量来相互赋值来测验,他们的类型是否兼容,例如:
interface Test1 { a: number; b: number; c: string;}interface Test2 { a: number; b: number;}let test1: Test1 = { a: 1, b: 2, c: "3",};let test2: Test2 = { a: 1, b: 2,};test1 = test2;
此时提醒类型 "Test2" 中短少属性 "c",但类型 "Test1" 中须要该属性。
- 然而当咱们用test1赋值给test2的时候:
test2 = test1;
这个时候是能够的
- 这里其实暗藏着一些逻辑,
Test1
接口比Test2
接口多一个c
属性,Test2
接口能够说是Test1
接口的子类。这是多态性
对于如何解决、判断TS的类型兼容性,大家能够看上面这些类型
- 协变(Covariant):只在同一个方向;
- 逆变(Contravariant):只在相同的方向;
- 双向协变(Bivariant):包含同一个方向和不同方向;
- 不变(Invariant):如果类型不完全相同,则它们是不兼容的。