javascript - 获取返回对象的 Typescript 类型
问题描述
挑战
下面是我们如何在应用程序中控制和传递数据的简化示例。它用于许多地方,用于在 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 文件查找类型/接口定义,并根据找到的内容自动输出带有转换键的其他类型。
目前打字稿不支持通过类型定义自动进行这种转换,我猜他们对添加类似的东西会非常谨慎;例如,在类型定义中连接字符串文字尚未成为语言,不幸的是,您在这里寻找的东西比这要复杂得多。
推荐阅读
- javascript - 我需要访问对象数据(id-title-body)
- python - 获取不在列表中的随机字符串
- java - 从 Java 上传的 Firebase 存储图像不会在 Firebase 控制台中显示缩略图预览
- postman - 新的分区 CouchDB 文档
- objective-c - 只有在我的一个项目中,我根本无法使用 Xcode 断点,lldb 崩溃并始终使用相同的日志。有没有办法调试这个问题?
- python - 从其他函数和模块调用字典
- java - 如何使用 BufferedReader + StringTokenizer 实现 hasNext() 方法?
- javascript - 如何使用菜单按钮显示相应的元素数据类别?
- php - 如何在 PHP 中以每秒 100 次的方式批量进行 api 调用
- css - 为非 ASP .NET Core 应用寻找 SASS/SCSS/Less 库