Typescript 是否可以根据对象属性推断/派生不同类型?

问题描述 投票:0回答:1

从这个数据来看,在 TypeScript 中是否可能:

const data = {
  field1: {values: ['a', 'b', 'c']},
  field2: {values: ['c', 'd', 'e'], multiple: true}
}

const fields = someFunction(data)

根据

someFunction
是否存在(或者是否正确,如果这会让事情变得更容易)来推断/导出
fields
的以下返回值(以及
multiple
的类型)?

type FieldsType = {
  field1: 'a' | 'b' | 'c',
  field2: ('c' | 'd' | 'e')[]
}
如果需要的话,

data
可以是
as const

typescript types type-inference
1个回答
3
投票

首先你需要一个源数据的类型:

type Data = Record<string, {
  values: readonly string[],
  multiple?: boolean
}>

然后您可以创建一个接受该条件的映射条件类型:

type Fields<T extends Data> = {
  [K in keyof T]:
    T[K]['multiple'] extends true
      ? T[K]['values'][number][]
      : T[K]['values'][number]
}

此类型映射

T
field1
field2
)中的所有键,并将该属性的值类型解析为条件类型。

该条件类型表示 if

T[K]['multiple'] extends true
then 返回该属性的
values
的成员类型的数组,否则返回该类型的非数组。

您现在可以使用该类型,例如:

function someFunction<T extends Data>(data: T): Fields<T> {
  // TODO: implement this
}

这符合您的期望:

const fields = someFunction({
  field1: { values: ['a', 'b', 'c'] },
  field2: { values: ['c', 'd', 'e'], multiple: true }
} as const)

fields.field1 // ('a' | 'b' | 'c')[]
fields.field2 // 'a' | 'b' | 'c'

看游乐场

© www.soinside.com 2019 - 2024. All rights reserved.