Type Guard 與 Enum 的應用
文字上翻譯的 Type Guard 就是類型守衛。我們經常需要根據後端的 API 響應或是程式碼邏輯操作來建立複雜的類型。有時候 VS Code 會報錯,提示我們需要排除一些不確定的類型定義。我們可以透過官方定義的 Utility Types 來做一些操作,但更多時候我們需要自行設計這些複雜的類型定義,以將型別限縮在我們希望的範圍中,這時類型守衛就派上了用場。
Type Guard 是一種 Run time 檢查,用來細化變量的類型範圍。
Type Guard 是一種特殊的函數,它根據某些條件來判斷變量是否屬於特定類型。
function isNumber ( value : any ) : value is number {
return typeof value === 'number' ;
}
const someValue : number = 42 ;
if ( isNumber (someValue)) {
console. log ( ` ${ someValue } is a number` );
} else {
console. log ( ` ${ someValue } is not a number` );
}
枚舉是一種會被編譯的類型,用於定義一組命名的常量。它可以幫助我們更清晰地表達特定的數值集合,提高程式碼的語義和可讀性。
Enum 可以用數字或字符串作為枚舉值,且默認情況下,Enum 的值會從數字 0 開始自動遞增。
enum Color {
Red = 0 ,
Green = 1 ,
Blue = 2 ,
}
enum Direction {
Up = 'UP' ,
Down = 'DOWN' ,
Left = 'LEFT' ,
Right = 'RIGHT' ,
}
這時我遇到了一個案例希望能在實作邏輯中添加枚舉的型別守衛,透過這種方式,我們能夠用通順地語義,描述我們的邏輯。
example
假設我們需要處理來自後端的複雜 API 響應數據,這些數據可能包含多種類型的信息。我們可以結合 Enum 和 Type Guard 來進行類型檢查,確保數據的正確性和一致性。
enum ApiResponseStatus {
Success = 'SUCCESS' ,
Error = 'ERROR' ,
Loading = 'LOADING' ,
}
interface ApiResponseBase {
status : ApiResponseStatus ;
}
interface ApiResponseSuccess < T > extends ApiResponseBase {
status : ApiResponseStatus . Success ;
data : T ;
}
interface ApiResponseError extends ApiResponseBase {
status : ApiResponseStatus . Error ;
message : string ;
}
interface ApiResponseLoading extends ApiResponseBase {
status : ApiResponseStatus . Loading ;
}
type ApiResponse < T > = ApiResponseSuccess < T > | ApiResponseError | ApiResponseLoading ;
function isApiResponseSuccess < T >(
response : ApiResponse < T >
) : response is ApiResponseSuccess < T > {
return response.status === ApiResponseStatus.Success;
}
function isApiResponseError < T >( response : ApiResponse < T >) : response is ApiResponseError {
return response.status === ApiResponseStatus.Error;
}
function isApiResponseLoading < T >(
response : ApiResponse < T >
) : response is ApiResponseLoading {
return response.status === ApiResponseStatus.Loading;
}
async function fetchData < T >( url : string ) : Promise < ApiResponse < T >> {
const response = await fetch (url);
const data = await response. json ();
if (response.ok) {
return {
status: ApiResponseStatus.Success,
data: data as T ,
};
} else {
return {
status: ApiResponseStatus.Error,
message: 'Failed to fetch data' ,
};
}
}
async function handleApiResponse < T >( url : string ) {
const response = await fetchData < T >(url);
if ( isApiResponseSuccess (response)) {
console. log ( 'Data:' , response.data);
} else if ( isApiResponseError (response)) {
console. error ( 'Error:' , response.message);
} else if ( isApiResponseLoading (response)) {
console. log ( 'Loading...' );
} else {
console. error ( 'Unknown response status' );
}
}
handleApiResponse <{ id : number ; name : string }>( 'https://api.example.com/getData' );
我們深入討論了 TypeScript 中的類型守衛(Type Guard)和枚舉(Enum),並嘗試結合這兩種強大的工具來提高代碼的安全性和可維護性。
Type Guard 允許我們在運行時進行精確的類型檢查,而枚舉提供了一種清晰且有語義的方式來定義一組命名常量。
通過實際範例,我們展示了如何在處理複雜的 API 響應數據時使用這些技術。
嘗試使用看看吧~