Typescript:返回一个返回promise类型定义的对象



我是TS的新手,一直被这个特殊的问题所困扰。

我正在用reduce构建一个对象,它将对象方法封装在一个函数中。我需要对象返回原始对象的密钥,以及apiDispatch函数的承诺,就我所知。

如有任何帮助,将不胜感激

const actions = {
getSomething: ({ id }) => ({
url: `/something/${id}`
})
};
function buildClient() {
const apiDispatch = async (data: any) => Promise;
return Object.entries(actions).reduce((acc, [key, value]) => {
acc[key] = (data: any, options: any): Promise<any> =>
apiDispatch({
...value(data),
...options
});
return acc;
}, {} as typeof actions);
}
const client = buildClient();
client.getSomething({ id: 123 }).then((res: any) => res);
  1. acc[key]给出以下错误-Element implicitly has an 'any' type because expression of type 'string' can't be used to index type
  2. client.getSomething().then()则不分配给该类型

链接到codesandbox:

https://codesandbox.io/s/typescript-playground-export-forked-2yg63?file=/index.ts

据我所知,getSomething属性的末尾应该有两个参数。

const acts = {
getSomething: ({ id }: { id: string }) => ({
url: `/something/${id}`
}),
getSomethingElse: ({ name }: { name: string }) => ({
url: `/something/${name}`
})
} as const;
type Actions = typeof acts;
type Fn = (...args: any[]) => object
const apiDispatch = <T,>(data: T) => Promise.resolve(data);
type Convert<T extends Record<string, Fn>> = {
[Prop in keyof T]: <Options extends object>(data: Parameters<T[Prop]>[0], options: Options) => Promise<any>
}
type O = Convert<typeof acts>
const buildClient = <
Keys extends string,
Value extends Fn,
Rec extends Record<Keys, Value>
>(actions: Rec) =>
Object.entries<Value>(actions).reduce((acc, [key, value]) => ({
...acc,
[key]: <T, U>(data: T, options: U) => apiDispatch({
...value(data),
...options
})
}), {} as Convert<Rec>);
const client = buildClient(acts)
const result = client.getSomething({ id: 'dsf' }, {}).then(data => data) // ok
const result2 = client.getSomethingElse({ name: 'dsf' }, {}).then(data => data) // ok
const result3 = client.getSomethingElse({ id: 'dsf' }, {}).then(data => data) // expected error

只是友好的建议,尽量避免TS。在这里,在我的博客中,你可以找到一些你可能会遇到的问题,改变TS 中的值

我只更改了一行就解决了您的问题。在这种情况下,TypeScript不够聪明,无法理解在这个地方的赋值是允许的。所以我要做的是稍微更改类型(像Sean(,然后使用TypeScript中的as运算符将其改回。

这就是代码现在的样子:

type OverrideReturn<T extends (...args: any[]) => any, R> = (...args: Parameters<T>) => R;
const actions = {
getSomething: ({ id }: { id: any }) => ({
url: `/something/${id}`
})
};
function buildClient() {
const apiDispatch = async (data: any) => ({ name: "test object" });
return Object.entries(actions).reduce((acc, [key, value]) => {
acc[key] = (data: any, options: any): Promise<any> =>
apiDispatch({
...value(data),
...options
});
return acc;
}, {} as Record<string, any>) as {} as { [K in keyof typeof actions]: OverrideReturn<typeof actions[K], Promise<any>> };
}
const client = buildClient();
client.getSomething({ id: 123 }).then((res: any) => res);

TypeScript游乐场

更新

出现此错误的原因是您定义了{} as typeof actions。有了这一点,Typescript希望您的accactions相同。但是,由于您希望acc有所不同,因此您需要为其定义一个新的返回类型。

  1. buildClient定义新类型,如果actions类型可以随时更改,则可以在此处使用Typescript Generic type。使用下面的新类型定义,Client类型将是一个与泛型类型具有相同属性键的对象,并且每个键的值将是返回Promise的函数

type Client<T> = Record<keyof T, (data: any, options?: any) => Promise<any>>;

  1. buildClient定义为接收泛型类型T的泛型函数

function buildClient<T>()

  1. 放置acc[key as keyof T],让Typescript知道属性键将来自泛型类型T
  2. {} as Client<T>,让Typescript知道{}Client<T>类型,而不是空对象
  3. 当您调用buildClient时,只需将<typeof actions>放在它旁边,这样Typescript就会用typeof actions替换所有泛型类型T

const client = buildClient<typeof action>()

在所有这些更改之后,Typescript现在将理解client只有一个属性getSomething,并且它是一个返回promise的函数。因此,最终代码将是:

type Client<T> = Record<keyof T, (data: any, options?: any) => Promise<any>>;
const actions = {
getSomething: ({ id }) => ({
url: `/something/${id}`
})
};
function buildClient<T>(): Client<T> {
const apiDispatch = async (data: any) => Promise;
return Object.entries(actions).reduce((acc, [key, value]) => {
acc[key as keyof T] = (data: any, options: any): Promise<any> =>
apiDispatch({
...value(data),
...options
});
return acc;
}, {} as Client<T>);
}
const client = buildClient<typeof actions>();
client.getSomething({ id: 123 }).then((res: any) => res);

最新更新