接口
接口提供了一套統一的訪問方式,但是具體的訪問邏輯和數據需要後面從新定義。只能描述 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: "" });