昨天我們完成了 Google Maps 的標記功能,今天我們來做個簡單的小小優化吧
今日重點:
今天要優化的原因不是因為什麼大問題,而是我們要知道,TypeScript 的本質是幫助我們能快速地處理錯誤,讓我們快速且精準地知道整份程式碼的錯誤在哪裡
今天的優化只是讓我們能夠更好除錯的優化,那就開始吧
我們先來看一下現在的 index.ts
// index.ts
import { User } from "./User";
import { Company } from "./Company";
import { CustomMap } from "./Map";
const map = new CustomMap();
const user = new User();
const company = new Company();
map.addMaker(user);
map.addMaker(company);
看起來很正常,但是其實會有一個小小的隱藏問題,注意這邊對 User
的使用
// User.ts
import { faker } from "@faker-js/faker";
export class User {
name: string;
location: {
lat: number;
lng: number;
};
constructor() {
this.name = faker.person.firstName();
this.location = {
lat: faker.location.latitude(),
lng: faker.location.longitude(),
};
}
markerContent(): string {
return `user name: ${this.name}!!`;
}
}
在 index.ts
中,map.addMaker()
之所以能接收 user
參數是因為我們在 class Map
的 addMaker(mappable: Mappable)
中有設定傳入參數必須符合 interface Mappable
// Map.ts
interface Mappable {
location: {
lat: number;
lng: number;
};
markerContent(): string;
}
export class CustomMap {
private googleMap: google.maps.Map;
constructor() {
this.googleMap = new google.maps.Map(
document.getElementById("maps") as HTMLElement,
{
zoom: 5,
center: {
lat: 23,
lng: 120.6,
},
}
);
}
addMaker(mappable: Mappable): void { // <== 因為這邊設定參數符合 Mappable
const markerI = new google.maps.Marker({
map: this.googleMap,
position: {
lat: mappable.location.lat,
lng: mappable.location.lng,
},
});
markerI.addListener("click", () => {
// Info Windows DOM
const contentString = `
<div>
<p>地圖</p>
<p>我是地點 info</p>
</div>`;
const infoWindow = new google.maps.InfoWindow({
content: mappable.markerContent(),
});
infoWindow.open(this.googleMap, markerI);
});
}
}
而我們的 User
實體有符合 interface Mappable
,所以被允許傳入 addMaker()
使用
圖示如下圖:
那,如果 User 其實是不符合 interface Mappable
的話呢?
如下圖,理應上 TypeScript 應該要提醒我們知道這個顯而易見的錯誤
但是可以發現 index.ts
會有錯誤提示,內容是 class User
不符合 class Map
中設定的 addMarker
要傳入的參數 Type Mappable
但是關鍵錯誤的地方 class User
卻沒有報錯
這就是問題
TypeScript 在 index.ts
中報的錯誤,讓我們知道是 class User
裡面不符合 class Map
中的 Type 設定,我們無法馬上精準地知道問題出在哪邊
這時就是
implements
出馬的時候!
我們可以設計 class User
的時候,就知道他必須要使用 class Map
的方法來標記在地圖上
所以我們在實作 class User
的時候可以預先設定要符合 class Map
裡面的方法
有點饒舌,但是實作意思上就是讓 class User
預先先符合 interface Mappable
先記得把 class Map
的 interface Mappable
export 出去
// Map.ts
export interface Mappable {
location: {
lat: number;
lng: number;
};
markerContent(): string;
}
...
...
在 class User
中引用,並設定好 User
的 Type 要經由 Mappable
實現 implements
// Map.ts
import { faker } from "@faker-js/faker";
import { Mappable } from "./Map";
export class User implements Mappable { // this way
// 如果要給其他模組使用,別忘記要寫 export 出去
name: string;
location: {
lat: number;
lng: number;
};
constructor() {
this.name = faker.person.firstName();
this.location = {
lat: faker.location.latitude(),
lng: faker.location.longitude(),
};
}
markerContent(): string {
return `user name: ${this.name}!!`;
}
}
這樣就完成囉,可以發現,如果我們在實作 class User
裡面的方法時,如果有缺漏,現在 TypeScript 也會正確地在 class User
中報錯,方便我們定位問題囉