首頁 > web前端 > js教程 > 主體

TypeScript 幹預:使用 Byzantium 打破運行時檢查成癮

Barbara Streisand
發布: 2024-10-27 06:15:29
原創
797 人瀏覽過

聽著,我們需要談談你的類型檢查癮。是的,您-在您的身分驗證中間件中進行了 47 個instanceof 檢查。編寫的測試案例多於實際程式碼的開發人員。將 TypeScript 視為只是花哨的 JSDoc 註釋的人。

幹預

讓我為你畫一幅圖畫:現在是中午,你正在喝第四杯咖啡,並且正在調試一個生產問題。日誌顯示使用者以某種方式通過了十五層運行時驗證。你的單元測試比 Twitter 的活躍用戶還要多,但不知何故,不知何故,有人設法在應該是字符串的地方發送了一個數字。

「但那是不可能的!」你哭了,滾動瀏覽測試覆蓋率報告,顯示原始的 100%。 「我檢查過這個!」

你有嗎?你真的嗎?或者您只是將同一張支票寫了三次:

  1. 一旦進入 TypeScript 介面
  2. 再次在您的驗證中間件
  3. 再次在單元測試

停止測試 TypeScript 已經知道的內容

這是一個革命性的想法:如果我們......信任編譯器會怎麼樣?我知道,瘋狂的概念。但請聽我說完。

interface ValidRabbit {
    username: string;
    password: string;
}
interface InvalidRabbit {
    username: number;
    password: string;
}


type ValidateRabbit<Rabbit> = Assert<
    //assert that Rabbit is of type {username, password}
    Is.Type<
        User,
        {
            username: string;
            password: string;
        }
    >,
    //custom compile time exceptions
    "Trix are for kids. Provide a username and password.",
    User
>;

// Ha! Silly Rabbit...
function checkRabbit<T>(rabbit: ValidateRabbit<T>) {
    // .... protect your trix
}

declare const rabbit1: ValidRabbit;
declare const rabbit2: InvalidRabbit;

checkRabbit(rabbit1);
checkRabbit(rabbit2);
/**        ~~~~~~~~~
 *           └───── Type Exception! "...Provide a username and password"
 */
登入後複製
登入後複製

“但是生產呢?”

我現在可以聽到您的聲音:「但是如果有人向我的 API 發送無效的 JSON 怎麼辦?」

首先,誰傷害了你?其次,是的,驗證您的 API 邊界。但是,一旦該資料進入您的打字稿域,就該放手了。讓編譯器成為你的保鑣。

以下是拜占庭為您的信任問題聚會帶來的內容:

// Define your trust boundaries
type APIRequest<Request> = Assert<
    And<
    Is.On<Request, "body">,
    Or<Is.In<Request["method"], "POST">, Is.In<Request["method"], "PUT">>
>;,
    "Someone's being naughty with our API"
>;

// Now everything inside is type-safe
function handleRequest<R>(req: APIRequest<R>) {
    // If it compiles, it's valid
    // If it's valid, it compiles
    // This is the way
}
登入後複製

DevOps 團隊會愛你(一次)

想像一下:您的 CI/CD 管道在幾分鐘內完成,而不是幾小時。您的生產日誌中不會充滿類型錯誤。您的 AWS 帳單看起來不像電話號碼。

怎麼樣?因為拜占庭將類型檢查移至編譯時。沒有了:

  • 運行數千個僅檢查類型的單元測試
  • 消耗 CPU 週期一遍又一遍地檢查相同的類型
  • 凌晨 3 點醒來,因為有人將 undefined 傳遞給一個明確表示需要字串的函數
// Before: Your CPU crying for help
function validateUserMiddleware(req, res, next) {
    try {
        validateId(req.params.id)        // CPU cycle
        validateBody(req.body)           // CPU cycle
        validatePermissions(req.user)    // CPU cycle
        validateToken(req.headers.auth)  // CPU cycle
        // Your CPU is now considering a career change
        next()
    } catch (e) {
        res.status(400).json({ error: e.message })
    }
}

// After: Your CPU sending you a thank you note
type ValidRequest = Assert<
    And<
        Is.On<Request, 'params.id'>,
        Is.On<Request, 'body'>,
        Is.On<Request, 'user'>,
        Is.On<Request, 'headers.auth'>
    >,
    "Invalid request shape"
>;

function handleRequest(req: ValidRequest) {
    // Just business logic, no trust issues
}
登入後複製

“但我喜歡寫測試!”

The TypeScript Intervention: Breaking Your Runtime Check Addiction with Byzantium
偉大的!為真正需要測試的東西編寫測試:

  • 業務邏輯
  • 整合點
  • 使用者工作流程
  • 複雜演算法

你知道什麼不需要測試嗎?字串是否實際上是字串。讓 TypeScript 來處理這場生存危機。

真實的談話:好處

  1. 更快的發展

    • 不再用三種不同的方式寫相同的驗證
    • 在編譯時捕獲錯誤,而不是在凌晨 3 點
    • 花時間在功能上,而不是驗證樣板
  2. 更好的性能

    • 型檢的零運轉時開銷
    • 更小的套件大小(無驗證庫)
    • 快樂的CPU,快樂的生活
  3. 提高安全性

    • 類型級保證無法被繞過
    • 不再有「哎呀,忘了驗證」
    • 預設完全覆蓋
  4. DevOps 夢想

    • 更快的 CI/CD 管道
    • 降低基礎建設成本
    • 生產事故減少
    • SRE 團隊更快樂(結果可能會有所不同)

入門

interface ValidRabbit {
    username: string;
    password: string;
}
interface InvalidRabbit {
    username: number;
    password: string;
}


type ValidateRabbit<Rabbit> = Assert<
    //assert that Rabbit is of type {username, password}
    Is.Type<
        User,
        {
            username: string;
            password: string;
        }
    >,
    //custom compile time exceptions
    "Trix are for kids. Provide a username and password.",
    User
>;

// Ha! Silly Rabbit...
function checkRabbit<T>(rabbit: ValidateRabbit<T>) {
    // .... protect your trix
}

declare const rabbit1: ValidRabbit;
declare const rabbit2: InvalidRabbit;

checkRabbit(rabbit1);
checkRabbit(rabbit2);
/**        ~~~~~~~~~
 *           └───── Type Exception! "...Provide a username and password"
 */
登入後複製
登入後複製

選擇是你的

您可以繼續生活在恐懼中,為所有內容編寫運行時檢查,將 TypeScript 視為 JavaScript 的可選類型。

或您可以在 2024 年加入我們,我們信任我們的編譯器並讓它完成其工作。

記住:每次你寫執行時間類型檢查時,TypeScript 編譯器都會在某個地方哭泣。

結論

Byzantium 不僅僅是另一個庫——它是對類型信任問題的干預。是時候放棄運行時檢查並擁抱編譯時保證的力量了。

您的 CPU 會感謝您的。您的 DevOps 團隊會感謝您。您的用戶會感謝您(因為沒有發現與類型相關的錯誤)。

最重要的是,你會在凌晨 3 點感謝自己,當時你睡得很熟,而不是在生產中調試類型錯誤。


P.S.如果您仍然不相信,請嘗試計算程式碼庫中有多少個運行時類型檢查。然後乘以你的小時費率。這就是你花了多少時間不信任 TypeScript。

P.P.S.在撰寫這篇文章的過程中,沒有人受傷。儘管一些運行時檢查已永久停用。

*P.P.P.S。如果您想做出貢獻,請訪問我的 Github 並克隆該存儲庫。一切都還是新鮮的,所以有很多貢獻的機會。

JSR.io 上提供的文件和套件

以上是TypeScript 幹預:使用 Byzantium 打破運行時檢查成癮的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!