例如,api像这样的api('serviceName', {data: 1})
,由api的客户端调用。请注意,客户端不必与服务器在同一台计算机上运行。
api
如下:
export const api = async (type: string, payload: Object) => {
const res: any = await request
.post(`someurl.com/api`)
.json({data: ejson.stringify({type, payload})});
return res;
};
服务器端看起来像这样:
const apiRemote = (apiName, apiInput) => {
return apiList[apiName](apiInput)
}
请注意,客户端不能直接包含apiRemote
文件。
如何使api
具有类型?
一些几乎可行的示例:
interface S1 {
name: 's1',
input: number,
output: number,
}
interface S2 {
name: 's2',
input: string,
output: string,
}
interface List {
s1: S1;
s2: S2;
}
const a = async () => {
type Api = <T extends keyof List>(name: T, input: List[T]['input']) => List[T]['output'];
const api: Api = window["api"];
const x: number = await api("s1", 2);
const y: string = await api("s2", 's');
};
问题是我不喜欢格式化S1和S2。我想看起来像这样:
type S1 = (input:Input):Output
或类似的东西。
编辑2:
interface S1 {
name: 's1',
input: number,
output: number,
}
interface S2 {
name: 's2',
input: string,
output: string,
}
type Service<T extends { input: any, output: any }> = (input: T['input']) => Promise<T['output']>
// I'd like not to have this one because now I have to enforce manually that
// s1 key in List is the same as S1["name"].
// I think makes sense for the name to be in the S1 not in this List.
interface List {
s1: S1;
s2: S2;
}
// I'd like to keep it in this format instead
type S = S1 | S2;
const a = async () => {
// But in this place, if I replace `List[T]` with `S['input']` will lose the types.
type Api = <T extends S["name"]>(name: T, input: List[T]['input']) => Promise<List[T]['output']>;
const api: Api = window["api"];
const x: number = await api("s1", 2);
const y: string = await api("s2", 's');
};
答案 0 :(得分:1)
interface List {
s1: (input: number) => number;
s2: (input: string) => string;
}
// https://github.com/Microsoft/TypeScript/pull/26243
type Parameters<T extends (...args: any[]) => any> = T extends (...args: infer P) => any ? P : never;
const a = async () => {
type Api = <T extends keyof List>(name: T, ...input: Parameters<List[T]>) => ReturnType<List[T]>;
const api: Api = window["api"];
const x: number = await api("s1", 2);
const y: string = await api("s2", 's');
};
好的,如果您想这样做,可以使用以下代码从List
构造S
,然后像以前一样进行操作:
// Distributive conditional type to look at each union constituent of `S`
// and keep the one with the name we are looking for.
type Lookup<SS, K> = SS extends { name: infer N } ? N extends K ? SS : never : never;
type List = {
[K in S["name"]]: Lookup<S, K>
};
有关条件类型的更多信息,请参见handbook。