首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在TypeScript中,我可以指定对象字段的类型,同时仍然可以推断出文字键类型吗?

在TypeScript中,我可以指定对象字段的类型,同时仍然可以推断出文字键类型吗?
EN

Stack Overflow用户
提问于 2020-06-25 17:39:31
回答 2查看 46关注 0票数 0

我要做的是定义某种“富枚举”,其中每个枚举键都链接到一些我想指定其类型的数据。

例如,就像这样:

代码语言:javascript
复制
const Seasons = {
    winter: { temperature: 5, startMonth: "December" },
    spring: { temperature: 20, startMonth: "March" },
    summer: { temperature: 30, startMonth: "June" },
    fall: { temperature: 15, startMonth: "September" },
} as const

这个声明很好,让我可以做如下事情:

代码语言:javascript
复制
type Season = keyof typeof Seasons // "winter" | "spring" | "summer" | "fall"

甚至是像这样的类型守卫

代码语言:javascript
复制
function isSeason(s: string): s is Season {
    return Object.keys(Seasons).includes(s)
}

然而,我不能做的是让编译器检查所有的“季节定义”是否都有一个给定的类型。如果我这样定义:

代码语言:javascript
复制
type SeasonData = typeof Seasons[Season]

那么SeasonData就是所有定义类型的联合--不管它们是否具有相同的形状。

因此,我正在寻找一种语法上无冗余且轻量级的方式来定义如下内容:

代码语言:javascript
复制
const Seasons: EnumWith<{temperature: number, startMonth: string}> = ... // as before
               ^^^^^^^^ <- to be defined!

特别是,我尽量不在任何其他结构(接口或数组)中重复季节列表,而是直接从对象定义中推断Season类型(尽管听到alternative总是不错的!)。

可以做些什么呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-25 18:02:51

我不确定我是否完全理解您的用例,我对您的类型之间的关系建模的方式如下所示

代码语言:javascript
复制
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" },
}

这将为您提供足够的构建块来表示您的域中所需的所有内容,希望它能有所帮助。

票数 1
EN

Stack Overflow用户

发布于 2020-06-25 18:22:19

我刚刚找到了一种从键中提取文字类型信息,同时仍然检查值的有点复杂的方法:

代码语言:javascript
复制
function EnumWith<P>() {
    return function <K extends keyof any, R extends Record<K, P>>(defs: R): R {
        return defs
    }
}

它允许这样写:

代码语言:javascript
复制
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允许您捕获泛型签名中的键的类型,并将两个泛型类型划分为两个函数调用,以便我们可以指定一个并推断另一个(目前在TypeScript中的单个函数调用中是不可能的)。

因此,诚然,}>()({这行代码有点难看…

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62572358

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档