對于我的專案,我需要想出一個 TypeScript 型別,這就是所謂的 CardSize。
這種型別可以采取多種形式。它可以是靜態值、回應式(特定于斷點的)值,也可以是由空格分隔的兩者的組合。
可能的(單數)值如下:
type CardSize =
'compact' |
'normal' |
'compact@small' |
'compact@medium' |
'compact@large' |
'normal@small' |
'normal@medium' |
'normal@large';
我最終想要的型別如下所示:
type CardSize =
'compact' |
... |
'normal@large' |
'compact normal@medium' |
'compact compact@small normal@medium' |
'compact@small normal@large' etc.
第一步似乎是利用模板文字型別,所以我涵蓋了所有的單數型別:
type CardSize = Size | `${Size}@${Breakpoint}`;
接下來,我嘗試研究 Permutations 以獲得可能值的任意組合,但到目前為止還沒有運氣。
如果我能以某種方式設定這兩個約束,那也會很好:
為了限制的可能組合的數量,以在分配相同的時間只有一個特定斷點值(例如,不同時具有'compact@small'與'normal@small在相同的字串)
其次,如果排列順序無關緊要,那就太好了。我會認為以下相同:
const size: CardSize = 'compact@small @normal@large';
const size: CardSize = 'normal@large compact@small';
有誰知道如何實作這種排列?即使這意味著沒有這兩個限制條件,它也會有很大的幫助!
回復:我意識到置換型別對于我想要實作的目標來說有點矯枉過正。我可以在CardSize不依賴| string作為后備的情況下強制執行型別安全嗎?
uj5u.com熱心網友回復:
您絕對可以生成字串值的排列/組合的聯合型別,通過模板文字型別遞回連接。當然,隨著要排列和組合的元素數量的增加,排列和組合的數量會迅速增加。TypeScript 只能處理數萬個元素數量級的聯合構建,當接近這個數量時,編譯器性能往往會受到影響。所以這種方法只適用于少量元素。
您的CardSize示例會很好,因為您只有兩個大小和四個斷點:
type CardSize = BuildCardSizes<'compact' | 'normal', '' | '@small' | '@medium' | '@large'>
whereBuildCardSizes<S, B>是一個適當定義的型別函式,它允許您根據需要使用任何內容S,但只允許您B最多使用一次元素。這是我如何定義它:
type BuildCardSizes<S extends string, B extends string, BB extends string = B> =
B extends any ? (`${S}${B}` | `${S}${B} ${BuildCardSizes<S, Exclude<BB, B>>}`) : never;
這樣做是采用B斷點的聯合并使用分布條件型別將其拆分為其組成成員。這就是B extends any ? (...) : never部分,在括號內,B只是該聯合的一個元素。請注意,我們還需要完整的聯合。TypeScript 并不容易做到這一點,所以我使用了BB另一個型別引數,它默認為原始的B. 在下文中,B表示“當前斷點聯合的某些特定元素”,而BB表示“當前完整的斷點聯合”。
因此,對于每個B,可接受的卡片大小是`${S}${B}`, 某些元素S與特定元素的串聯B;或者`${S}${B} ${BuildCardSizes<S, Exclude<BB, B>>}`,這是相同的東西,后跟一個空格,然后BuildCardSizes<S, Exclude<BB, B>>...這是您使用相同S但從B完整元素串列中洗掉的卡片尺寸集BB。
讓我們在您的示例上對其進行測驗:
/* type CardSize = "compact" | "normal" | "compact@small" | "normal@small" | "compact@medium" | "normal@medium" |
"compact@large" | "normal@large" | "compact@medium compact@large" | "compact@medium normal@large" |
"normal@medium compact@large" | "normal@medium normal@large" | "compact@large compact@medium" |
"compact@large normal@medium" | "normal@large compact@medium" | "normal@large normal@medium" |
"compact@small compact@medium" | "compact@small normal@medium" | "compact@small compact@large" |
"compact@small normal@large" | "compact@small compact@medium compact@large" |
"compact@small compact@medium normal@large" | "compact@small normal@medium compact@large" |
"compact@small normal@medium normal@large" | "compact@small compact@large compact@medium" |
"compact@small compact@large normal@medium" | "compact@small normal@large compact@medium" |
"compact@small normal@large normal@medium" | "normal@small compact@medium" | "normal@small normal@medium" |
"normal@small compact@large" | "normal@small normal@large" | "normal@small compact@medium compact@large" |
"normal@small compact@medium normal@large" | "normal@small normal@medium compact@large" |
"normal@small normal@medium normal@large" | "normal@small compact@large compact@medium" |
"normal@small compact@large normal@medium" | "normal@small normal@large compact@medium" |
"normal@small normal@large normal@medium" | "compact@large compact@small" | "compact@large normal@small" |
"normal@large compact@small" | "normal@large normal@small" | "compact@medium compact@small" |
"compact@medium normal@small" | "compact@medium compact@small compact@large" | ... */
呃,哇,編譯器對這個...的并集沒有問題,檢查筆記... 632個元素,但它太大了,我無法在這個答案中寫出來或完全檢查。不管怎樣,你可以從上面看到大小被重用,但斷點沒有。
讓我們抽查一下:
c = 'normal compact@small' // okay
c = 'compact@small normal' // okay
c = 'compact@small normal normal@large compact@medium' // okay
c = 'normal@small normal@medium normal@large normal' // okay
c = 'compact@small normal@small' // error
c = 'compact normal' // error
c = 'normal@small normal@medium normal@large normal normal@big' // error
c = '' // error
看起來挺好的!
As I mentioned in the comments, there are other approaches for larger numbers of elements; instead of generating a specific union of all possible acceptable values, you use a generic constraint to check that some given value is acceptable. It's more complicated, though, and out of scope for this question.
Playground link to code
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/351072.html
上一篇:只用逗號分割字串不留空格
