【问题标题】:Dynamic type inference with TypeScript types/interfaces使用 TypeScript 类型/接口的动态类型推断
【发布时间】:2020-08-21 09:41:30
【问题描述】:

我正在尝试编写一个返回类型为UnpackedValuesOnly 的函数,该函数可以动态确定“打包”值K 的类型,而无需用户明确定义K 是什么。

这是我所能到达的最接近的地方:

//pretend that this is a useful class for some reason
class PackedValue<T> {
  value: T
  constructor(value: T) {
    this.value = value
  }
}

//This is my best attempt at dynamically unpacking the type of a PackedValue
type UnpackedValuesOnly<T, K = any, K2 = any, K3 = any, K4 = any, K5 = any> = {
  [P in keyof T]: T[P] extends PackedValue<K>
    ? K
    : T[P] extends PackedValue<K2>
    ? K2
    : T[P] extends PackedValue<K3>
    ? K3
    : T[P] extends PackedValue<K4>
    ? K4
    : T[P] extends PackedValue<K5>
    ? K5
    : UnpackedValuesOnly<T[P], K, K2, K3, K4, K5>
}

const unpackObj = <T, K = any, K2 = any, K3 = any, K4 = any, K5 = any>(toUnpack: T): UnpackedValuesOnly<T, K, K2, K3, K4, K5> => {
  //implementation unimportant, assume that non packed values are preserved, packed values are unpacked
  return {} as any as UnpackedValuesOnly<T, K, K2, K3, K4, K5>
}


const foo = {
  a: 'hello',
  b: new PackedValue([ 1, 3 ]),
  c: new PackedValue('asdf')
}

const bar =  unpackObj<typeof foo, number[]>(foo)

//type of string
bar.a

//type of number[]
bar.b

//type of any
bar.c

以上有几个主要缺点:

  1. PackedValue 类型的数量是有限的,在本例中为 5 个
  2. 调用unpackObj 时,用户必须明确定义所有使用的PackValue 类型,否则这些类型将显示为any 类型并丢失所有编译器检查

有没有办法编写UnpackedValuesOnly,以便下面的示例代码允许编译器/linter 通过隐式确定PackedValue 的类型来报告正确的类型?

const bar = unpackObj(foo) // or maybe unpackObj<typeof foo>(foo)

//type of string
bar.a

//type of number[]
bar.b

//type of string
bar.c

【问题讨论】:

    标签: typescript


    【解决方案1】:

    是的,有一种使用infer关键字的方法:

    type UnpackedValueOnly<T> = {
        [key in keyof T]: T[key] extends PackedValue<infer U> ? U : T[key]
    }
    

    检查此TS sandbox 并将鼠标悬停在Test 上以查看变量foo 的初始类型是

    {
      a: string
      b: PackedValue<number[]>
      c: PackedValue<string>
    }
    

    解压后是

    {
      a: string
      b: number[]
      c: string
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-12-01
      • 2021-02-21
      • 2022-11-24
      • 2017-11-19
      • 1970-01-01
      • 1970-01-01
      • 2019-09-17
      • 1970-01-01
      相关资源
      最近更新 更多