请教一个 Typescript 的问题

280 天前
 tlerbao

有两个响应类型 ResultData (不分页)和 ResultPage (分页),我下面封装的 get 方法每次调用的时候都要导入 ResultPage 或 ResultData ;

http.get<ResultPage<SomeType>>("/test", params);

http.get<ResultData<SomeType>>("/test", params);

TS 有没有什么办法传入一个参数或怎样实现自动识别调用分页和不分页的类型?

get<T>(url: string, params?: object, _object = {}): Promise<T> {
  return this.service.get(url, { params, ..._object });
}

// 请求响应
export interface Result {
  code: string;
  message: string;
}

// 请求响应数据
export interface ResultData<T = any> extends Result {
  data: T;
}

// 请求分页响应
export interface ResultPage<T> extends Result {
  count: number;
  current: number;
  limit: number;
  data: T[];
}
2271 次点击
所在节点    TypeScript
14 条回复
des
280 天前
Promise<ResultPage<T>>
des
280 天前
@des 定义两个不同的 get ,getPage 和 getResult 吧
pursuer
280 天前
大概试了一下类似这样
interface test{
(page:true):Promise<ResultPage>
(page:false):Promise<ResultData>
}
let get:test=function(page){
...
} as test;
tlerbao
280 天前
@des #2 定义两个 get 看来是比较简单的方法,但是为了学习更多的知识,不知道 typescript 有没有什么工具方法,或者传入两个泛型参数之类的(假设)。所以来问问
xavierchow
280 天前
> http.get<ResultPage<SomeType>>("/test", params);
> 或
> http.get<ResultData<SomeType>>("/test", params);

这两个调用的参数一模一样,可以思考一下为什么你每次调用的时候知道该指定哪个返回类型?( ResultData VS ResultPage )
是不是其实 params 的类型是不一样的?
如果是的话,可以去定义 params 的类型,然后用 https://www.typescriptlang.org/docs/handbook/2/conditional-types.html , 大致思路就是用 param 的类型去确定响应的类型。

另一个方式就是你去定义 UnionType ,比如 Result = ResultData | ResultPage, 你只用写 http.get<Resutl> ...
然后在使用返回的响应值的地方,用 TypeGuard ( https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards )去 narrow down 具体的类型( ResultData VS ResultPage )
zogwosh
280 天前

用函数重载
BeautifulSoap
280 天前
为什么一定要定义成接口,定义 ResultData 和 ResultPage 的 class 实现 Result 接口,然后传对应 class 的 object ,get 里用 instanceof 判断下不就解决的事情,,,,,,

ts 编译时会把所有接口信息抹去,在接口上折腾没意义(虽然我不知道类型体操有没有黑魔法能做到)
wusheng0
280 天前
T extends Array ? ResultPage : ResultData 这种呢
mmdsun
279 天前
自定义类型?

// 定义是否包含分页属性的类型检查
type IsPaginated<Params> = Params extends { current: number; limit: number } ? true : false;

// 结果类型的条件选择
type DecideResult<T, Params> = IsPaginated<Params> extends true ? ResultPage<T> : ResultData<T>;
zhours
279 天前
tlerbao
278 天前
@mmdsun 没太看懂怎么用呢?
tlerbao
277 天前
@zhours 学到了,
但是在 page 的时候要先在前面写一个 never 感觉怪怪的也不语义化,还有更好的办法吗?大神
const noPage = get<string>("");
const Page = get<never, string>("");
zhours
277 天前
tlerbao
277 天前
@zhours #13 感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1015681

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX