<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          通過五個(gè)真實(shí)應(yīng)用場(chǎng)景,深入理解如何使用 TypeScript 枚舉(enum)

          共 14804字,需瀏覽 30分鐘

           ·

          2024-06-20 08:00

          如果你想讓你的 TypeScript 代碼更加有條理,枚舉(enum)是一個(gè)非常強(qiáng)大的工具。它可以將相關(guān)的值組合在一起,使你的代碼結(jié)構(gòu)更加清晰,易于閱讀。讓我們深入了解一下如何使用它們吧!

          一、簡單的示例:方向操作

          枚舉的一個(gè)常見用例是:在有限的選項(xiàng)集合中進(jìn)行選擇,使代碼更清晰明了。下面我們來看看一個(gè)簡單的例子,通過枚舉來處理方向操作。

          enum Movement {
            Up = "UP",
            Down = "DOWN",
            Left = "LEFT",
            Right = "RIGHT"
          }

          function handlePlayerInput(key: string) {
            switch (key) {
              case Movement.Up:
                // 移動(dòng)玩家角色向上
                console.log("移動(dòng)玩家角色向上");
                break;
              case Movement.Down:
                // 移動(dòng)玩家角色向下
                console.log("移動(dòng)玩家角色向下");
                break;
              case Movement.Left:
                // 移動(dòng)玩家角色向左
                console.log("移動(dòng)玩家角色向左");
                break;
              case Movement.Right:
                // 移動(dòng)玩家角色向右
                console.log("移動(dòng)玩家角色向右");
                break;
              default:
                console.log("無效的輸入");
            }
          }

          在這個(gè)例子中,我們定義了一個(gè)名為 Movement 的枚舉,它包含四個(gè)成員,分別代表四個(gè)方向:上、下、左、右。然后,我們使用這個(gè)枚舉在 handlePlayerInput 函數(shù)中處理玩家的輸入。

          為什么要用枚舉?

          • 代碼更清晰:使用枚舉后,代碼更具可讀性。你可以清楚地看到每個(gè)方向?qū)?yīng)的具體操作,而不必依賴字符串或數(shù)字。
          • 防止錯(cuò)誤:枚舉使得輸入值更加有限,減少了拼寫錯(cuò)誤的可能性。例如,使用字符串時(shí),容易出現(xiàn)拼寫錯(cuò)誤,而使用枚舉則可以避免這種情況。
          • 易于維護(hù):如果需要添加新的方向或修改現(xiàn)有的方向,只需在枚舉中進(jìn)行修改,而不需要在多個(gè)地方進(jìn)行字符串替換。

          總之,枚舉讓代碼更加直觀和可靠,是組織和管理固定選項(xiàng)集合的有效工具。

          二、 HTTP 狀態(tài)碼

          枚舉不僅可以表示簡單的選項(xiàng)集合,還可以關(guān)聯(lián)特定的值(如數(shù)字、字符串等)。下面我們通過一個(gè)示例展示如何使用帶值的枚舉來確保類型安全,并防止使用任意數(shù)字。


          enum StatusCode {
            OK = 200,
            BadRequest = 400,
            NotFound = 404
          }

          function handleResponse(code: StatusCode): string {
            if (code === StatusCode.OK) {
              return "請(qǐng)求成功";
            } else if (code === StatusCode.NotFound) {
              return "資源未找到";
            } else if (code === StatusCode.BadRequest) {
              return "錯(cuò)誤請(qǐng)求";
            } else {
              return "未知響應(yīng)碼";
            }
          }

          // 假設(shè)我們有幾個(gè)不同的響應(yīng)碼
          const responseCode1 = 200;
          const responseCode2 = 404;
          const responseCode3 = 400;

          // 將數(shù)字轉(zhuǎn)換為StatusCode類型,并調(diào)用handleResponse函數(shù)
          console.log(handleResponse(responseCode1 as StatusCode)); // 輸出:請(qǐng)求成功
          console.log(handleResponse(responseCode2 as StatusCode)); // 輸出:資源未找到
          console.log(handleResponse(responseCode3 as StatusCode)); // 輸出:錯(cuò)誤請(qǐng)求

          在這個(gè)例子中,我們定義了一個(gè)名為 StatusCode 的枚舉,它包含三個(gè)成員,分別代表 HTTP 狀態(tài)碼:200(OK),400(BadRequest),404(NotFound)。然后,我們?cè)?handleResponse 函數(shù)中使用這個(gè)枚舉來處理不同的 HTTP 響應(yīng)碼。

          三、在 Redux Toolkit 中使用枚舉

          Redux Toolkit 是一個(gè)流行的狀態(tài)管理庫,特別適用于 React 應(yīng)用。它大量使用 TypeScript 來確保類型安全。以下是一個(gè)定義異步操作狀態(tài)的枚舉,這在狀態(tài)管理庫中非常常見。


          enum PayloadActionLoadingState {
            Idle = "idle",
            Loading = "loading",
            Failed = "failed",
            Success = "success"
          }

          這個(gè)枚舉定義了異步操作的不同狀態(tài),如“空閑”(Idle)、“加載中”(Loading)、“失敗”(Failed)和“成功”(Success)。在 Redux Toolkit 中,管理這些狀態(tài)非常常見。

          在 Redux Toolkit 中應(yīng)用枚舉

          假設(shè)我們有一個(gè) Redux slice 來管理異步數(shù)據(jù)獲取操作的狀態(tài)。我們可以使用 PayloadActionLoadingState 枚舉來定義狀態(tài)并處理相應(yīng)的操作。

          定義 Slice

          首先,我們定義一個(gè) Redux slice:

          import { createSlice, PayloadAction } from '@reduxjs/toolkit';

          interface DataState {
            data: any;
            loadingState: PayloadActionLoadingState;
            error: string | null;
          }

          const initialState: DataState = {
            data: null,
            loadingState: PayloadActionLoadingState.Idle,
            error: null,
          };

          const dataSlice = createSlice({
            name: 'data',
            initialState,
            reducers: {
              fetchDataStart(state) {
                state.loadingState = PayloadActionLoadingState.Loading;
                state.error = null;
              },
              fetchDataSuccess(state, action: PayloadAction<any>) {
                state.loadingState = PayloadActionLoadingState.Success;
                state.data = action.payload;
              },
              fetchDataFailed(state, action: PayloadAction<string>) {
                state.loadingState = PayloadActionLoadingState.Failed;
                state.error = action.payload;
              },
            },
          });

          export const { fetchDataStart, fetchDataSuccess, fetchDataFailed } = dataSlice.actions;

          export default dataSlice.reducer;

          使用 Slice 和 枚舉

          在 React 組件中使用這個(gè) slice 和枚舉:

          import React, { useEffect } from 'react';
          import { useDispatch, useSelector } from 'react-redux';
          import { fetchDataStart, fetchDataSuccess, fetchDataFailed } from './dataSlice';
          import { RootState } from './store';
          import { PayloadActionLoadingState } from './payloadActionLoadingState';

          const DataComponent: React.FC = () => {
            const dispatch = useDispatch();
            const { data, loadingState, error } = useSelector((state: RootState) => state.data);

            useEffect(() => {
              const fetchData = async () => {
                dispatch(fetchDataStart());
                try {
                  const response = await fetch('https://api.example.com/data');
                  const result = await response.json();
                  dispatch(fetchDataSuccess(result));
                } catch (err) {
                  dispatch(fetchDataFailed(err.toString()));
                }
              };

              fetchData();
            }, [dispatch]);

            if (loadingState === PayloadActionLoadingState.Loading) {
              return <div>Loading...</div>;
            }

            if (loadingState === PayloadActionLoadingState.Failed) {
              return <div>Error: {error}</div>;
            }

            if (loadingState === PayloadActionLoadingState.Success) {
              return <div>Data: {JSON.stringify(data)}</div>;
            }

            return <div>Idle</div>;
          };

          export default DataComponent;

          解釋

          1、定義枚舉

          • PayloadActionLoadingState 枚舉定義了異步操作的四種狀態(tài)。

          2、創(chuàng)建 Slice

          • 定義了 DataState 接口來表示狀態(tài)結(jié)構(gòu)。
          • 使用 createSlice 創(chuàng)建了一個(gè)名為 data 的 slice,包含初始狀態(tài)和 reducers。

          3、處理異步操作

          • fetchDataStart:設(shè)置 loadingState 為 Loading,并清空錯(cuò)誤信息。
          • fetchDataSuccess:設(shè)置 loadingState 為 Success,并存儲(chǔ)獲取到的數(shù)據(jù)。
          • fetchDataFailed:設(shè)置 loadingState 為 Failed,并存儲(chǔ)錯(cuò)誤信息。

          4、在組件中使用

          • 使用 useDispatch 和 useSelector 訪問 Redux 狀態(tài)和 dispatch actions。
          • 在 useEffect 中發(fā)起異步請(qǐng)求,處理不同的狀態(tài)。根據(jù) loadingState 渲染不同的 UI。

          通過使用枚舉 PayloadActionLoadingState,我們確保了狀態(tài)的類型安全,并使代碼更具可讀性和可維護(hù)性。希望這個(gè)例子能幫助你更好地理解如何在 Redux Toolkit 中使用枚舉來管理異步操作狀態(tài)。

          四、使用枚舉作為判別聯(lián)合類型

          這個(gè)例子展示了如何使用枚舉來定義兩個(gè)可能的形狀:圓形(Circle)和矩形(Rectangle)。這是確保在處理不同形狀時(shí)的類型安全的基礎(chǔ)。

          每個(gè)形狀類型(Circle, Rectangle)都表示為 ShapeType 枚舉的一個(gè)成員。

          Shape 接口有一個(gè) type 屬性,它必須是 ShapeType 枚舉的一個(gè)成員。

          enum ShapeType {
              Circle = "Circle",
              Rectangle = "Rectangle"
          }

          interface Shape {
              type: ShapeType;
          }

          interface Circle extends Shape {
              type: ShapeType.Circle;
              radius: number;
          }

          interface Rectangle extends Shape {
              type: ShapeType.Rectangle;
              width: number;
              height: number;
          }

          function calculateArea(shape: Shape): number {
              switch (shape.type) {
                  case ShapeType.Circle:
                      const circle = shape as Circle; // 類型斷言為 Circle
                      return Math.PI * circle.radius * circle.radius;
                  case ShapeType.Rectangle:
                      const rectangle = shape as Rectangle; // 類型斷言為 Rectangle
                      return rectangle.width * rectangle.height;
                  default:
                      throw new Error("Invalid shape type");
              }
          }

          具體的形狀接口(Circle, Rectangle)擴(kuò)展了基礎(chǔ)的 Shape 接口,并且必須將其 type 屬性設(shè)置為對(duì)應(yīng)的枚舉值。

          我們可以創(chuàng)建一些形狀實(shí)例,并使用 calculateArea 函數(shù)來計(jì)算它們的面積:

          const myCircle: Circle = {
              type: ShapeType.Circle,
              radius: 5
          };

          const myRectangle: Rectangle = {
              type: ShapeType.Rectangle,
              width: 10,
              height: 5
          };

          console.log(`Circle Area: ${calculateArea(myCircle)}`); // 輸出:Circle Area: 78.53981633974483
          console.log(`Rectangle Area: ${calculateArea(myRectangle)}`); // 輸出:Rectangle Area: 50

          代碼解釋

          1、定義枚舉

          • ShapeType 枚舉包含兩個(gè)成員:Circle 和 Rectangle,表示兩種形狀類型。

          2、定義基礎(chǔ)接口

          • Shape 接口有一個(gè) type 屬性,類型為 ShapeType 枚舉。

          3、擴(kuò)展接口

          • Circle 接口擴(kuò)展了 Shape,并添加了 radius 屬性,同時(shí)將 type 屬性固定為 ShapeType.Circle。
          • Rectangle 接口擴(kuò)展了 Shape,并添加了 width 和 height 屬性,同時(shí)將 type 屬性固定為 ShapeType.Rectangle。

          4、實(shí)現(xiàn)面積計(jì)算函數(shù)

          • calculateArea 函數(shù)接受一個(gè) Shape 類型的參數(shù),通過 switch 語句檢查 type 屬性,根據(jù)不同的形狀類型執(zhí)行相應(yīng)的面積計(jì)算。
          • 使用類型斷言(Type Assertion)將 Shape 類型的參數(shù)轉(zhuǎn)換為具體的形狀類型(Circle 或 Rectangle),從而訪問特定屬性。

          通過這種方式,我們使用枚舉來創(chuàng)建判別聯(lián)合類型,使得 calculateArea 函數(shù)能夠根據(jù) type 屬性進(jìn)行分支處理,確保類型安全并執(zhí)行正確的計(jì)算。

          五、使用枚舉作為數(shù)據(jù)結(jié)構(gòu)

          這個(gè) TypeScript 示例展示了如何使用枚舉來表示撲克牌的花色、等級(jí)以及根據(jù)花色派生的顏色屬性。代碼包括兩個(gè)枚舉、一個(gè)獲取牌值的函數(shù)、一個(gè)描述牌結(jié)構(gòu)的接口,以及一個(gè)創(chuàng)建牌的函數(shù)。


          enum Suit {
            Hearts = "?", // 紅色花色
            Diamonds = "?", // 紅色花色
            Clubs = "?", // 黑色花色
            Spades = "?" // 黑色花色
          }

          enum Rank {
            Ace = 1,
            Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten,
            Jack, Queen, King 
          }

          function getCardValue(rank: Rank): number {
            if (rank <= Rank.Ten) {
              return rank;
            } else {
              return 10;
            }
          }

          interface Card {
            suit: Suit;
            rank: Rank;
            color: string; // 根據(jù)花色派生的屬性
          }

          function createCard(suit: Suit, rank: Rank): Card {
            return {
              suit,
              rank,
              color: suit === Suit.Hearts || suit === Suit.Diamonds ? 'Red' : 'Black'
            }
          }

          // 使用示例
          let card1 = createCard(Suit.Hearts, Rank.Ace);
          console.log(`The Ace of Hearts is red: ${card1.color}`); // 輸出:The Ace of Hearts is red: Red

          let card2 = createCard(Suit.Spades, Rank.Queen);
          console.log(`The Queen of Spades is black: ${card2.color}`); // 輸出:The Queen of Spades is black: Black

          解釋

          1、定義枚舉

          • Suit 枚舉定義了撲克牌的四種花色,每種花色都有一個(gè)符號(hào)表示。
          • Rank 枚舉定義了撲克牌的等級(jí),從 Ace 到 King。

          2、獲取牌值的函數(shù)

          • getCardValue 函數(shù)接受一個(gè) Rank 類型的參數(shù),并返回該牌的數(shù)值。對(duì)于 Ace 到 Ten,它們的數(shù)值等于等級(jí)本身。對(duì)于 Jack、Queen 和 King,它們的數(shù)值為 10。

          3、定義牌的接口

          • Card 接口描述了一張牌的結(jié)構(gòu),包括花色、等級(jí)和顏色屬性。顏色屬性是根據(jù)花色派生的,紅色花色(Hearts 和 Diamonds)為紅色,黑色花色(Clubs 和 Spades)為黑色。

          4、創(chuàng)建牌的函數(shù)

          • createCard 函數(shù)接受花色和等級(jí)作為參數(shù),并返回一個(gè) Card 對(duì)象。該函數(shù)根據(jù)花色來設(shè)置顏色屬性。

          這個(gè)示例展示了如何使用 TypeScript 的枚舉和接口來創(chuàng)建一個(gè)簡單的撲克牌模型。通過枚舉,我們可以確保花色和等級(jí)的類型安全,通過接口,我們可以定義牌的結(jié)構(gòu),使代碼更加清晰和易于維護(hù)。

          推薦閱讀

          結(jié)束

          通過以上幾個(gè)例子,我們可以看到枚舉在 TypeScript 中是如何發(fā)揮重要作用的。無論是提高代碼的可讀性,還是確保類型安全,枚舉都提供了一個(gè)干凈且結(jié)構(gòu)化的基礎(chǔ),讓我們的代碼更加規(guī)范和易于維護(hù)。

          隨著項(xiàng)目復(fù)雜度的增加,枚舉的優(yōu)勢(shì)會(huì)愈加明顯。它們不僅能讓代碼更易讀,更易維護(hù),還能減少錯(cuò)誤的發(fā)生,提升代碼的可靠性。

          如果你覺得今天的內(nèi)容對(duì)你有幫助,別忘了關(guān)注我的公眾號(hào)「前端達(dá)人」。你的關(guān)注和互動(dòng)是我繼續(xù)分享技術(shù)干貨的動(dòng)力。期待在評(píng)論區(qū)看到你的問題和建議,我們一起交流進(jìn)步!

          關(guān)注我,解鎖更多 TypeScript 技巧和最佳實(shí)踐!??


          瀏覽 71
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  激情插入视频 | 欧美日韩一级二级三级 | 天堂网在线视频 | 黄片 操逼| 婷婷丁香五月婷婷 |