是否有一種簡寫方式來宣告具有許多遵循模式的屬性的介面。就我而言,我正在創建一個包含 30 個資料點的圖表。我的界面會是這樣的
interface BarData {
day1: number;
day2: number;
...
day30: number;
}
是否有一些符號可以讓我宣告day*從 1 到 30 的范圍而不必全部寫出來?
uj5u.com熱心網友回復:
假設您已經可以使用BarData但想要一種用更少的樣板代碼寫出來的方法(不幸的是,以更混亂的代碼為代價),這是一種方法:
type LessThan<N extends number, A extends number[] = []> =
N extends A['length'] ? A[number] : LessThan<N, [...A, A['length']]>;
type OneToThirty = Exclude<LessThan<31>, 0>;
/* type OneToThirty = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
| 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 */
interface BarData extends Record<`day${OneToThirty}`, number> { }
LessThan<N>type 函式是一種尾遞回條件型別,它采用非負整數文字型別 N并生成小于 的所有非負整數文字型別的并集N。LessThan<5>也是如此0 | 1 | 2 | 3 | 4。它通過累積由前一個累加器值的屬性組成的元組型別來實作這一點。length所以[]長度為0,[0]長度為1,[0, 1]長度為2,以此類推。
那么我們可以使用LessThan<31>來獲取0和之間的所有數字30,然后使用實用程式型別來排除和獲取to之間的Exclude<T, U>數字。0130
之后,我們"day"通過模板文字型別將這些數字附加到字串中Record<K, V>,使用實用程式型別來參考具有這些day*鍵且其值型別為 的型別number,最后定義為該記錄型別BarData的擴展。interface
您可以確保它有效:
function foo(bar: BarData) {
bar.day14 = 3;
}
萬歲!
但是......我有點懷疑你真的可以接受BarData。如果您在型別級別以編程方式描述鍵名,我想您也想在運行時以編程方式創建它們。但是編譯器不知道typefor (let i=1; i<31; i ) {}會產生什么。它只會推斷。所以你會得到錯誤:iOneToThirtynumber
for (let i = 1; i <= 30; i ) {
bar[`day${i}`] ; // error!
// Element implicitly has an 'any' type because expression of type
// '`day${number}`' can't be used to index type 'BarData'
}
除非你開始跳更多的圈子:
for (let j: OneToThirty = 1; j <= 30; j = j 1 as OneToThirty) {
bar[`day${j}`] ; // okay
}
這很好,但沒有比替代方案更安全的型別,其中BarData有一個模式索引簽名,你只需注意保持在界限內:
interface BarData {
[k: `day${number}`]: number;
}
function foo(bar: BarData) {
for (let i = 1; i <= 30; i ) {
bar[`day${i}`] ; // okay
}
}
在這一點上,您不妨只使用一個陣列,因為它對您有好處:
interface BarData {
day: number[];
}
function foo(bar: BarData) {
for (let i = 1; i <= 30; i ) {
bar.day[i] ; // okay
}
}
這可能是最傳統的方法。盡管如此,如果您對最初的BarData定義感到滿意,那么OneToThirty頂部的內容將實作您所尋找的。
Playground 代碼鏈接
uj5u.com熱心網友回復:
在最新版本的 TypeScript 中,您可以使用有效日期后綴和模板文字型別的聯合來做到這一點:
type DayNumbers = 1 | 2 | 3 | 4 | 5 | 6; // ...and so on
type BarData = {
[key in `day${DayNumbers}`]: number;
}
這要求物件擁有所有的日子:
// Works, it has all the required properties
const example1: BarData = {
day1: 1,
day2: 2,
day3: 3,
day4: 4,
day5: 5,
day6: 6,
};
// Doesn't work, it's missing `day6`:
const example2: BarData = { // Error: Property 'day6' is missing in type ... but required in type 'BarData'.(2741)
day1: 1,
day2: 2,
day3: 3,
day4: 4,
day5: 5,
};
游樂場鏈接
如果您不想要求所有這些,您可以使用?它們使它們成為可選:
type DayNumbers = 1 | 2 | 3 | 4 | 5 | 6; // ...and so on
type BarData = {
[key in `day${DayNumbers}`]?: number;
// ????????????????????????????^
}
...在這種情況下example2,上面會很好。
游樂場鏈接
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/462375.html
標籤:打字稿
