一篇够用的TypeScript总结【实用】
一、前言
鬼哥
今天给大家分享的这篇文章来自,有赞@俊劫
大佬的一篇总结文章,在坐地铁的时候,花个10分钟
碎片时间来学习下,还是非常有必要的,还是非常有收获的一篇文章。
没写ts
之前看官方文档 (opens new window
),被那么多特性吓尿了,实际上写业务用的特性不多。
这里更多的是,以自己的理解去总结一下常用的ts
特性。总结一些项目中使用较多的,一些TS
高级特性·关注公众号
,后面会持续ts
系列的文章的
二、ts类型
本篇所有demo
都可在TypeScript Playground (opens new window)
运行,不理解的建议都来跑跑看。
1、基础类型
常用:
boolean、number、string、array、enum、any、void
不常用:
tuple、null、undefine、never
2、对象类型
“简单理解
”interface
和type
的区别:type
更强大,interface
可以进行声明合并,type
不行;
看个人习惯,一般声明都用interface
,需要用到其他变量类型,type
多一些。有没有interface
或type
一把梭的🤣?
interface Hero {
name: string;
age: number;
skill: string;
skinNum?: number;
say(): string; // say函数返回值为string
[propname: string]: any; // 当前Hero可定义任意字符串类型的key
}
// 继承
interface littleSoldier extends Hero {
rush(): string;
}
// 任意类型
interface IAnyObject {
[key: string]: any;
}
type Hero = {
name: string,
age: number,
skill: string,
skinNum?: number,
};
3、数组类型
项目中常见的写法,需要声明列表数据类型:
interface IItem {
id: number;
name: string;
isDad: boolean;
}
const objectArr: IItem[] = [
{ id: 1, name: '俊劫', isGod: true }
];
// or
const objectArr: Array<IItem> = [
{ id: 1, name: '俊劫', isGod: true }
];
const numberArr: number[] = [1, 2, 3];
const arr: (number | string)[] = [1, "string", 2];
4、元组 tuple
元组和数组类似,但是类型注解时会不一样
赋值的类型、位置、个数需要和定义(生明)的类型、位置、个数一致。
暂时没用过,感觉用处不大~~~
数组 某个位置的值可以是注解中的任何一个
const LOL: (string | number)[] = ["zed", 25, "darts"];
// 元祖 每一项数据类型必须一致
const LOL: [string, string, number] = ["zed", "darts", 25];
5、联合| or 交叉&类型
联合类型:某个变量可能是多个 interface 中的其中一个,用 | 分割 交叉类型:由多个类型组成,用 & 连接
// anjiao 某胖博主爱好
interface Waiter {
anjiao: boolean;
say: () => {};
}
interface Teacher {
anjiao: boolean;
skill: () => {};
}
// 联合类型
function judgeWho(animal: Waiter | Teacher) {}
// 交叉类型
// 同名类型会进行合并,同名基础类型属性的合并返回:never
// 同名非基础类型属性可以正常合并
function judgeWho(jishi: Waiter & Teacher) {}
6、enum枚举
提高代码可维护性,统一维护某些枚举值,避免 JiShi === 1
这种魔法数字。JiShi === JiShiEnum.BLUEJ
这样写,老板一眼就知道我想找谁。
// 初始值默认为 0
enum JiShiEnum {
REDJ,
BLUEJ,
GREENJ,
}
// 设置初始值
enum JiShiEnum {
REDJ = 8,
BLUEJ,
GREENJ,
}
const jishi: JiShiEnum = JiShiENUM.BLUE
console.log(jishi) // 9
// 字符串枚举,每个都需要声明
enum JiShiEnum {
REDJ = "8号",
BLUEJ = "9号",
GREENJ = "10号",
}
7、泛型 T(Type)
“简单说就是:泛指的类型,不确定的类型,可以理解为一个占位符(使用T只是习惯,使用任何字母都行)
”
K(Key):表示对象中的键类型; V(Value):表示对象中的值类型; E(Element):表示元素类型。
// T 自定义名称
function myFun<T>(params: T[]) {
return params;
}
myFun <string> ["123", "456"];
// 定义多个泛型
function join<T, P>(first: T, second: P) {
return `${first}${second}`;
}
join <number, string> (1, "2");
8、断言
主要通过 as
语法,告诉ts这个变量属于哪个类型,一般用在你比 TypeScript
更了解某个值的详细信息。
function judgeWho(animal: Waiter | Teacher) {
if (animal.anjiao) {
(animal as Teacher).skill();
}else{
(animal as Waiter).say();
}
}
9、in
类似于数组和字符串的 includes
方法
function judgeWhoTwo(animal: Waiter | Teacher) {
if ("skill" in animal) {
animal.skill();
} else {
animal.say();
}
}
10、类型注解
显式的告诉代码,我们的 count
变量就是一个数字类型,这就叫做类型注解
let count: number; // 类型注解
count = 123;
11、类型推断
如果 TS 能够自动分析变量类型, 我们就什么也不需要做了 如果 TS 无法分析变量类型的话, 我们就需要使用类型注解
// ts可以推断出count 为number类型
let count = 123;
12、void和never
返回值类型,也算是基础类型。没有返回值的函数: void
function sayHello(): void {
console.log("hello world");
}
如果一个函数是永远也执行不完的,就可以定义返回值为 never
function errorFuntion(): never {
throw new Error();
console.log("Hello World");
}
一个函数有入参,也有出参,项目中的常规写法:
// 定义一个小姐姐
interface IGirl {
name: string,
age: number,
skill: string,
isAnMo: boolean;
number: JiShiEnum;
};
// 定义搜索小姐姐的入参
interface ISearchParams extends IGirl{
serviceTime: string;
}
interface IGetGirls {
data: IGirl[];
}
// 函数主体
export function getGirls(data: ISearchParams): Promise<IGetGirls> {
return axios({
url: `/dabaojian/getGirls`,
method: 'GET',
data,
});
}
13、类型检测
1、typeof
typeof 操作符可以用来获取一个变量或对象的类型
interface Hero {
name: string;
skill: string;
}
const zed: Hero = { name: "影流之主", skill: "影子" };
type LOL = typeof zed; // type LOL = Hero
在上面代码中,我们通过 typeof
操作符获取 zed
变量的类型并赋值给 LOL
类型变量,之后我们就可以使用 LOL
类型
const ahri: LOL = { name: "阿狸", skill: "魅惑" };
2、instanceof
class NumberObj {
count: number;
}
function addObj(first: object | NumberObj, second: object | NumberObj) {
if (first instanceof NumberObj && second instanceof NumberObj) {
return first.count + second.count;
}
return 0;
}
3、keyof
keyof 与 Object.keys 略有相似,只不过 keyof 取 interface 的键
interface Point {
x: number;
y: number;
}
// type keys = "x" | "y"
type keys = keyof Point;
用 keyof 可以更好的定义数据类型
function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
return o[name]
}
14、ts类里的关键字
了解ts关键字的作用,在写base类的时候可能会用到,个人用的不多。
public private 类的外部不可用,继承也不行 protected 类的外部不可用,继承可以 public readOnly xxx 只读属性 static funcXXX 静态方法,不需要 new 就可以调用 abstract funcXXX 抽象类,所有子类都必须要实现 funcXXX
二、ts的优缺点
优点
“代码的可读性和可维护性:举个🌰看后端某个接口返回值,一般需要去network看or去看接口文档,才知道返回数据结构,而正确用了ts后,编辑器会提醒接口返回值的类型,这点相当实用。在编译阶段就发现大部分错误,避免了很多线上bug 增强了编辑器和 IDE 的功能,包括代码补全、接口提示、跳转到定义、重构等
”
三、anyScript
可能因为业务场景或者业务紧张,or某个跑路的大哥省了点功夫,用了typeScript
的项目也可能会变成anyScript
。以下是几种救急的方式:
// @ts-nocheck 禁用整个文件的ts校验
// @ts-ignore 禁用单行ts校验
any
和unknown
不建议多用,但也不是不能用,有些场景确实不好写ts定义。
原文地址
❤️ 看完三件事
非常棒的一篇Ts实用文章,
如果你觉得这篇内容对你挺有启发,不妨:
点个【在看】,或者分享转发,让更多的人也能看到这篇内容
点击↓面关注我们,一起学前端
长按↓面二维码,添加鬼哥微信,一起学前端