【问题标题】:Can we build a typescript type based on the shape of a prop?我们可以根据道具的形状构建打字稿类型吗?
【发布时间】:2021-03-04 12:23:59
【问题描述】:

我有一个类型列表:

type A = 1
type B = 2
type X = 'x'
type Y = 'y'

我将收到如下对象:Record<string, A | B>。例如:{ test1: A, test2: B, test3: A}。我想创建一个返回这种类型的函数:{ test1: X, test2: Y, test3: X }

我知道我们可以做到:type Result<T> = T extends A ? X: T extends B ? Y : never 映射 AxBY,但这是我能做的最好的:

function transform <U extends string> (p: Record<U, A | B>): Record<U, Result<A | B>> {
  const result = {} as Record<U, Result<A | B>>
  (Object.keys(p) as U[]).forEach(k => (result[k] = p[k] === 1 ? 'x' as const : 'y' as const))
  return result
}

const a = transform({ test1: 1 as const, test2: 2 })
// a: Record<"test2" | "test1", "x" | "y">
// So a.test1 is of type 'x' | 'y' and not 'x'

当您不知道输入的确切形状时,我实际上不确定我想要实现的目标是否可以使用打字稿......

示例:

input type result type
{ foo: A; bar: B } { foo: X; bar: Y }
{ test1: A; test2: B; test3: A } { test1: X; test2: Y; test3: X }
{ test1: A; test2: A; test3: A } { test1: X; test2: X; test3: X }
{ stuff: A } { stuff: X }

基本上,知道A type 将被映射到̀X type, and B typewill be mapped toY type, I want that my transform`函数返回我一个对象,我可以确保:

  • input 中不存在的键在 output 中不存在,因此 output[key] 应该引发错误
  • 如果input[key] 属于A 类型,则output[key] 被正确推断为X 类型。

这可能吗?

【问题讨论】:

  • 您能否提供更多示例,说明您尝试通过一些预期和意外行为实现的目标?
  • 好主意。谢谢!

标签: typescript types


【解决方案1】:

我认为conditinal types 可以实现。这是一个可能的解决方案,带有帮助器类型MapResult

type MapResult<T> = {
    [K in keyof T]:
        T[K] extends A ? X
        : T[K] extends B ? Y
        : unknown
}

function transform <U extends Record<string, A | B>>(p: U): MapResult<U> {
    const result: Record<string, X | Y> = {};
    Object.keys(p).forEach(k =>
        result[k] = p[k] === 1 ? 'x' : 'y'
    )
    return result as MapResult<U>;
}

这应该符合您的要求。 Playground Link

【讨论】:

  • 我印象深刻!我真的认为这是不可能的。非常感谢,你是个天才! :)
猜你喜欢
  • 2021-03-23
  • 2020-10-05
  • 2019-05-30
  • 2021-02-22
  • 2020-02-14
  • 2018-10-26
  • 2022-08-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多