【问题标题】:How to use types as values in TypeScript? / Metatypes如何在 TypeScript 中使用类型作为值? / 元类型
【发布时间】:2022-01-05 10:04:11
【问题描述】:

我正在开发一个从数据源获取记录的组件。该组件是用我不太习惯的 TypeScript 编写的。

每条记录都有一个键和记录的值类型。 fetch 方法采用RecordDescriptor<Value> 的一个实例,其泛型参数Value 确定该方法的返回类型。

在 Swift 中,我将使用以下代码实现目标,并利用 metatypes

struct RecordDescriptor<Value> {
    let key: String
    let valueType: Value.Type // `Value.Type` is a metatype, the type of a type
}

func fetchValue<Value>(for descriptor: RecordDescriptor<Value>) -> Value {
    // …
}

let intRecordDescriptor = RecordDescriptor(key: "int_record", valueType: Int.self)
// `Int.self` refers to the `Int` type itself, not an instance of `Int`

let intValue = fetchValue(for: intRecordDescriptor)

基本上,我可以专门化泛型参数Value,而不使用类型的具体实例——只使用类型名称本身。

如何在 TypeScript 中实现相同的结果?

【问题讨论】:

  • 如果我是你,我会尝试用 JavaScript 写这个并将其作为一个 JavaScript 问题发布,因为它拥有世界上任何语言中最大的支持基础(而 TypeScript 几乎不被关注) 并且从 JavaScript 到 TypeScript 的转换是微不足道的。

标签: javascript swift typescript generics


【解决方案1】:

你不关心 Metatypes 的类型提示功能,你只关心他们的能力

访问初始化器或类或协议的其他静态成员

这很简单的拼写为:

interface Newable {
    new(): any
}

type Constructable<T> =
  T extends Newable
    ? T
    : T extends (...args: any[]) => unknown
      ? T : never

type RecordDescriptor<T, Key extends string> = { key: Key }
  & (
    T extends Constructable<T>
      ? { transformation: T }
      // Replace this arm with `never`
      // to not allow scalars / non-classes like `boolean`
      : { transformation: (arg?: unknown) => T }
    )

用法是:

let descriptorN: RecordDescriptor<Number, "numbers"> = {
  key: "numbers",
  transformation: Number
}
let resultN: Number = descriptorN.transformation("123")


let descriptorF: RecordDescriptor<(a: string, b: boolean) => string | boolean, "crazy"> =
  { key: "crazy", transformation: (a, b) =>  b ? "hi" : a.length > 3 }
let resultF: string | boolean = descriptorF.transformation("hmm", true)

let rp: RecordDescriptor<boolean, "options"> =
  { key: "options", transformation: () => true }
let resultP: boolean = rp.transformation()

Playground link

【讨论】:

    猜你喜欢
    • 2021-12-06
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 2017-06-09
    • 1970-01-01
    相关资源
    最近更新 更多