使用FlowType验证API响应

时间:2016-08-26 23:18:25

标签: javascript facebook flowtype

所以我到目前为止已经发现window.fetch会返回Response个对象defined here

我现在要做的是以某种方式扩展此定义以针对我的特定api进行类型检查。这是一个小例子。

我有一个端点,它会异步递减一个数字。响应可以返回400错误或200返回一些JSON有效负载。

所以我创建了一个interface来帮助解决这些问题:

interface ErrorResponse<S,T> {
  status: S,
  statusText: T,
}

interface JSONResponse<S,J> {
  status: S,
  json(): Promise<J>,
}

我正在使用一些泛型,所以我可以准确指出响应是什么:

type DecrementJSON = { count: number }
type DecrementResponse = ErrorResponse<400,string>
                       | JSONResponse<200,DecrementJSON>

然后我有我的api请求:

export const decrement = (count : number) : Promise<DecrementResponse> =>
  fetch('/dec', {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ count }),
  })

我收到了这个错误:

src/api/index.js:18
 18:   fetch('/dec', {
       ^ function call
 17: export const decrement = (count : number) : Promise<DecrementResponse> =>
                                                         ^^^^^^^^^^^^^^^^^ union: type application of polymorphic type: class type: ErrorResponse | type application of polymorphic type: class type: JSONResponse. This type is incompatible with
704: declare function fetch(input: string | Request, init?: RequestOptions): Promise<Response>;
                                                                                     ^^^^^^^^ Response. See lib: /private/tmp/flow/flowlib_2cb52cf2/bom.js:704
  Member 1:
   14: type DecrementResponse = ErrorResponse<400,string>
                                ^^^^^^^^^^^^^^^^^^^^^^^^^ type application of polymorphic type: class type: ErrorResponse
  Error:
   14: type DecrementResponse = ErrorResponse<400,string>
                                              ^^^ number literal `400`. Expected number literal `400`
  664:     status: number;
                   ^^^^^^ number. See lib: /private/tmp/flow/flowlib_2cb52cf2/bom.js:664
  Member 2:
   15:                        | JSONResponse<200,DecrementJSON>
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type application of polymorphic type: class type: JSONResponse
  Error:
   15:                        | JSONResponse<200,DecrementJSON>
                                             ^^^ number literal `200`. Expected number literal `200`
  664:     status: number;
                   ^^^^^^ number. See lib: /private/tmp/flow/flowlib_2cb52cf2/bom.js:664

亲自尝试here。感谢

感谢@vkurchatkin指出验证问题。我已经更新了函数以在内部进行所有验证:

type DecrementResponse = { status: 400, error: string }
                       | { status: 200, data: { count: number } }

export const decrement = async (count : number) : Promise<DecrementResponse> => {
  const response = await fetch('/dec', {
    method: 'POST',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ count }),
  })
  if (response.status === 400) {
    return {
      status: 400,
      error: response.statusText,
    }
  }
  if (response.status === 200) {
    const result = await response.json()
    return {
      status: 200,
      data: result,
    }
  }
  throw new TypeError(`Unknown response status: ${response.status}`)
}

因为我没有必要验证实际反序列化的json数据,所以唯一没有真正做到的事情。

另一个不进行类型检查的简单示例是this one

/* @flow */

// https://github.com/facebook/flow/blob/master/lib/bom.js#L711
interface StatusResponse<S> {
  status: S
}

type ApiResponse = StatusResponse<200> | StatusResponse<400>

const api = async () : Promise<ApiResponse> => {
  const response = await fetch('www.google.com')
  if (response.status === 200) {
    return response
  } else if (response.status === 200) {
    return response
  }
  throw new TypeError('unknown status')
}

在我看来,因为我们正在验证状态......

0 个答案:

没有答案