frouriojs/frourio

ServerResponseのbodyとheadersの型がanyになる

Closed this issue · 1 comments

Description

スクリーンショット 2021-06-06 18 39 38

type ServerResponse<K extends AspidaMethodParams> =
  | (K extends { resBody: K['resBody']; resHeaders: K['resHeaders'] }
  ? BaseResponse<K['resBody'], K['resHeaders'], K['status']>
  : K extends { resBody: K['resBody'] }
  ? PartiallyPartial<BaseResponse<K['resBody'], K['resHeaders'], K['status']>, 'headers'>
  : K extends { resHeaders: K['resHeaders'] }
  ? PartiallyPartial<BaseResponse<K['resBody'], K['resHeaders'], K['status']>, 'body'>
  : PartiallyPartial<
      BaseResponse<K['resBody'], K['resHeaders'], K['status']>,
      'body' | 'headers'
    >)
  | PartiallyPartial<BaseResponse<any, any, HttpStatusNoOk>, 'body' | 'headers'>

の定義の以下が原因

| PartiallyPartial<BaseResponse<any, any, HttpStatusNoOk>, 'body' | 'headers'>

status が HttpStatusNoOk かそれ以外かが決まっていないため BaseResponse<any, any, HttpStatusNoOk> の any になりうる

解決策の例

「HttpStatusNoOk では body と headers がない」と定義する

| BaseResponse<never, never, HttpStatusNoOk>

正常系で普通に body を取得するときは resBody に定義した型を取得

スクリーンショット 2021-06-06 18 48 35

ステータスを絞れば never

スクリーンショット 2021-06-06 19 05 54

この場合、以前バリデーションエラーの400のときはエラーを返してもらうようにして頂いたのでその body を考慮したりする必要があるかも知れません。
Promise.all(validators(req)).catch(err => reply.code(400).send(err))

サンプルのテストでステータスを絞る

スクリーンショット 2021-06-06 18 58 41

status が HttpStatusNoOk でないならば現状のままでも型は取れるのでサンプルのテストコードを書き換えて可能であればドキュメントに記載

Environment

  • Package version: vX.X.X
  • OS:
    • Linux
    • Windows
    • macOS
  • Node.js version: ``
  • npm version: ``

Additional context

非常に詳細に調べていただきありがとうございます。
答えを出すのにかなり時間がかかりましたが、画像のような絞り込みを記述することにしました
根本的な解決は aspida v2 をリリースしたあとなら実現できそうです

image