項目45 安全でない型アサーションを、適切に型付けされた関数の内部に隠す
安全で型アサーションのない関数の実装と、望ましい型シグネチャの両方を実現できない状況では、型シグネチャを優先する
型シグネチャの方が利用者にとって親切なため
使いづらくなるコード
code:ts
interface MountainPeak {
name: string;
continent: string;
elevationMeters: number;
firstAscentYear: number;
}
async function checkedFetchJSON(url: string): Promise<unknown> {
const response = await fetch(url);
if (!response.ok) {
throw new Error(Unable to fetch! ${response.statusText});
}
return response.json();
}
// 型チェッカーのエラーを解消するためにPromise<unknown>にする必要がある
export async function fetchPeak(peakId: string): Promise<unknown> {
return checkedFetchJSON(/api/mountain-peaks/${peakId}); // OK
}
上記のように、不明確な型を型アサーションとして指定すると、利用する側では扱いにくくなる
良いコード
不明な型を具体的な型へのアサーションを関数本体に隠すことで、型アサーションを局所的なものにできる
code:ts
export async function fetchPeak(peakId: string): Promise<MountainPeak> {
return checkedFetchJSON(
/api/mountain-peaks/${peakId},
) as Promise<MountainPeak>; // 型アサーションを関数内部に隠蔽する
}
型アサーションを隠す別の方法として関数のオーバーロードがある
code:ts
export async function fetchPeak(peakId: string): Promise<MountainPeak>;
export async function fetchPeak(peakId: string): Promise<unknown> {
return checkedFetchJSON(/api/mountain-peaks/${peakId}); // OK
}
const denali = fetchPeak('denali');
// ^? const denali: Promise<MountainPeak>
型アサーションを使用する場合、その型アサーションが正しいことを保証するテストコードを書くと、よし信頼できる型となる