[英]Is it possible to extend Array.prototype only for a specific type on 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.