typeScript學(xué)習(xí)心得一

TypeScript的核心原則之一是對值所具有的結(jié)構(gòu)進(jìn)行類型檢查

泛型

泛型是指一個表示類型的變量溯祸,一般用T表示,用它來代替某個實(shí)際的類型本姥,而后通過實(shí)際調(diào)用時傳入的類型來對其進(jìn)行替換肩袍,可以利用泛型來適應(yīng)不同類型。
TypeScript 中不建議使用 any 類型婚惫,不能保證類型安全氛赐,調(diào)試時缺乏完整的信息。
TypeScript可以使用泛型來創(chuàng)建可重用的組件先舷。支持當(dāng)前數(shù)據(jù)類型艰管,同時也能支持未來的數(shù)據(jù)類型。擴(kuò)展靈活蒋川∩螅可以在編譯時發(fā)現(xiàn)你的類型錯誤,從而保證類型安全尔破。
1:泛型函數(shù)

<泛型變量名稱>(參數(shù)1: 泛型變量, 參數(shù)2: 泛型變量, ...參數(shù)n: 泛型變量) => 泛型變量
 /*------------基礎(chǔ)使用方法------------*/
  function join<T, P>(first: T, second: P): T {
    return first;
  }
  //const twoParms = join<number, string>(1, '我是string');
  const twoParms = join(1, '我是string');

  /*---------泛型集合--------------*/
  function map<T>(params: Array<T>) {
    return params;
  }
  //const sanleType = map<string>(['123']);
  const sanleType = map(['123']);

  /* -----------泛型箭頭函數(shù)-------------*/
  const identity = <T,>(arg: T): T => {
    return arg;
  };
  const identity2: <T>(arg: T) => T = (arg) => {
    return arg;
  };

2:泛型接口

 /* -------------泛型接口-------------*/
 interface ColumnProps<T> {
  key: number | string;
  title: string;
  dataIndex: keyof T; // 約束 dataIndex 值需為引用泛型 T 中的屬性
}
interface ITableItem {
  key: number | string;
  name: string;
  address: string;
  age: number;
}
const columns: Array<ColumnProps<ITableItem>> = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
    },
  ];

3:泛型類

 /*--------------泛型類---------------*/
  class Person<T> {
    love: T;
    say: (arg: T) => T;
  }
  let myFn: IGeneric<number> = fn;
  myFn(13); //13
 
  let me = new Person<string>();
  me.love = 'TS';
  // me.love = 520; // ERROR
  me.say = function(love: string){
    return `my love is ${love}`;
  }
泛型約束

泛型可以通過 extends 一個接口來實(shí)現(xiàn)泛型約束街图,寫法如:

<泛型變量 extends 接口>
<T, K extends keyof T>
//K為傳入的T上已知的屬性,

interface IArray {
  length: number
}
function logIndex<T extends IArray>(arg: T): void {
  for (let i = 0; i < arg.length; ++i) {
    console.log(i)
  }
}
let arr = [1, 2, 3]
// logIndex<number>(arr) // 報(bào)錯
logIndex<number[]>(arr) // 允許
logIndex(arr) // 自動類型推導(dǎo)懒构,允許
泛型應(yīng)用場景之一
/*-------------應(yīng)用場景start---------------------------*/
interface ColumnProps<T> {
  key: number | string;
  title: string;
  dataIndex: keyof T; // 約束 dataIndex 值需為引用泛型 T 中的屬性
}
interface ITableItem {
  key: number | string;
  name: string;
  address: string;
  age: number;
}
interface TableProps {
  dataSource: ITableItem[];
  columns: Array<ColumnProps<ITableItem>>;
}
const MyTable = (props: TableProps) => {
  const { dataSource, columns } = props;
  return <Table dataSource={dataSource} columns={columns} />;
};
const ApplcationMod = () => {
  const dataSource = [
    {
      key: '1',
      name: '金城武',
      age: 32,
      address: '西湖區(qū)湖底公園1號',
    },
    {
      key: '2',
      name: '吳彥祖',
      age: 42,
      address: '西湖區(qū)湖底公園1號',
    },
  ];

  const columns: Array<ColumnProps<ITableItem>> = [
    {
      title: '姓名',
      dataIndex: 'name',
      key: 'name',
    },
    {
      title: '年齡',
      dataIndex: 'age',
      key: 'age',
    },
    {
      title: '住址',
      dataIndex: 'address',
      key: 'address',
    },
  ];

  return (
    <div>
      <h3>泛型應(yīng)用場景</h3>
      <MyTable dataSource={dataSource} columns={columns} />
    </div>
  );
};

keyof 關(guān)鍵字

keyof 關(guān)鍵字非常實(shí)用,后面可以看到很多工具泛型都是使用 keyof 實(shí)現(xiàn)的耘擂。
keyof T(索引類型查詢)的結(jié)果為 T上已知的公共屬性名的聯(lián)合胆剧。
keyof 的一個特性: keyof T的類型會被認(rèn)為是 string、number醉冤、symbol 的子類型秩霍。

interface Point {
    x: number;
    y: number;
}

type Axis = keyof Point;
// 等同于 type Axis = "x" | "y"
function cal(a: Point, b: Point, axis: Axis): number {
  return (a[axis] + b[axis]) / 2;
}
cal({x:20,y:99},{x:100,y:200},'x')

type類型別名

1.可以創(chuàng)建聯(lián)合類型、元組類型蚁阳、基本類型(string,number,symbol)

  //聯(lián)合類型
   type Pets = 'hi' | 'age' | 'hello';
  interface Dog {
    x:string
  }
  interface Cat {
    y:number
  }
  type Pet = Dog | Cat
  //元組+泛型
  //與 聲明數(shù)組類型 類似铃绒,只不過在 數(shù)組 基礎(chǔ)上更加細(xì)分化每個元素的類型。
  type Pair<T> = [T, T]; 
  const ff: Pair<number> = [1, 2];
  const cc: Pair<number> = [1, 1];
  const dd: Pair<string> = ['1', '2'];

2.可以利用type和映射類型快速創(chuàng)建類型

 { [ K in P ] : T }

實(shí)例

type Coord = {
    [K in 'x' | 'y']: number;
};
// 得到
// type Coord = {
//  x: number;
//  y: number;
// }
它執(zhí)行了一個循環(huán)(可以理解為類似 for...in 的效果)螺捐,這里的 P 直接設(shè)置為 'x' | 'y' 的一個聯(lián)合類型颠悬,而 K 是一個標(biāo)識符矮燎,它映射為 P 的每一個子類型。T 為數(shù)據(jù)類型赔癌,我們直接固定為 number诞外,也可以是任何其他復(fù)雜類型。

//約束key,value為同樣的值灾票;
type Coord = { [K in 'x' | 'y']: K };
// 得到 type Coord = { x: 'x'; y: 'y'; }

3:生成類型的函數(shù)類型
可以封裝一個快速生成接口類型的函數(shù)類型:

  type Unite = 'dog' | 'cat' | 'pig';
  type PetInfo = {
    name: string;
    age: number;
  };
  type Coord4 = {
    [K in Unite]: PetInfo;
  };
  const animalInfo: Coord4 = {
    dog: { name: 'dogname', age: 3 },
    cat: { name: 'catname', age: 3 },
    pig: { name: 'pigname', age: 3 },
  };
//等同于
  type Creat<K extends keyof any, U> = {
    [P in keyof K]: U;
  };
//預(yù)置的高級類型 Record<K extends keyof any, T> 峡谊,可以直接使用
  type Pets = Creat<Unite,PetInfo>
  const animalInfo2: Pets = {
    dog: { name: 'dogname2', age: 3 },
    cat: { name: 'catname2', age: 3 },
    pig: { name: 'pigname2', age: 3 },
  };

interface 與 type

相同點(diǎn)
/*都可以描述一個對象或者函數(shù)*/
interface User {
  name: string
  age: number
}
interface SetUser {
  (name: string, age: number): void;
}
type User = {
  name: string
  age: number
};

type SetUser = (name: string, age: number)=> void;
*都允許拓展(extends)*/
interface Name { 
  name: string; 
}
interface User extends Name { 
  age: number; 
}
type Name = { 
  name: string; 
}
type User = Name & { age: number  };
//interface extends type
type Name = { 
  name: string; 
}
interface User extends Name { 
  age: number; 
}
//type extends interface
interface Name { 
  name: string; 
}
type User = Name & { 
  age: number; 
}
不同點(diǎn)

type 可以聲明基本類型別名,聯(lián)合類型刊苍,元組等類型
nterface 能夠聲明合并

interface User {
  name: string
  age: number
}

interface User {
  sex: string
}
/*
User 接口為 {
  name: string
  age: number
  sex: string 
}
*/

不清楚什么時候用interface/type既们,能用 interface 實(shí)現(xiàn),就用 interface , 如果不能就用 type 正什。

Partial

Partial 將傳入的所有屬性變?yōu)榭蛇x

// 映射類型進(jìn)行推斷
type Partial<T> = {
  [P in keyof T]?: T[P];
};
interface Article {
  articleId: string;
  title: string;
  content: string;
  status: number;
}
//等同于
// interface Article1 {
//   articleId?: string;
//   title?: string;
//   content?: string;
//   status?: number;
// }
const Index = (props: Partial<Article>) => {
  //to do..........
};

Required(用處不大)

將傳入的所有屬性變?yōu)楸剡x項(xiàng)贤壁,這個和 Partial 相反


image.png
type Required<T> = { [P in keyof T]-?: T[P] };
interface Article {
  articleId: string;
  title: string;
  content: string;
  status: number;
}
const Index = (props: Required<Article>) => {
  //to do..........
};

Exclude

Exclude<T, U> -- 從T中剔除可以賦值給U的類型,起到過濾的作用

//官方例子
type T00 = Exclude<"a" | "b" | "c" | "d", "a" | "c" | "f">;  // "b" | "d"
需求:工作日時間可調(diào)整。
type Exclude<T, U> = T extends U ? never : T;
//平常日剔除休息日就是工作日
// 一周(平常日)
type Weekday = 'Monday' | 'Tuesday' | 'Wednesday' | 'Thursday' | 'Friday' | 'Saturday' | 'Sunday';
// 休息日
type DayOff = 'Saturday' | 'Sunday'|'Monday';
// 工作日
type WorkDay = Exclude<Weekday, DayOff>; 

const day: WorkDay = 'Tuesday';

TypeScript 的映射類型

簡單語法

{ [ K in P ] : T }
type Coord = {
    [K in 'x' | 'y']: T;
};
// 得到
// type Coord = {
//  x: T;
//  y: T;
// }
首選確定它執(zhí)行了一個循環(huán)(可以理解為類似 for...in 的效果)埠忘,這里的 P 直接設(shè)置為 'x' | 'y' 的一個聯(lián)合類型脾拆,而 K 是一個標(biāo)識符,它映射為 P 的每一個子類型莹妒。T 為數(shù)據(jù)類型名船,我們直接固定為 number,也可以是任何其他復(fù)雜類型旨怠。
因?yàn)?T 值數(shù)據(jù)類型可以是任何值渠驼,甚至數(shù)值 1 也可以,因此我們把數(shù)據(jù)類設(shè)成 K 自身也行:

type Coord = { [K in 'x' | 'y']: K };
// 得到 
type Coord = { x: 'x'; y: 'y'; }

立用映射類型+keyOf關(guān)鍵字 封裝一個快速生成接口類型的函數(shù)類型Record

//封裝一個快速生成接口類型的函數(shù)類型
type Record<K extends keyof any, T> = {
    [P in K]: T;
};
//K extends keyof any
等價于
//type K = 'dog' | 'cat' | 'fish'鉴腻;

type PetType = 'dog' | 'cat' | 'fish';

interface PetInfo {
  name: string;
  age: number;
}

type Pets = Record<PetType, PetInfo>;

const pets: Pets = {
  dog: { name: 'didi', age: 1 },
  cat: { name: 'cici', age: 2 },
  fish: { name: 'fifi', age: 3 }
};
or
interface Pets {
  dog: PetInfo;
  cat: PetInfo;
  fish: PetInfo;
}

額外的屬性檢查

需求:代碼遷移復(fù)用迷扇,希望原先的 js 代碼能夠遷移到 ts 中,增加類型推斷

1.使用 as 關(guān)鍵字爽哎,斷言類型蜓席,

as 語法,大部分其他場景應(yīng)該避免使用课锌,類型斷言純粹是編譯時語法厨内。類型推斷應(yīng)該盡量使用 interface / type / 基礎(chǔ)類型

//const asFoo = {};//報(bào)錯寫法
//const asFoo = {} as Foo;
const asFoo: { [propName: string]: any } = {};//推薦字符串索引用法
asFoo.bar = 2;//error類型“{}”上不存在屬性“bar”。
asFoo.title = 'as 類型斷言';//error類型“{}”上不存在屬性“bas”渺贤。

interface Foo {
  bar: number;
  title: string;
  [propName: string]: any;//可解決報(bào)錯
}
image.png

類型保護(hù)

聯(lián)合類型時雏胃,會遇到這種問題。無法準(zhǔn)確知道是否存在某個屬性志鞍。


image.png
類型注解&類型推段

TS能夠自動的分析變量類型時瞭亮,就什么都不需要做了
TS無法分析出變量類型時,就需要使用類型注解固棚。
定義基礎(chǔ)類型可不用寫類型注解


image.png
//let count:number = 1;
let count = 1;//不需要寫類型注解统翩;
const fistCount = 1;
const secondCount = 2;
const total = fistCount + secondCount;//不需要加類型注解仙蚜,ts可直接推斷出total為number類型

//返回值類型不寫也不會報(bào)錯,但是實(shí)戰(zhàn)中一般還是要做一層約束唆缴。
function getTotal(fistCount:number,secondCount:number):number{
  return fistCount + secondCount;
}
const total = getTotal(1,2);//不需要加類型注解,ts分析出是number類型
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鳍征,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子面徽,更是在濱河造成了極大的恐慌艳丛,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,029評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趟紊,死亡現(xiàn)場離奇詭異氮双,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)霎匈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評論 3 385
  • 文/潘曉璐 我一進(jìn)店門戴差,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人铛嘱,你說我怎么就攤上這事暖释。” “怎么了墨吓?”我有些...
    開封第一講書人閱讀 157,570評論 0 348
  • 文/不壞的土叔 我叫張陵球匕,是天一觀的道長。 經(jīng)常有香客問我帖烘,道長亮曹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,535評論 1 284
  • 正文 為了忘掉前任秘症,我火速辦了婚禮照卦,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘乡摹。我一直安慰自己役耕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評論 6 386
  • 文/花漫 我一把揭開白布趟卸。 她就那樣靜靜地躺著蹄葱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪锄列。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,850評論 1 290
  • 那天惯悠,我揣著相機(jī)與錄音邻邮,去河邊找鬼。 笑死克婶,一個胖子當(dāng)著我的面吹牛筒严,可吹牛的內(nèi)容都是我干的丹泉。 我是一名探鬼主播,決...
    沈念sama閱讀 39,006評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼鸭蛙,長吁一口氣:“原來是場噩夢啊……” “哼摹恨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起娶视,我...
    開封第一講書人閱讀 37,747評論 0 268
  • 序言:老撾萬榮一對情侶失蹤匿又,失蹤者是張志新(化名)和其女友劉穎训柴,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸟妙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了锣咒。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片几迄。...
    茶點(diǎn)故事閱讀 38,683評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖青柄,靈堂內(nèi)的尸體忽然破棺而出伐债,到底是詐尸還是另有隱情,我是刑警寧澤致开,帶...
    沈念sama閱讀 34,342評論 4 330
  • 正文 年R本政府宣布峰锁,位于F島的核電站,受9級特大地震影響喇喉,放射性物質(zhì)發(fā)生泄漏祖今。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評論 3 315
  • 文/蒙蒙 一拣技、第九天 我趴在偏房一處隱蔽的房頂上張望千诬。 院中可真熱鬧,春花似錦膏斤、人聲如沸徐绑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽傲茄。三九已至,卻和暖如春沮榜,著一層夾襖步出監(jiān)牢的瞬間盘榨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評論 1 266
  • 我被黑心中介騙來泰國打工蟆融, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留草巡,地道東北人。 一個月前我還...
    沈念sama閱讀 46,401評論 2 360
  • 正文 我出身青樓型酥,卻偏偏與公主長得像山憨,于是被迫代替她去往敵國和親查乒。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評論 2 349

推薦閱讀更多精彩內(nèi)容