【问题标题】:Get Typescript typing of returned object获取返回对象的 Typescript 类型
【发布时间】:2020-05-30 03:13:25
【问题描述】:

挑战

以下是我们如何在应用中控制和传递数据的简化示例。它用于许多地方,用于在 UI、API 和数据库之间转换数据。 API 和 UI 使用camelCase。 数据库使用snake_case

目前,Partial/Pick 类型的组合很尴尬,无法在哪里输入...

const item = { fooBar: 'something' }
Item.cast(item).value // returns type Partial<ItemModel>
Item.create(item).value // returns type ItemModel

目标是返回真正返回的对象类型。

// Examples
const item = { fooBar: 'something' }
Item.cast(item).value // returns { fooBar: 'something' }
Item.cast(item).databaseFormat // returns { foo_bar: 'something' }
Item.create(item).value // returns { id: '{uuid}', fooBar: 'something' }
Item.create(item).databaseFormat // returns { id: '{uuid}', foo_bar: 'something' }

const itemFromDatabase = { id: '{uuid}', foo_bar: 'something', baz: null }
Item.cast(itemFromDatabase).value // returns { id: '{uuid}', fooBar: 'something', baz: null }
Item.cast(itemFromDatabase).databaseFormat // returns { id: '{uuid}', foo_bar: 'something', baz: null }

对此有什么想法吗?我会想象它类似于 Object.entries() 返回类型,但我无法确定正确的 T keyof 组合。

// https://mariusschulz.com/blog/keyof-and-lookup-types-in-typescript
interface ObjectConstructor {
  // ...
  entries<T extends { [key: string]: any }, K extends keyof T>(o: T): [keyof T, T[K]][];
  // ...
}

代码

import camelcaseKeys from 'camelcase-keys'
import snakecaseKeys from 'snakecase-keys'

type Optional<T, K extends keyof T> = Pick<Partial<T>, K> & Omit<T, K>

interface ItemModel {
  id: string
  fooBar: any
  baz?: number
}

interface ItemDatabaseModel {
  id: string
  foo_bar: any
  baz?: number
}

export class Item {

  private _data: Partial<ItemModel>

  public static cast(item: Partial<ItemModel | ItemDatabaseModel>): Item {
    return new this(camelcaseKeys(item))
  }

  public static create(item: Optional<ItemModel | ItemDatabaseModel, 'id'>): Item {
    // Use item.id or add item.id === null to force key
    return new this(camelcaseKeys(item))
  }

  private constructor(input: Partial<ItemModel>) {
    // Validate "input" properties have a Item class property setter, else throw
    // foreach => this[key] = input[key]
  }

  get databaseFormat() { return snakecaseKeys(this._data) }
  get value() { return this._data }

  set id(value: string | null) {
    // automatically generate an ID if null, otherwise validate
    this._data.id = value
  }
  set fooBar(value: any) {
    // validate
    this._data.fooBar = value
  }
  set baz(value: number | null) {
    // validate
    this._data.baz = value
  }
}

【问题讨论】:

  • 您是说希望能够让 typescript 推断出在任意类型的对象通过函数转换这些键之后您将拥有哪些键?
  • @OliverRadini,是的!这是更好的表达方式。 :)

标签: javascript typescript class


【解决方案1】:

实现这一点的最佳方法是使用一些工具,该工具通过您的 typescript 文件查找类型/接口定义,并根据找到的内容自动输出带有转换键的其他类型。

目前 typescript 不支持通过类型定义自动进行这种转换,我猜他们在添加类似的东西时会非常谨慎;例如,在类型定义中连接字符串文字还没有进入语言,不幸的是,您在这里寻找的东西比这要复杂得多。

【讨论】:

    猜你喜欢
    • 2021-04-25
    • 1970-01-01
    • 1970-01-01
    • 2012-03-15
    • 2021-05-01
    • 1970-01-01
    • 2021-12-25
    • 2022-09-30
    • 2021-12-03
    相关资源
    最近更新 更多