TypeScript接口的使用(七)

1. 接口的聲明

在前面我們通過type可以用來聲明一個對象類型:

type Point = {
  x: number
  y: number
}

對象的另外一種聲明方式就是通過接口來聲明:

interface Point = {
  x: number
  y: number
}

接口類型也可以定義可選類型和只讀屬性棕叫,只讀屬性指我們再初始化之后,這個值是不可以被修改的

// 通過類型(type)別名來聲明對象類型
// type InfoType = {name: string, age: number}

// 另外一種方式聲明對象類型: 接口interface
// 在其中可以定義可選類型
// 也可以定義只讀屬性
interface IInfoType {
  readonly name: string
  age: number
  friend?: {
    name: string
  }
}

const info: IInfoType = {
  name: "why",
  age: 18,
  friend: {
    name: "kobe"
  }
}

console.log(info.friend?.name)
console.log(info.name)
// info.name = "123"
info.age = 20


2. 索引類型

// 通過interface來定義索引類型
interface IndexLanguage {
  [index: number]: string
}

const frontLanguage: IndexLanguage = {
  0: "HTML",
  1: "CSS",
  2: "JavaScript",
  3: "Vue"
}


interface ILanguageYear {
  [name: string]: number
}

const languageYear: ILanguageYear = {
  "C": 1972,
  "Java": 1995,
  "JavaScript": 1996,
  "TypeScript": 2014
}


3. 函數(shù)類型

前面我們都是通過interface來定義對象中普通的屬性和方法的奕删,實際上它也可以用來定義函數(shù)類型:
用接口定義函數(shù)類型


image.png
// type CalcFn = (n1: number, n2: number) => number
// 可調用的接口
interface CalcFn {
  (n1: number, n2: number): number
}

function calc(num1: number, num2: number, calcFn: CalcFn) {
  return calcFn(num1, num2)
}

const add: CalcFn = (num1, num2) => {
  return num1 + num2
}

calc(20, 30, add)


4. 接口繼承

接口和類一樣是可以進行繼承的俺泣,也是使用extends關鍵字:
并且我們會發(fā)現(xiàn),接口是支持多繼承的(類不支持多繼承)

interface ISwim {
  swimming: () => void;
}

interface IFly {
  flying: () => void;
}

interface IAction extends ISwim, IFly {}
//支持多繼承

const action: IAction = {
  swimming() {},
  flying() {},
  //里面必須有這兩個方法
};

image.png

5.交叉類型

image.png

6.交叉類型的應用

image.png
// 一種組合類型的方式: 聯(lián)合類型
type WhyType = number | string;
type Direction = "left" | "right" | "center";
/* ,聯(lián)合類型的話是把我們多個這個值伏钠,
多個我們的類型横漏,多個類型跟他聯(lián)合在一起,到時候的話熟掂,你取里面的任何缎浇,一個類型都可以 */

// 另一種組件類型的方式: 交叉類型
type WType = number & string;

interface ISwim {
  swimming: () => void;
}

interface IFly {
  flying: () => void;
}

type MyType1 = ISwim | IFly;
type MyType2 = ISwim & IFly;

const obj1: MyType1 = {
  flying() {},
};

const obj2: MyType2 = {
  swimming() {},
  flying() {},
};

export {};

兩個接口他們的組合的時候就有兩種方式了,第一種方式的話是定義一個新的接口打掘,然后讓他們繼承自我原來的這兩個接口华畏,那么這個接口里面就相當于把前面這兩個就給他組合在一起了,另外一種方式尊蚁,交叉類型,他也是可以把我們兩個對象類型侣夷,兩個對象類型跟他結合在一起横朋,結合在一起之后的話,生成一個新的類型.

7.接口的實現(xiàn)

1.接口作為標識符的使用

interface Iswim {
  swimming: () => void;
}

interface IEat {
  eating: () => void;
}

//這兩個接口可以作為類型百拓,比如在定義變量的時候
const a: Iswim = {
  swimming() {},
}; //接口作為標識符類型

function foo(swim: Iswim) {
  //傳入的這個對象必須滿足這個接口
}
foo({ swimming() {} });
  1. 類可以作為接口
interface Iswim {
  swimming: () => void;
}

interface IEat {
  eating: () => void;
}
// 類實現(xiàn)接口
class Animal {}

//類Fish除了可以繼承Animal琴锭,也可以實現(xiàn)接口
//但是繼承的化只能實現(xiàn)單繼承
class Fish extends Animal implements ISwim, IEat {
  swimming() {
    console.log("Fish Swmming");
  }

  eating() {
    console.log("Fish Eating");
  }
  //因為實現(xiàn)了兩個接口所以里面必須有swiming和eating
  /* 
  使用類實現(xiàn)接口的化,編寫一一些公共的公共的API的話衙传,在很多的情況下都可以調用的决帖,對于可復用的一些API的時候,它就變得更加的靈活蓖捶。那么我們就可以面向接口進行編程地回。
  */
}

//// 編寫一些公共的API: 面向接口編程
//function swimAction(swimable: Fish {
//  swimable.swimming();
//}
swimAction(new Fish());
//這么寫的話,這個函數(shù)就不具備通用性俊鱼,因為這個參數(shù)我們就只能傳Fish類型的一個對象刻像。
//如果我們想swimAction({swimming: function() {}})是不可以的。只能new一個Fish對象

//這個時候我們就可以面向接口編程
function swimAction(swimable: ISwim) {
  swimable.swimming()
}
// 1.所有實現(xiàn)了接口的類對應的對象, 都是可以傳入
swimAction(new Fish())
//如果Person也實現(xiàn)了 ISwim
class Person implements ISwim {
  swimming() {
    console.log("Person Swimming")
  }
}
swimAction(new Person())
swimAction({swimming: function() {}})
/* 就意味著只要是有一個類并闲,它實現(xiàn)了這個接口细睡,到時候的話,它都是可以調動我公共的這個API的帝火,那么我在編輯這個公共API的時候溜徙,我這里最好就是面向接口編程的 
面向接口編程的話,就讓我編寫的這個API他更加具備通用性啦犀填,在很多很多地方都可以被別人調用蠢壹,只要你實現(xiàn)了我的這個接口,甚至是我們普通的對象字面量宏浩,你只要也是符合我接口對應的類型的知残,你也是可以傳到我們這個里面去的,可以轉到這個里面去,所以這個的話就叫做面向接口編程
*/

export {};

8.interface和type區(qū)別

image.png
interface IFoo {
  name: string;
}
interface IFoo {
  age: number;
}
/* interface允許定義兩個名字相同的接口,意味著會把兩個接口的內容合并在一起求妹,相當于
interface Ifoo {
  ame: string
  age: number
}
 */
const foo: IFoo = {
  name: "why",
  age: 18,
};

export {};
// document.getElementById("app") as HTMLDivElement
/* 
剛才我們看到的Windows類型乏盐,包括document這些類型它來自哪里呢,這些類型來自于我們在安裝typescript的時候制恍,它會默認幫助我們安裝一些lib的庫父能,
那安裝的這些庫里面,它就默認有幫助我們定義很多的類型净神,
包括比如說這個javascript里面內置的一些類型項何吝,Math,Data這些類型鹃唯,包括這些內置類型爱榕,
也包括dom的一些類型的API的話,
Winodw類型坡慌,HTMLDivElement類型等
06:01
*/
//window這個類型沒有age這個屬性黔酥,我們如果想有age這個屬性的化
interface Window {
  age: number;
}
//這時候不能覆蓋以前的Window,而是合并
window.age = 19;
console.log(window.age);

//type根本不允許定義兩個相同的類型
// type IBar = {
//   name: string
//   age: number
// }

// type IBar = {
// }



9.字面量賦值

interface IPerson {
  name: string;
  age: number;
  height: number;
}

const info: IPerson = {
  name: "why",
  age: 18,
  height: 1.88,
  //address: "廣州市", //不能添加這個屬性洪橘,因為IPerson沒有定義
};


怎么讓他不報錯呢

interface IPerson {
  name: string;
  age: number;
  height: number;
}

const info = {
  name: "why",
  age: 18,
  height: 1.88,
  address: "廣州市",
}; //info會做類型推導摔敛,推導出來
/*  
const info: {
    name: string;
    age: number;
    height: number;
    address: string;
}

*/

const p: IPerson = info;
/* 
這個時候把info類型和IPerson類型是沖突的关划,因為多了個address
ts主要做類型檢測儡首,類型檢測通過蔑鹦,你這個代碼就沒有問題
fressness擦除
當把info這個引用類型賦值給p的時候,他會把我們對應某一個屬性給它擦除掉弟晚,擦出掉之后忘衍,也就是address,如果依然是滿足你這里的這個類型的情況下指巡,也就是 IPerson 淑履,因為我們這三個是不是依然是滿足的,依然是滿足的情況下藻雪,就是可以賦值的秘噪。如果info里面沒有age,你再把這個address擦掉之后勉耀,你是少一個的指煎,少一個是不行的,同學們就是擦除掉那些多余的便斥,擦掉那些多余的之后至壤,
我依然是符合你這類型的,他是允許我們這么賦值的枢纠,它允許這么賦值
*/

console.log(info);
console.log(p);
/* { name: 'why', age: 18, height: 1.88, address: '廣州市' }
{ name: 'why', age: 18, height: 1.88, address: '廣州市' } */
export {};


這是因為TypeScript在字面量直接賦值的過程中像街,為了進行類型推導會進行嚴格的類型限制。
但是之后如果我們是將一個 變量標識符 賦值給其他的變量時,會進行freshness擦除操作镰绎。

應用

interface IPerson {
  name: string;
  age: number;
  height: number;
}

function printInfo(person: IPerson) {
  console.log(person);
  // console.log(person.address);不可以使用address脓斩,因為對于類型檢測來說,畴栖,人家認為你這個person里面只有三個屬性随静,,在這里取address的時候吗讶,在類型檢測這一步他是過不去的燎猛,但是可以直接打印所有
}

// 代碼會報錯
// printInfo({
//   name: "why",
//   age: 18,
//   height: 1.88,
//   address: "廣州市"
// })

const info = {
  name: "why",
  age: 18,
  height: 1.88,
  address: "廣州市",
};

printInfo(info);
//{ name: 'why', age: 18, height: 1.88, address: '廣州市' }
export {};

10.TypeScript枚舉類型

image.png
//,其實枚舉類型就是定義一組常量照皆,并且給他放到我們對應的一種數(shù)據(jù)類型里面
// type Direction = "left" | "Right" | "Top" | "Bottom"

enum Direction {
  LEFT,
  RIGHT,
  TOP,
  BOTTOM,
} //代碼閱讀性強
/* 
看起來這些東西是我們的一些標識的一些常量重绷,但是其實本質上他們是一些數(shù)字常量,也就第一個的話其實是一個零膜毁,然后第二個的話是一個一论寨,第三個的話是一個二,然后第四個的話就是一個三爽茴,它內部是由我們這里這么一些數(shù)字的值的,只不過這些值你不需要去寫绰垂,你不寫的時候室奏,他們默認也是有的,但是能改變這里這些東西的值
enum Direction {
  LEFT = 0,
  RIGH = 1,
  TOP = 2,
  BOTTOM = 3,
} 默認

enum Direction {
  LEFT = 100,
  RIGH = 200,
  TOP = 300,
  BOTTOM = 400,
}
enum Direction {
  LEFT = 100,
  RIGH ,//101
  TOP ,//102
  BOTTOM,//103
}
*/
function turnDirection(direction: Direction) {
  console.log(direction);
  switch (direction) {
    case Direction.LEFT:
      console.log("改變角色的方向向左");
      break;
    case Direction.RIGHT:
      console.log("改變角色的方向向右");
      break;
    case Direction.TOP:
      console.log("改變角色的方向向上");
      break;
    case Direction.BOTTOM:
      console.log("改變角色的方向向下");
      break; //如果少些一個case的化,代碼會報錯劲装。因為default用了never類型
    default:
      const foo: never = direction;
      break;
  }
}

turnDirection(Direction.LEFT);
turnDirection(Direction.RIGHT);
turnDirection(Direction.TOP);
turnDirection(Direction.BOTTOM);

export {};
/* 
0
改變角色的方向向左
1
改變角色的方向向右
2
改變角色的方向向上
3
改變角色的方向向下
*/

11.枚舉類型的值

image.png
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末胧沫,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子占业,更是在濱河造成了極大的恐慌绒怨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件谦疾,死亡現(xiàn)場離奇詭異南蹂,居然都是意外死亡,警方通過查閱死者的電腦和手機念恍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門六剥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峰伙,你說我怎么就攤上這事疗疟。” “怎么了瞳氓?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵策彤,是天一觀的道長。 經(jīng)常有香客問我,道長店诗,這世上最難降的妖魔是什么裹刮? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮必搞,結果婚禮上必指,老公的妹妹穿的比我還像新娘。我一直安慰自己恕洲,他們只是感情好塔橡,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著霜第,像睡著了一般葛家。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上泌类,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天癞谒,我揣著相機與錄音,去河邊找鬼刃榨。 笑死弹砚,一個胖子當著我的面吹牛,可吹牛的內容都是我干的枢希。 我是一名探鬼主播桌吃,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼苞轿!你這毒婦竟也來了茅诱?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤搬卒,失蹤者是張志新(化名)和其女友劉穎瑟俭,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體契邀,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡摆寄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蹂安。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椭迎。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖田盈,靈堂內的尸體忽然破棺而出畜号,到底是詐尸還是另有隱情,我是刑警寧澤允瞧,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布简软,位于F島的核電站蛮拔,受9級特大地震影響,放射性物質發(fā)生泄漏痹升。R本人自食惡果不足惜建炫,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疼蛾。 院中可真熱鬧肛跌,春花似錦、人聲如沸察郁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皮钠。三九已至稳捆,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間麦轰,已是汗流浹背乔夯。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留款侵,地道東北人末荐。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像新锈,于是被迫代替她去往敵國和親鞠评。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內容