Typescript Template Types String Ascriminants

טיפוסי תבניות מילוליים משופרים עם Typescript 4.5

מה זה "הצרה" ב-TS?

לפני שנסתכל על השיפור של טיפוסים מילוליים ב-Typescript 4.5 ואילך, אני רק רוצה לסכם במהירות מה בעצם המשמעות של "הצרה" בהקשר הזה. בעיקרון אתה יכול לצמצם סוג ב-Typescript על ידי בדיקת המאפיינים של הישות. אם קיים נכס בישות שזמין רק עבור סוג מסוים, אז Typescript מבין זאת ולכן יכול לספק את הסוגים הנכונים.

דוגמא הקוד הבאה מדגימה למה אני מתכוון בכך.

type Addition = {
    sum: number;
}

type Subtraction = {
    result: number;
}

function calculate(action: Addition | Subtraction) {
    if ('sum' in action) {
      // Simple example of using properties
      // of an entity to narrow down its
      // actual type.
      //
      // 'action' is at this point of type
      // 'Addition'. Nice!
      const addition = action;
    }
}

צמצום עבור סוגי מחרוזת תבניות

החל מגרסה 4.5 של Typescript, ניתן ליישם את הדפוס הזה גם עבור טיפוסים מילוליים של תבניות, הידועים גם כמחרוזות מיוחדות עם סימנים אחוריים. התאמת הדפוסים הופכת לעוצמתית מאוד בשפה.

כמובן, כדי שהצמצום יהיה שמיש, כל הסוגים בהשוואה צריכים לחלוק את אותו מפתח מאפיין. אחרת, אתה יכול פשוט להשתמש בצמצום הנפוץ כמו לעיל.

דוגמא הקוד הבאה מראה כיצד מחרוזות תבנית יכולות להשתמש בצמצום:

type Addition = {
    variant: `${string}-addition`;
    sum: number;
}

type Subtraction = {
    variant: `${string}-subtraction`;
    result: number;
}

function process(action: Addition | Subtraction) {
    if (action.variant === "simple-addition") {
        // Stupid simple example, but you get the idea:
        // We used 'simple-addition', and the pattern 
        // matching by TS understood that '...-addition'
        // can be discriminated to 'Addition'.
        const addition = action;
    }
}
//
// Example that DOES NOT work.
//
// This demo illustrates that the
// discriminante has to be a string,
// else the pattern matching worn't work.

type Addition = {
    variant: `${string}-arithemtic`;
    sum: number;
}

type Subtraction = {
    variant: `${number}-arithemtic`;
    result: number;
}

function process(action: Addition | Subtraction) {
    if (action.variant === "123-arithemtic") {
        // Still 'Addion | Subtraction',
        // as we can only compare against
        // a string '123-arithmetic', which
        // is of course the same for both.
        const addition = action;
    }
}

ועכשיו אתה יודע על צמצום מילולי התבנית ב-Typescript! ייתכן שזו תכונה שלא תשתמש בה לעתים קרובות, אבל כשזה מתאים, אני חושב שהיא יכולה להפחית מאוד את מורכבות הקוד ולשמור על בסיס הקוד שלך קצת יותר נקי מאשר בלי התכונה.