2021/07/27

Specific String On Typescript

今天在寫 anguar 的時候想到一個問題,一般我們在 parameter 後面帶的會是型別,像是:

const tester = (params: { name: string }): void => {
    console.log(params.name);
}

tester({name: 'a'}); // a

那是否可以直接限定想要的內容,答案是可以的:

const tester = (params: { name: 'a' | 'b' }): void => {
    console.log(params.name);
}
  
tester({name: 'a'}); // a

此時如果你下 tester({name: 'c'}); 會得到 TS2322: Type '"c"' is not assignable to type '"a" | "b"'. 的警告,不過多寫了幾個案例以後發現一個雷,不能用變數帶入:

const tester = (params: { name: 'a' | 'b' }): void => {
    console.log(params.name);
}
const params = {
    name: 'a'
};

tester(params); // a

上方的寫法會得到警告 TS2345: Argument of type '{ name: string; }' is not assignable to parameter of type '{ name: "a" | "b"; }'. Types of property 'name' are incompatible. Type 'string' is not assignable to type '"a" | "b"'.,最簡單的解法是:

const tester = (params: { name: 'a' | 'b' }): void => {  
    console.log(params.name);
}
const params = {
    name: 'a' as const
};

tester(params); // a

不過上社群討論後,最好的解法應該是用 enum

enum TesterParam {
    A = 'a',
    B = 'b'
}

const tester = (params: { name: TesterParam }): void => {
    console.log(params.name);
}
const params = {
    name: TesterParam.A
};

tester(params); // a

這樣的架構對維護來說是最好的。