所以我到目前为止已经发现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')
}
在我看来,因为我们正在验证状态......