![](/img/trans.png)
[英]Typescript create key constrained type for object literal with inferred number values
[英]In TypeScript, can I specify the type of object fields while still getting the literal key types inferred?
我要做的是定義某種“豐富的枚舉”,其中每個枚舉鍵都鏈接到我想指定其類型的一些數據。
例如,像這樣:
const Seasons = {
winter: { temperature: 5, startMonth: "December" },
spring: { temperature: 20, startMonth: "March" },
summer: { temperature: 30, startMonth: "June" },
fall: { temperature: 15, startMonth: "September" },
} as const
這個聲明很好,讓我可以做如下事情:
type Season = keyof typeof Seasons // "winter" | "spring" | "summer" | "fall"
甚至像
function isSeason(s: string): s is Season {
return Object.keys(Seasons).includes(s)
}
但是,我不能做的是讓編譯器檢查所有“季節定義”是否具有給定的類型。 如果我定義這個:
type SeasonData = typeof Seasons[Season]
然后SeasonData
是所有定義類型的並集——無論它們是否具有相同的形狀。
因此,我正在尋找一種語法上非冗余且輕便的方式來定義以下內容:
const Seasons: EnumWith<{temperature: number, startMonth: string}> = ... // as before
^^^^^^^^ <- to be defined!
特別是,我試圖不必在任何其他結構(接口或數組)中重復季節列表,並直接從 object 定義推斷類型Season
(盡管聽到替代總是好的。)。
可以做些什么?
我不確定我是否完全理解您的用例,我會 model 的方式您的類型之間的關系類似於以下內容
type Season =
| "winter"
| "spring"
| "summer"
| "fall"
type Month =
| "January"
| "February"
| "March"
| "April"
| "May"
| "June"
| "July"
| "August"
| "September"
| "October"
| "November"
| "December"
type SeasonStruct = {
temperature: number
startMonth: Month
}
type Seasons = { [K in Season]: SeasonStruct }
const seasons: Seasons = {
winter: { temperature: 5, startMonth: "December" },
spring: { temperature: 20, startMonth: "March" },
summer: { temperature: 30, startMonth: "June" },
fall: { temperature: 15, startMonth: "September" },
}
這應該為您提供足夠的構建塊來代表您在域中需要的所有內容,希望對您有所幫助。
剛剛找到了一種有點復雜的方法來從鍵中提取文字類型信息,同時仍然檢查值:
function EnumWith<P>() {
return function <K extends keyof any, R extends Record<K, P>>(defs: R): R {
return defs
}
}
這允許這樣寫:
const Seasons = EnumWith<{
temperature: number
startMonth: Month // defined as in bugs's answer
}>()({
winter: { temperature: 5, startMonth: "December" },
spring: { temperature: 20, startMonth: "March" },
summer: { temperature: 30, startMonth: "June" },
fall: { temperature: 15, startMonth: "September" },
})
type Season = keyof typeof Seasons
關鍵是要發現K extends keyof any
可以讓你在泛型簽名中捕獲鍵的類型,並將這兩種泛型類型划分為兩個 function 調用,以便我們可以指定一個並推斷另一個(目前不可能在 TypeScript 中的單個 function 調用中)。
所以,當然,這行}>()({
有點礙眼……
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.