簡體   English   中英

switch case語句中的Typescript類型安全性

[英]Typescript type safety in switch case statements

我正在使用Redux,我正在嘗試使我的減速器類型安全。 我在ngrx-store / example應用程序中找到了一些代碼示例,他們完全成功地做到了這一點。 https://github.com/ngrx/example-app/blob/master/src/app/actions/book.ts

在將這個集成到我自己的項目中時,我發現了一些奇怪的東西,我無法解釋。 檢查以下代碼示例(內聯注釋):

// Action has a type and payload property
interface Action {
    type: string;
    payload?: any;
}

// Here I declare the action types as plain strings
const FIRST = "FIRST";
const SECOND = "SECOND";

// I create classes for every action with there respective types
class FirstAction implements Action {
    public type = FIRST;
    payload: { id: number };

    public constructor(id: number) {
        this.payload = { id };
    }
}

class SecondAction implements Action {
    public type = SECOND;

    public constructor() { }
}

// Create a union type
type Actions = FirstAction | SecondAction;

// Use the union type as type parameter in my function
function test(action: Actions): void {
    switch (action.type) {
        case FIRST:
                    // compiler will complain it cannot find the payload 
                    // property on Actions
            let temp = action.payload.id;
        case SECOND:
        // empty
        default:
        //empty
    }
}

如果我將FIRST和SECOND屬性的定義替換為以下內容,它確實有效。

export function type<T>(label: T | ''): T {
    return <T>label;
}


const FIRST = type("FIRST");
const SECOND = type("SECOND");

據我所知,type函數只將字符串強制轉換為字符串。 為什么代碼在調用type函數時有效,但在立即聲明字符串時卻沒有?

這是一個打字稿操場示例 ,您可以在其中注釋定義(首先是工作版本)。

這是因為TSC編譯器無法區分這兩個值:

const FIRST = "FIRST";
const SECOND = "SECOND";

它都是string類型,因此TSC不知道哪個屬於什么。 你必須給它一個類型,這就是你用你的type函數強制它所做的。

但如果按如下方式編寫它會更容易:

const FIRST: "FIRST" = "FIRST";
const SECOND: "SECOND" = "SECOND";

打字稿操場

它只適用於const,而不是正則表達式,沒有變量。

switch(variable_expression) { 
   case constant1: { 
      //code; 
      break; 
   } 
   case constant2: { 
      //code; 
      break; 
   } 
   default: { 
      //code; 
      break; 
   } 
}

我會使用as運算符:

let temp = (action as FirstAction).payload.id;

其他一些想法:
- 如果您已經擁有所有操作類都實現的Action ,那么您真的需要Actions嗎?
- 將每個案例的減速器提取到一個函數中可能有助於可讀性和單元測試。
- 請記住,reducer采取狀態和操作,並返回狀態(我知道你只是簡化了你的例子)。

function test(state: State, action: Action): State {
    switch (action.type) {
        case FIRST:
            return handleFirst(state, action as FirstAction);
        case SECOND:
            return handleSecond(state, action as SecondAction);
        default:
            return state;
    }
}

function handleFirst(state: State, action: FirstAction): State {
    let temp = action.payload.id;
    // ...
}

// ...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM