typescript 接口、泛型、函數

接口

接口提供了一套統一的訪問方式,但是具體的訪問邏輯和數據需要後面從新定義。只能描述 Object、 class 、 function 的類型。而且同名的 interface 會自動合併。【跟 type 的區別是 type 能夠描述所有數據類型,而且變量不能重名】

interface Animal {
  color?: string; // 可選屬性
  barking: string;
  age: number;
  readonly idCard: string; //  只讀屬性,只有初始化時可以被賦值
}

let dog: Animal = {
  color: "black",
  barking: "汪~",
  age: 2,
  idCard: "xx1321213212",
};

任意值類型

interface Point {
  color?: string;
  // 任意值類型 要求時 number 或者 string 或者 undefined
  // 因爲 color 在 Point 中,他需要滿足任意值類型要求返回的數據類型
  [key: string]: number | string | undefined;
}

let p1: Point = {
  color: "red",
  x: 3, // key 值是什麼這裏無關緊要了
};

// 因爲增加了 任意值類型,這裏也可以新增屬性
p1.z = 5;
// 因爲 數字其實完全可以通過字符串來標註, p1[0] => p1['0']
// 所以 [key: string] 雖然要求時字符串,但是並不影響
p1[0] = 9;

接口合併

interface Box {
  height: number;
  width: number;
}

interface Box {
  color: string;
}

let box: Box = { height: 1, width: 2, color: "red" };

用接口描述函數

interface iFunc {
  (x: number, y: number): number;
}

let fn1: iFunc = function (a: number, b: number) {
  return a + b;
};
// 第二種用法
function test(cb: iFunc) {
  let res = cb(2, 3);
}

test(function (a: number, b: number) {
  return a + b;
});

類型斷言

限定變量的類型,告訴編譯器,變量的具體類型,但是對代碼層面是沒有影響的

let img = document.querySelector("img");
// img && (<HTMLImageElement>img).src;

// 這種也可以
img && (img as HTMLImageElement).src;

this 的問題

interface T {
  a: number;
  fn: (x: number) => void;
}

let obj: T = {
  a: 1,
  // this 不再是 any【但是需要注意的是,這裏的第一個參數 還是 x】
  fn(this: T, x: number) {},
};

函數重載

同一個函數可以攜帶不同的參數列表,可以返回不同的數據類型

function setCss(
  el: HTMLElement,
  attr: "background" | "opacity",
  val: string | number
) {}

let el = document.querySelector("div");
el && setCss(el, "background", "red");
el && setCss(el, "background", 0.5); // 發現這樣寫沒有報錯

改進

// 函數重載
function setCss(el: HTMLElement, attr: "background", val: string);
function setCss(el: HTMLElement, attr: "opacity", val: number);
function setCss(el: HTMLElement, attr: any, val: any) {}

let el = document.querySelector("div");
el && setCss(el, "background", "red");
el && setCss(el, "background", 0.5); // 報錯。 已經規定了 background 屬性的值只能是 string

泛型

通過泛型解決不確定數據類型的問題

// 在這裏 obj 的類型不確定。只有實參傳遞的時候才能確定數據
function fn(obj: any, key: string): void {
  console.log(obj[key]);
}

let obj1 = {
  x: 1,
  y: 2,
};

let obj2 = {
  name: "lwt",
  age: 16,
};

// 比如這裏 obj2 根本沒有 x 卻沒有報錯
fn(obj2, "x");

解決

// 在這裏 用 T 代替可能傳遞的數據類型, key 用 keyof 取出 T 中的鍵
function fn<T>(obj: T, key: keyof T): void {
  console.log(obj[key]);
}

let obj1 = {
  x: 1,
  y: 2,
};

let obj2 = {
  name: "lwt",
  age: 16,
};

// 報錯
fn(obj2, "x");

一個案例

// 具體的業務場景是 data 中可能存放執行成功的數據,也可能存放執行失敗的數據
interface Res<T> {
  status: number;
  message: string;
  data: T; // 返回的數據格式不確定
}
// 執行成功需要返回的數據接口
interface SuccessData {
  id: number;
  name: string;
}
// 執行失敗需要返回的數據接口
interface FailData {
  errorInfo: string;
}

// 返回的數據
function test<T>(d: T): Res<T> {
  let data: Res<T> = {
    status: 200,
    message: "",
    data: d,
  };
  return data;
}

let succ = test<SuccessData>({ id: 1, name: "" });
let fail = test<FailData>({ errorInfo: "" });
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章