一篇夠用的TypeScript總結(jié)【實(shí)用】

一、前言
鬼哥今天給大家分享的這篇文章來(lái)自,有贊@俊劫大佬的一篇總結(jié)文章,在坐地鐵的時(shí)候,花個(gè)10分鐘碎片時(shí)間來(lái)學(xué)習(xí)下,還是非常有必要的,還是非常有收獲的一篇文章。
沒(méi)寫(xiě)ts之前看官方文檔 (opens new window),被那么多特性嚇尿了,實(shí)際上寫(xiě)業(yè)務(wù)用的特性不多。
這里更多的是,以自己的理解去總結(jié)一下常用的ts特性??偨Y(jié)一些項(xiàng)目中使用較多的,一些TS高級(jí)特性·關(guān)注公眾號(hào),后面會(huì)持續(xù)ts系列的文章的
二、ts類(lèi)型
本篇所有demo都可在TypeScript Playground (opens new window)運(yùn)行,不理解的建議都來(lái)跑跑看。
1、基礎(chǔ)類(lèi)型
常用:
boolean、number、string、array、enum、any、void
不常用:
tuple、null、undefine、never
2、對(duì)象類(lèi)型
“簡(jiǎn)單理解
”interface和type的區(qū)別:type更強(qiáng)大,interface可以進(jìn)行聲明合并,type不行;
看個(gè)人習(xí)慣,一般聲明都用interface,需要用到其他變量類(lèi)型,type多一些。有沒(méi)有interface或type一把梭的???
interface Hero {
name: string;
age: number;
skill: string;
skinNum?: number;
say(): string; // say函數(shù)返回值為string
[propname: string]: any; // 當(dāng)前Hero可定義任意字符串類(lèi)型的key
}
// 繼承
interface littleSoldier extends Hero {
rush(): string;
}
// 任意類(lèi)型
interface IAnyObject {
[key: string]: any;
}
type Hero = {
name: string,
age: number,
skill: string,
skinNum?: number,
};
3、數(shù)組類(lèi)型
項(xiàng)目中常見(jiàn)的寫(xiě)法,需要聲明列表數(shù)據(jù)類(lèi)型:
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
元組和數(shù)組類(lèi)似,但是類(lèi)型注解時(shí)會(huì)不一樣
賦值的類(lèi)型、位置、個(gè)數(shù)需要和定義(生明)的類(lèi)型、位置、個(gè)數(shù)一致。
暫時(shí)沒(méi)用過(guò),感覺(jué)用處不大~~~
數(shù)組 某個(gè)位置的值可以是注解中的任何一個(gè)
const LOL: (string | number)[] = ["zed", 25, "darts"];
// 元祖 每一項(xiàng)數(shù)據(jù)類(lèi)型必須一致
const LOL: [string, string, number] = ["zed", "darts", 25];
5、聯(lián)合| or 交叉&類(lèi)型
聯(lián)合類(lèi)型:某個(gè)變量可能是多個(gè) interface 中的其中一個(gè),用 | 分割 交叉類(lèi)型:由多個(gè)類(lèi)型組成,用 & 連接
// anjiao 某胖博主愛(ài)好
interface Waiter {
anjiao: boolean;
say: () => {};
}
interface Teacher {
anjiao: boolean;
skill: () => {};
}
// 聯(lián)合類(lèi)型
function judgeWho(animal: Waiter | Teacher) {}
// 交叉類(lèi)型
// 同名類(lèi)型會(huì)進(jìn)行合并,同名基礎(chǔ)類(lèi)型屬性的合并返回:never
// 同名非基礎(chǔ)類(lèi)型屬性可以正常合并
function judgeWho(jishi: Waiter & Teacher) {}
6、enum枚舉
提高代碼可維護(hù)性,統(tǒng)一維護(hù)某些枚舉值,避免 JiShi === 1這種魔法數(shù)字。JiShi === JiShiEnum.BLUEJ這樣寫(xiě),老板一眼就知道我想找誰(shuí)。
// 初始值默認(rèn)為 0
enum JiShiEnum {
REDJ,
BLUEJ,
GREENJ,
}
// 設(shè)置初始值
enum JiShiEnum {
REDJ = 8,
BLUEJ,
GREENJ,
}
const jishi: JiShiEnum = JiShiENUM.BLUE
console.log(jishi) // 9
// 字符串枚舉,每個(gè)都需要聲明
enum JiShiEnum {
REDJ = "8號(hào)",
BLUEJ = "9號(hào)",
GREENJ = "10號(hào)",
}
7、泛型 T(Type)
“簡(jiǎn)單說(shuō)就是:泛指的類(lèi)型,不確定的類(lèi)型,可以理解為一個(gè)占位符(使用T只是習(xí)慣,使用任何字母都行)
”
K(Key):表示對(duì)象中的鍵類(lèi)型; V(Value):表示對(duì)象中的值類(lèi)型; E(Element):表示元素類(lèi)型。
// T 自定義名稱(chēng)
function myFun<T>(params: T[]) {
return params;
}
myFun <string> ["123", "456"];
// 定義多個(gè)泛型
function join<T, P>(first: T, second: P) {
return `${first}${second}`;
}
join <number, string> (1, "2");
8、斷言
主要通過(guò) as 語(yǔ)法,告訴ts這個(gè)變量屬于哪個(gè)類(lèi)型,一般用在你比 TypeScript 更了解某個(gè)值的詳細(xì)信息。
function judgeWho(animal: Waiter | Teacher) {
if (animal.anjiao) {
(animal as Teacher).skill();
}else{
(animal as Waiter).say();
}
}
9、in
類(lèi)似于數(shù)組和字符串的 includes 方法
function judgeWhoTwo(animal: Waiter | Teacher) {
if ("skill" in animal) {
animal.skill();
} else {
animal.say();
}
}
10、類(lèi)型注解
顯式的告訴代碼,我們的 count 變量就是一個(gè)數(shù)字類(lèi)型,這就叫做類(lèi)型注解
let count: number; // 類(lèi)型注解
count = 123;
11、類(lèi)型推斷
如果 TS 能夠自動(dòng)分析變量類(lèi)型, 我們就什么也不需要做了 如果 TS 無(wú)法分析變量類(lèi)型的話, 我們就需要使用類(lèi)型注解
// ts可以推斷出count 為number類(lèi)型
let count = 123;
12、void和never
返回值類(lèi)型,也算是基礎(chǔ)類(lèi)型。沒(méi)有返回值的函數(shù): void
function sayHello(): void {
console.log("hello world");
}
如果一個(gè)函數(shù)是永遠(yuǎn)也執(zhí)行不完的,就可以定義返回值為 never
function errorFuntion(): never {
throw new Error();
console.log("Hello World");
}
一個(gè)函數(shù)有入?yún)ⅲ灿谐鰠?,?xiàng)目中的常規(guī)寫(xiě)法:
// 定義一個(gè)小姐姐
interface IGirl {
name: string,
age: number,
skill: string,
isAnMo: boolean;
number: JiShiEnum;
};
// 定義搜索小姐姐的入?yún)?/span>
interface ISearchParams extends IGirl{
serviceTime: string;
}
interface IGetGirls {
data: IGirl[];
}
// 函數(shù)主體
export function getGirls(data: ISearchParams): Promise<IGetGirls> {
return axios({
url: `/dabaojian/getGirls`,
method: 'GET',
data,
});
}
13、類(lèi)型檢測(cè)
1、typeof
typeof 操作符可以用來(lái)獲取一個(gè)變量或?qū)ο蟮念?lèi)型
interface Hero {
name: string;
skill: string;
}
const zed: Hero = { name: "影流之主", skill: "影子" };
type LOL = typeof zed; // type LOL = Hero
在上面代碼中,我們通過(guò) typeof 操作符獲取 zed 變量的類(lèi)型并賦值給 LOL 類(lèi)型變量,之后我們就可以使用 LOL 類(lèi)型
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 略有相似,只不過(guò) keyof 取 interface 的鍵
interface Point {
x: number;
y: number;
}
// type keys = "x" | "y"
type keys = keyof Point;
用 keyof 可以更好的定義數(shù)據(jù)類(lèi)型
function get<T extends object, K extends keyof T>(o: T, name: K): T[K] {
return o[name]
}
14、ts類(lèi)里的關(guān)鍵字
了解ts關(guān)鍵字的作用,在寫(xiě)base類(lèi)的時(shí)候可能會(huì)用到,個(gè)人用的不多。
public private 類(lèi)的外部不可用,繼承也不行 protected 類(lèi)的外部不可用,繼承可以 public readOnly xxx 只讀屬性 static funcXXX 靜態(tài)方法,不需要 new 就可以調(diào)用 abstract funcXXX 抽象類(lèi),所有子類(lèi)都必須要實(shí)現(xiàn) funcXXX
二、ts的優(yōu)缺點(diǎn)
優(yōu)點(diǎn)
“代碼的可讀性和可維護(hù)性:舉個(gè)??看后端某個(gè)接口返回值,一般需要去network看or去看接口文檔,才知道返回?cái)?shù)據(jù)結(jié)構(gòu),而正確用了ts后,編輯器會(huì)提醒接口返回值的類(lèi)型,這點(diǎn)相當(dāng)實(shí)用。在編譯階段就發(fā)現(xiàn)大部分錯(cuò)誤,避免了很多線上bug 增強(qiáng)了編輯器和 IDE 的功能,包括代碼補(bǔ)全、接口提示、跳轉(zhuǎn)到定義、重構(gòu)等
”
三、anyScript
可能因?yàn)闃I(yè)務(wù)場(chǎng)景或者業(yè)務(wù)緊張,or某個(gè)跑路的大哥省了點(diǎn)功夫,用了typeScript的項(xiàng)目也可能會(huì)變成anyScript。以下是幾種救急的方式:
// @ts-nocheck 禁用整個(gè)文件的ts校驗(yàn)
// @ts-ignore 禁用單行ts校驗(yàn)
any和unknown 不建議多用,但也不是不能用,有些場(chǎng)景確實(shí)不好寫(xiě)ts定義。
原文地址
?? 看完三件事
非常棒的一篇Ts實(shí)用文章,
如果你覺(jué)得這篇內(nèi)容對(duì)你挺有啟發(fā),不妨:
點(diǎn)個(gè)【在看】,或者分享轉(zhuǎn)發(fā),讓更多的人也能看到這篇內(nèi)容
點(diǎn)擊↓面關(guān)注我們,一起學(xué)前端
長(zhǎng)按↓面二維碼,添加鬼哥微信,一起學(xué)前端
