我正在尝试为我们正在使用的库编写声明文件,而没有任何修改方法。
它的工作方式是您可以发送配置对象,返回将基于其中的一些键
const args = {
// ...
resources: {
One: {
query: { url: 'value' }
}
}
}
library(args)
调用它会返回一个对象,该对象具有resources
的深层嵌套键作为函数
const ret = {
One: {
query: async (query) => <data>
}
}
// ret.One.query(args) => data
理想情况下,每个<data>
也会被键入,由于动态键,我不确定是否可以输入?我已经尝试了几种使用keyof
参数的方法,但没有任何运气
编辑:更新示例
const config = {
// ...
resources: {
User: {
find: { url: 'http://example.com/userapi' }
},
Dashboard: {
update: { method: 'post', url: 'http://example.com/dashboardapi'}
}
}
}
const services = serviceCreator(config)
// service creator turns the supplied resources object into promise functions
await services.User.find({id: '123'}) // Promise<User>
await services.Dashboard.update({user: '123', action: 'save'}) // Promise<Dashboard>
答案 0 :(得分:2)
没有更多信息,我猜您正在寻找类似这样的东西:
type Arg<T> = { resources: T; }
type Ret<T> = {
[K in keyof T]: {
query: (...query: any[]) => Promise<any>;
}
}
declare const library: <T>(arg: Arg<T>) => Ret<T>;
让我们测试一下是否有效:
const args = {
resources: {
One: {
query: { url: 'value' }
}
}
}
var ret = library(args);
async function test() {
await ret.One.query(); // OK
}
您可以在此playground中进行尝试。
答案 1 :(得分:1)
我对TS还是陌生的,发现这个问题真的很有趣。这是我的看法,它很冗长,需要 weird 类型输入。但是它得到了很好的类型建议。我希望有更多经验丰富的用户提供反馈:
/**
* map dynamic resource type to method name,
* i.e 'User' -> 'find' | 'lookup'
*/
type MethodMap = Record<string, string>
interface ResourceParams {
url: string;
method?: 'GET' | 'POST' | 'PUT' | 'DELETE';
}
/**
* Each method in resource type has interface ResourceParams
*/
type Resources<T extends MethodMap> = {
[K in keyof T]: {
[S in T[K]]: ResourceParams;
}
}
interface Config<T extends MethodMap> {
resources: Resources<T>;
[key: string]: unknown;
}
type Result<T extends MethodMap> = {
[K in keyof T]: {
[S in T[K]]: () => Promise<any>
}
}
declare const library: <T extends MethodMap>(config: Config<T>) => Result<T>
// usage
const result = library<{ User: 'find' | 'lookup'; Dashboard: 'search' }>({
resources: {
User: {
find: { url: 'value' },
lookup: { url: 'asdads', method: 'GET' },
},
Dashboard: {
search: { url: 'value' }
},
}
})
result.User.find() // OK
result.User.lookup() // OK
result.Dashboard.search() // OK
result.User.search() // Not OK
result.Dashboard.find() // Not OK
result.Store.find() // Not OK