簡體   English   中英

如何鍵入 Typescript 數組以僅接受一組特定的值?

[英]How to type a Typescript array to accept only a specific set of values?

我正在為我無法控制的庫編寫類型聲明文件。 其中一個方法接受一個字符串數組作為參數,但這些字符串只能是非常具體的值。 目前我將此參數輸入為string[] ,但我想知道是否有辦法增強它以包含特定值。

示例源(我無法更改):

Fruits(filter) {
    for (let fruit of filter.fruits)
    {
        switch(fruit)
        {
            case 'Apple':
                ...do stuff
            case 'Pear':
                ...do stuff
            default:
                console.error('Invalid Fruit');
                return false;
        }
    }
    return true;
}

我當前的類型聲明:

function Fruits(filter: FruitFilter): boolean;

interface FruitFilter {
    fruits: string[];
}

在我寫這個問題時,我想出了一個部分解決方案,即定義有效字符串的聯合類型,然后將該字段的類型設置為該聯合的數組而不是字符串數組。 這給了我想要的檢查,但我注意到如果你輸入一個無效的字符串,它會將數組中的所有字符串標記為無效,並顯示錯誤Type 'string' is not assignable to type 'Fruit' 有沒有更好的方法來做到這一點,以便只有違規字符串被標記為無效,或者這與我將要得到的一樣接近?

部分解決方案:

function Fruits(filter: FruitFilter): boolean;

type Fruit = 'Apple' | 'Pear'

interface FruitFilter {
    fruits: Fruit[];
}

所以,你的問題似乎是這樣的:

type Fruit = "Apple" | "Pear";
interface FruitFilter {
  fruits: Fruit[];
}
declare function Fruits(filter: FruitFilter): boolean;
Fruits({ fruits: ["Apple", "Apple", "Pear"] }); // okay
Fruits({ fruits: ["Apple", "App1e", "Pear"] }); // error
// actual error: ~~~~~~~  ~~~~~~~  ~~~~~~ <-- string not assignable to Fruit
// expected error:        ~~~~~~~ <-- "App1e" not assignable to Fruit

並不是你有錯誤,而是錯誤沒有正確地限制在數組的“壞”元素上。

我對為什么會發生這種情況的猜測是,編譯器傾向於將字符串文字擴展為string ,將元組類型擴展為數組,除非您提示不要這樣做。 因此,當它無法驗證fruits的類型為Fruit[] ,它會備份並查看您提供的內容。 它將["Apple", "App1e", "Pear"]擴展為string[] (忘記字符串文字和它是一個三元素元組的事實),意識到string[]不能分配給Fruit[] ,然后通過標記每個元素繼續警告您。 我對GitHub 問題進行了簡短搜索,看看是否有人報告過這種情況,但我還沒有看到。 可能值得提交一些東西。

無論如何,為了測試我的猜測,我決定改變Fruits()的聲明,以暗示如果可能的話,我們想要一個字符串文字元組。 請注意[目前沒有方便的方法來做到這一點]; 現在進行暗示的方法是,呃,煉金術:

// 🧙⚗🌞🌛❓
declare function Fruits2<S extends string, T extends S[] | [S]>(arr: {
  fruits: T & { [K in keyof T]: Fruit };
}): boolean;
Fruits2({ fruits: ["Apple", "Apple", "Pear"] }); // okay
Fruits2({ fruits: ["Apple", "App1e", "Pear"] }); // error
//                          ~~~~~~~ <--string is not assignable to never

好吧,該錯誤的位置就是您想要的位置,盡管該消息可能仍然令人困惑。 當編譯器嘗試將"Apple"分配給不存在的Fruit & "App1e"交集時,就會發生這種情況。 編譯器將Fruit & "App1e"減少到never ......正確,但可能為時過早,錯誤消息有用。

無論如何,我不建議這樣做的“解決方案”,因為它是更為復雜,只給你錯誤的情況下,一個稍微一些錯誤的經驗。 但至少這有點像是關於它為什么發生的答案,以及如何解決它的可能方向(例如,查找或提交有關它的問題)。 好的,祝你好運!

代碼鏈接

您也可以為此使用枚舉:

enum Fruits {
    Apple,
    Pear,
}

interface FruitFilter {
    fruits: Array<Fruits>;
}

這些將在純 Javascript 中轉換為 0 和 1。

如果需要,您也可以使用字符串代替數字。 然后你必須像這樣定義枚舉:

enum Fruits {
    Apple = 'Apple',
    Pear = 'Pear',
}

TypeScript 文檔有更多示例以及如何在運行時使用它:

https://www.typescriptlang.org/docs/handbook/enums.html#enums-at-runtime

它也能工作,如果你不想要一個類型

export interface MyInterface {
   fruits: Array<'apple' | 'pear' | 'strawberry'>
}

暫無
暫無

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

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