Axios: ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ TypeScript์™€ ํ•จ๊ป˜ Axios๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•(AxiosResponse ๋ฌธ์ œ)

์— ๋งŒ๋“  2018๋…„ 04์›” 30์ผ  ยท  50์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: axios/axios

์š”์•ฝ

TypeScript(TS)๋กœ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ํ•˜๋Š” ํ”„๋กœ์ ํŠธ์— r => r.data ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. AxiosResponse ์œ ํ˜•์ด ์˜ˆ์ƒ๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  TS์— ์•Œ๋ฆฌ๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ? as Array<... ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์žฌ์ •์˜๋ฅผ ์‹œ๋„ํ–ˆ์ง€๋งŒ AxiosResponse ๋ฅผ Array ๋กœ ์บ์ŠคํŒ…ํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค(์˜ˆ: .length๊ฐ€ ์—†์Œ).

๊ฐ์‚ฌ ํ•ด์š”!

๋ฌธ๋งฅ

  • ์•ก์‹œ์˜ค์Šค ๋ฒ„์ „: 0.16.2
  • ํ™˜๊ฒฝ: Visual Studio ์ฝ”๋“œ

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‚ด axios.d.ts AxiosResponse ์žฌ์ •์˜:

import axios from 'axios'

declare module 'axios' {
  export interface AxiosResponse<T = any> extends Promise<T> {}
}

๋ชจ๋“  50 ๋Œ“๊ธ€

axios.request<T>(...args) ์Šคํƒ€์ผ ์ •์˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๋ฐฐ์—ด์˜ ๋งˆ์ง€๋ง‰ ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ๋Š” ์•”์‹œ์ ์œผ๋กœ (currentResponse: any) => T ์™€ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ data ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ:

interface ServerResponse {
  data: ServerData
}

interface ServerData {
  foo: string
  bar: number
}

๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

axios.request<ServerData>({
  url: 'https://example.com/path/to/data',
  transformResponse: (r: ServerResponse) => r.data
}).then((response) => {
  // `response` is of type `AxiosResponse<ServerData>`
  const { data } = response
  // `data` is of type ServerData, correctly inferred
})

@zcei ooh ์‹ค์ œ๋กœ ์ด๊ฒƒ์€ axios.interceptors.response.use ์™€ ๊ฐ™์€ ๊ธ€๋กœ๋ฒŒ ์ธํ„ฐ์…‰ํ„ฐ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚ด ์ƒ๊ฐ์—๋Š” - ์ธํ„ฐ์…‰ํ„ฐ๋Š” ํ˜„์žฌ ๋งค์šฐ "๋Š์Šจํ•œ" ์œ ํ˜•( any )์ด๋ฏ€๋กœ ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์—ฐ๊ฒฐํ•˜๊ณ  (r: any): any => r.data (๊ธฐ๋ณธ์ ์œผ๋กœ ์—„๊ฒฉํ•˜์ง€ ์•Š์€ ๋ชจ๋“œ์—์„œ๋Š” ์ž…๋ ฅ์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.

axios.request ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ง€์ ์—์„œ๋งŒ ์ผ๋ฐ˜์œผ๋กœ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ทธ๋Ÿฌ๋ฉด data ์†์„ฑ์˜ ์œ ํ˜•์œผ๋กœ ์ „๋‹ฌ๋ฉ๋‹ˆ๋‹ค.

(์‹ค์ œ๋กœ ์œ„์˜ ์ฝ”๋“œ ์Šค๋‹ˆํŽซ์—์„œ ์‹ค์ˆ˜๋ฅผ ํ–ˆ์Šต๋‹ˆ๋‹ค. data ๋Š” ์‹ค์ œ๋กœ AxiosResponse<ServerData> ์ด๊ณ  ServerData ์œ ํ˜•์˜ $ .data ํ•„๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. - ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค)

@zcei ์•ˆ๋…•ํ•˜์„ธ์š” ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค๋งŒ ์ด๊ฒƒ์€ ์ œ ์˜ˆ์ œ์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ๋ฅผ ๊ฐ•์กฐํ•˜๊ธฐ ์œ„ํ•ด ์ฝ”๋“œ ์ƒŒ๋“œ๋ฐ•์Šค๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ํ™•์ธํ•˜์„ธ์š”

๋™์ผํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์ธํ„ฐ์…‰ํ„ฐ๋Š” ๋ณธ์งˆ์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์š”์•ฝ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

this.instance.interceptors.response.use(response => response.data);

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋ฐ˜ํ™˜ ์œ ํ˜•

this.instance.post<string>(...);

AxiosPromise<string> ์ด๋ฉฐ, ๋ฐ์ดํ„ฐ๊ฐ€ ๋ž˜ํ•‘๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์˜๋„์ ์ž…๋‹ˆ๋‹ค. ์ธํ„ฐ์…‰ํ„ฐ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ ํ•ด์•ผ ํ•˜์ง€๋งŒ ์‘๋‹ต ํ‚ค๋ฅผ ํ˜ธ์ด์ŠคํŠธ ํ•ด์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

https://github.com/axios/axios/blob/0b3db5d87a60a1ad8b0dce9669dbc10483ec33da/lib/core/dispatchRequest.js#L63 -L67

๋‚˜๋Š” ๋‹น์‹ ์ด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์„œ๋ฒ„ ์‘๋‹ต์„ ๊ฐ€์งˆ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.

{
  "data": {
    "foo": 42
  }
}

response.data.data ์ค‘์ฒฉ์„ ์—†์• ๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ์ธํ„ฐ์…‰ํ„ฐ์—์„œ response.data ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋‚˜์ค‘์— response.data.data.foo response.data.foo ๋ฅผ ํ†ตํ•ด ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ response.foo ์•ก์„ธ์Šค๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‘๋‹ต ์ฝ”๋“œ ๋“ฑ๊ณผ ๊ฐ™์€ ๋‹ค๋ฅธ ํ•ญ๋ชฉ์„ ์ถ”์ ํ•˜๋Š” "๋ฃจํŠธ" ์‘๋‹ต ์ˆ˜์ค€์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ฃ„์†กํ•˜์ง€๋งŒ ์ ์–ด๋„ ๊ธฐ๋Šฅ์ ์œผ๋กœ๋Š” ๊ท€ํ•˜์˜ ์ „์ œ์— ๋™์˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์†์„ฑ์„ ํ’€์ง€ ์•Š๊ณ  ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

this.instance.post<string>(...).then(response => response.data);
this.instance.get<number>(...).then(response => response.data);

๋‚ด๊ฐ€ ์ •์˜ํ•˜๋Š” _๋ชจ๋“ _ ๋์ ์—์„œ. ๊ทธ ๋ชจ๋“  ์ฝ”๋“œ ๋ฐ˜๋ณต์˜ ์š”์ ์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

then ๊ฐ€ ์žˆ๋Š” ์š”์ฒญ์ด ์„ฑ๊ณตํ•  ๋•Œ๋งˆ๋‹ค ์‘๋‹ต ์ฝ”๋“œ ๋“ฑ์— ๋Œ€ํ•ด์„œ๋Š” ๋ณ„๋กœ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ๋ฌด์–ธ๊ฐ€๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ์—๋งŒ ์‘๋‹ต ์ฝ”๋“œ์— ์‹ ๊ฒฝ์„ ์“ฐ๋ฉฐ, ์ด๊ฒƒ์ด ๋ฐ”๋กœ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ๊ธฐ๊ฐ€ ์žˆ๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค. , ์ธํ„ฐ์…‰ํ„ฐ์™€ ํŠน์ • ๋์  ๋ชจ๋‘์—์„œ.

this.instance.interceptors.response.use(response => {
  // Everything went well, pass only relevant data through
  return response.data;
}, error => {
  // Something went wrong, figure out how to handle it here or in a `.catch` somewhere down the pipe
});

์š”์ฒญ์ด ์„ฑ๊ณตํ•  ๋•Œ๋งˆ๋‹ค, ์ฆ‰ then์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์‘๋‹ต ์ฝ”๋“œ์— ๋Œ€ํ•ด ๋ณ„๋กœ ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ธ€์Ž„, ๋‹น์‹  ์€ ๋‹ค๋ฅธ ์ •๋ณด์— ์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š์„ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋‹น์‹ ์ด ์˜ค์ง ๋ชธ์—๋งŒ ์‹ ๊ฒฝ์„ ์“ฐ๋Š” HTTP ํด๋ผ์ด์–ธํŠธ ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ชจ๋“  ์‚ฌ๋žŒ์—๊ฒŒ ์ œํ•œํ•˜๋Š” ๊ฒƒ์€ ์‹ค์ œ๋กœ ํ•ด๊ฒฐ์ฑ…์ด ์•„๋‹™๋‹ˆ๋‹ค.
์„ฑ๊ณต์ ์ธ ํ˜ธ์ถœ์—์„œ๋„ ์ƒํƒœ ์ฝ”๋“œ ๋ฐ ํ—ค๋”์— ๋Œ€ํ•œ ํ•ฉ๋ฒ•์ ์ธ ์‚ฌ์šฉ ์‚ฌ๋ก€๊ฐ€ ์ถฉ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. 204 vs 200 , ์†๋„ ์ œํ•œ ํ—ค๋” ํ™•์ธ, ์ถ”๊ฐ€ ๋ฆฌ์†Œ์Šค(ํŽ˜์ด์ง€ ๋งค๊น€)์— ๋Œ€ํ•œ Link ํ—ค๋” ์ถ”์ถœ ๋“ฑ pp.

์‹ ๊ฒฝ ์“ฐ์ง€ ์•Š๋Š”๋‹ค๋ฉด Axios๋ฅผ ๊ฐ์‹ธ๊ณ  ๋ชจ๋“  ๊ฒƒ์„ ๋ฒ„๋ฆฌ์‹ญ์‹œ์˜ค.

this.instance.request = <T>(...args) => {
  return axios.request<T>(...args).then(({ data }) => data)
}

this.instance.request<string>({ method: 'post', ... }).then(data => { ... });
this.instance.request<number>({ method: 'get', ... }).then(data => { ... });

ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์—์„œ ๋‚ด๊ฐ€ ํ•˜๋Š” ๋ฐฉ์‹๋Œ€๋กœ ๋ชจ๋“  ์‚ฌ๋žŒ์ด ์ผ์„ ํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฐœ๋…์„ ์–ด๋””์„œ ์–ป์—ˆ๋Š”์ง€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ €๋Š” ๋‹จ์ˆœํžˆ ๋ชจ๋“  ์š”์ฒญ์— โ€‹โ€‹๋Œ€ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ํ•ด์ œํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ๋…ธ๋ ฅ ์ค‘์ด๋ฉฐ ์ด ๋ฌธ์ œ๊ฐ€ ์ €๋ณด๋‹ค ๋จผ์ € ๋ฐœ์ƒํ–ˆ๋‹ค๋Š” ์ ์„ ๊ฐ์•ˆํ•  ๋•Œ ์ด ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š” ์œ ์ผํ•œ ์‚ฌ๋žŒ์€ ์•„๋‹™๋‹ˆ๋‹ค.

์ธํ„ฐ์…‰ํ„ฐ๋Š” ์ด๋ฆ„๊ณผ readme์˜ ์„ค๋ช…(๋ชจ๋“  ์‘๋‹ต์— ๋Œ€ํ•ด ๋ฌด์–ธ๊ฐ€๋ฅผ ์ˆ˜ํ–‰)์œผ๋กœ ์˜ฌ๋ฐ”๋ฅธ ์žฅ์†Œ๋ฅผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. 204 ๋Œ€ 200 ๋“ฑ์„ ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๋„ ์ธํ„ฐ์…‰ํ„ฐ์—์„œ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ํ•œ ์ค‘์•™์—์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

์ œ ์ƒ๊ฐ์— ์ง๊ด€์ ์ธ ์†”๋ฃจ์…˜์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ๊ฐ€์ง€ ์•Š๋„๋ก ์ธํ„ฐ์…‰ํ„ฐ์—์„œ ์›ํ•˜๋Š” ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ์˜ ์ผ๋ถ€ ํ•„๋“œ๋ฅผ ๋ณ€ํ™˜ํ•˜๋ ค๋Š” ๊ฒฝ์šฐ:

this.instance.interceptors.response.use(response => {
  response.data.foo = JSON.parse(response.data.bar);
  return response;
});

Axios์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ’€๊ณ  ์‹ถ๋‹ค๋ฉด:

this.instance.interceptors.response.use(response => response.data);

์ด๊ฒƒ์€ ๊ฐœ๋ฐœ์ž์—๊ฒŒ ๋ฌด์—‡์„ ํ•  ๊ฒƒ์ธ์ง€์— ๋Œ€ํ•œ ์„ ํƒ๊ถŒ์„ ๋‚จ๊ธธ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ œ ์ƒ๊ฐ์—๋Š” ์ด๊ฒƒ์ด ๋งค์šฐ ๋…๋‹จ์ ์ธ ์ธํ„ฐ์…‰ํ„ฐ๋ณด๋‹ค ๋‚ซ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋™์˜ํ•˜์ง€ ์•Š์œผ์…”๋„ ๋ฉ๋‹ˆ๋‹ค.

๋‹น์‹ ์€ "๋ชจ๋“  ์ฝ”๋“œ ๋ฐ˜๋ณต์˜ ์š”์ "์— ๋Œ€ํ•ด ์ถ”๋ก ํ•˜๊ณ  ์žˆ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ •๋ณด๊ฐ€ ํ•„์š”ํ•œ ์ด์œ ๋ฅผ ์„ค๋ช…ํ•˜๋ ค๊ณ ํ–ˆ์Šต๋‹ˆ๋‹ค.

์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ๊ณตํ†ต ๊ตฌ์กฐ ์—†์ด ์ „์ฒด ์‘๋‹ต์„ ๋’ค์„ž์„ ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์ธํ„ฐ์…‰ํ„ฐ์™€ ์‘๋‹ต์—์„œ ์œ ํ˜• ์•ˆ์ „์„ ์œ ์ง€ํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•œ ๋ฐฉ๋ฒ•์„ ์‹ค์ œ๋กœ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. :/
์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต ์œ ํ˜•์€ any ๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋ฉฐ ๊ฐœ๋ฐœ์ž๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋…ธ๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜์—๊ฒŒ ๊ทธ๊ฒƒ์€ ํ•˜๋‚˜์˜ ์†์„ฑ์— ์•ก์„ธ์Šคํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํŽธ์•ˆํ•œ ํƒ€์ดํ•‘์œผ๋กœ ์ธํ•ด ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๊ธฐ ์‰ฌ์šด ๊ฒƒ์ฒ˜๋Ÿผ ๋“ค๋ฆฝ๋‹ˆ๋‹ค.

"80% ์‚ฌ์šฉ ์‚ฌ๋ก€"์— ๋Œ€ํ•œ ์œ ํ˜• ์•ˆ์ „์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ๋ฃจํŠธ ์‘๋‹ต์„ ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” PR์„ ์ƒ๊ฐํ•ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋”ํ•  ๋‚˜์œ„ ์—†์ด ๊ธฐ์  ๊ฒƒ์ž…๋‹ˆ๋‹ค!

๋ฌธ์ œ๋Š” ๋‚ด๊ฐ€ ๋งŒ๋“  ์œ„์˜ ๋‘ ๊ฐ€์ง€ ์˜ˆ๊ฐ€ ๋ชจ๋‘ ์ด๋ฏธ ์„ค๋ช…ํ•œ ๋Œ€๋กœ ์ž‘๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋Šฅ์ ์œผ๋กœ๋Š” ์ž˜๋ชป๋œ ์œ ํ˜•์ผ ๋ฟ์ž…๋‹ˆ๋‹ค. ์ธํ„ฐ์…‰ํ„ฐ์—์„œ (์ˆ˜์ •๋œ) ์‘๋‹ต์ด ์•„๋‹Œ ๋‹ค๋ฅธ ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์ž˜๋ชป๋œ ๊ฒฝ์šฐ ๊ฑฐ๊ธฐ์—์„œ ์˜ˆ์ƒ๋˜๋Š” ์œ ํ˜•์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋จผ์ € @Etheryte ์™€ ๊ฐ™์€ ์ผ์„ ํ•˜๊ณ  ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์ด ํฅ๋ฏธ๋กญ์Šต๋‹ˆ๋‹ค!

์šฐ๋ฆฌ ์•ฑ์—์„œ r => r.data ๋Š” ์ฒด์ธ์˜ ์ตœ์ข… ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ์ด๋ฉฐ ์ƒˆ๋กœ ๊ณ ์นจ ํ† ํฐ ๋“ฑ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ƒํƒœ ์ฝ”๋“œ์— ์˜์กดํ•˜๋Š” ๋‹ค๋ฅธ ๊ฒƒ๋“ค์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ „ํ™”.

TS์—์„œ ์ด ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์ˆ˜์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ถˆ๊ฐ€๋Šฅํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ @zcei Axios API(์ธํ„ฐ์…‰ํ„ฐ)์˜ ๊ณต์‹ ๋ถ€๋ถ„์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ์ด๊ฒƒ์ด Axios๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํ•ฉ๋ฒ•์ ์ธ ๋ฐฉ๋ฒ•์ด๋ผ๋Š” ๊ฒƒ์€ ๋ถ€์ธํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋„! ํ•ญ์ƒ ์ž˜๋ชป๋œ ์ฝ”๋“œ ๐Ÿคฆโ€โ™‚๏ธ๋ฅผ ๋ณด๊ณ  ์žˆ์—ˆ๋Š”๋ฐ ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ์•„๋‹ˆ๋ผ transformResponse ์„น์…˜์— ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค - ์ •๋ง ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค!

๋ฐ˜ํ™˜ ์œ ํ˜•์„ ๋ณ€๊ฒฝํ•˜๋Š” ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด ์ž…๋ ฅ์„ ์–ด๋–ป๊ฒŒ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๊นŒ?

์•„๋งˆ๋„ ์ด๋Ÿฐ ๊ฒƒ?

interface AxiosInstance {
  request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
}

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถ€๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

axios.request<User, string>({
  method: 'get',
  url: '/user?id=12345'
})
  .then((foo: string) => { // <-- you could leave out the type annotation here, it's inferred
    console.log(foo)
  })

๋ฐฉ๊ธˆ ๋กœ์ปฌ์—์„œ ์‹œ๋„ํ–ˆ๊ณ  ์›ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์ €๋…์— ํ•จ๊ป˜ PR์„ ๋ฐ›์•„ ๋ชจ๋“  ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@zcei ์ข‹๋„ค์š”! ๋ฌผ๋ก  AxiosResponse๋ฅผ ๊ธฐ๋ณธ์œผ๋กœ ํ•˜๋Š” ๊ฒƒ์€ 99%์˜ ๊ฒฝ์šฐ์— ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค ๐Ÿ‘

๋“ฃ๊ธฐ ์ข‹์€! ํ˜ผ์„ ์„ ๋“œ๋ ค ๋‹ค์‹œ ํ•œ ๋ฒˆ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜“

@zcei ๋ฌธ์ œ ์—†์Šต๋‹ˆ๋‹ค! Axios์˜ ์ถœ์‹œ ์ฃผ๊ธฐ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

์—†์Šต๋‹ˆ๋‹ค. ์•„์ง v1 ์•ŒํŒŒ(#1333)์— ๋Œ€ํ•ด ๋ณด๋ฅ˜ ์ค‘์ธ ์‚ฌํ•ญ์ด ์žˆ์œผ๋ฉฐ ๊ทธ ๋™์•ˆ @nickuraltsev / @emilyemorehouse ๋Š” ํ•„์š”ํ•  ๋•Œ๋งˆ๋‹ค ๋ฆด๋ฆฌ์Šค๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
v0.18 ์ดํ›„๋กœ ์•ฝ๊ฐ„์˜ ๊ฒฌ์ธ๋ ฅ์ด ์žˆ์–ด(๋‚ด๊ฐ€ ๊ฐ€์žฅ ์ข‹์•„ํ•˜๋Š”: ์ธ์Šคํ„ด์Šค์— ๋Œ€ํ•œ ๋ฒ”์œ„ ์ง€์ • ์˜ต์…˜ ํฌํ•จ) ๋ฆด๋ฆฌ์Šค๋ฅผ ์ค‘๋‹จํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์›ํ•˜์‹œ๋ฉด Gitter ๋กœ ์—ฌ๋Ÿฌ๋ถ„์„ ์ดˆ๋Œ€ํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

0.19 ๋ฆด๋ฆฌ์Šค๊ฐ€ ๋‚˜์˜ค๊ธธ ๋ฐ”๋ž์ง€๋งŒ ๋งˆ์ง€๋ง‰์œผ๋กœ ํ™•์ธํ•œ ๊ฒฐ๊ณผ ๋งˆ์Šคํ„ฐ๊ฐ€ CI์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. 1.0์ด ์ถœ์‹œ๋˜๋ฉด ๋” ํ™•์‹คํ•˜๊ณ  ์ •๊ธฐ์ ์ธ ๋ฆด๋ฆฌ์Šค ์ผ์ •์„ ์›ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ™์€ ๋ฌธ์ œ๋ฅผ ๋งŒ๋‚œ๋‹ค. ํ•ด๊ฒฐ์ฑ…์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@qidaneix ๋ฆด๋ฆฌ์Šค๊ฐ€ ๋‚˜์˜ฌ ๋•Œ๊นŒ์ง€ npm install axios/axios#master ์„ค์น˜๋ฅผ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. #1605๋Š” ๊ทธ๊ฒƒ์„ ๊ณ ์ณค์–ด์•ผ ํ–ˆ๋‹ค. ํ…Œ์ŠคํŠธ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์‹ค์ œ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ์‹ค์ œ๋กœ ๋„์›€์ด ๋˜๋Š”์ง€ ์—ฌ๋ถ€์— ๋Œ€ํ•œ ํ”ผ๋“œ๋ฐฑ์„ ๋ฐ›๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๐Ÿ™‚

@zcei ๋‚ด์ผ ํ•ด๋ด์•ผ์ง€

@zcei ์–ธ์ œ ์ถœ์‹œ๋˜๋Š”์ง€ ์—ฌ์ญค๋ด๋„ ๋ ๊นŒ์š”?

1.0.0์ด ์ถœ์‹œ๋  ๋•Œ +1?

์ด๊ฒƒ์€ ํ™•์‹คํžˆ pre-1.0 ๋ฆด๋ฆฌ์Šค๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. @Khaledgarbaya Matt๊ฐ€ NPM์—๋„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๊นŒ? ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ๋ฆด๋ฆฌ์Šคํ•˜๋Š” ๋‚˜๋จธ์ง€ ์œ ์ง€ ๊ด€๋ฆฌ์ž์—๊ฒŒ ์นœ์ ˆํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค ๐Ÿ˜‰

๋ชจ๋‘ ์•ˆ๋…•. ํ˜„์žฌ NPM ๋ฆด๋ฆฌ์Šค๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ 1.0.0 ์ด์ „ ๋ฆด๋ฆฌ์Šค๋ฅผ ๋ฐœํ‘œํ•˜๊ณ  ์‹ถ์ง€๋งŒ Travis ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํŒจํ•˜๊ณ  ์žˆ์œผ๋ฉฐ ์•„์ง ์ˆ˜์ •ํ•  ๊ธฐํšŒ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜๋ฉด ์ฆ‰์‹œ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์–ด ๋”์šฑ ๊ธฐ์ฉ๋‹ˆ๋‹ค ๐Ÿ˜ฌ

@zcei npm ์ €์žฅ์†Œ์— ์ถ”๊ฐ€๋˜์ง€ ์•Š์•˜์œผ๋ฉฐ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๋ณ‘ํ•ฉํ•  ์ˆ˜๋งŒ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ๊ฐ€๊นŒ์šด ์žฅ๋ž˜์— 2๊ฐœ์›”์ฐจ์™€ ๊ฐ™์€ ๋ฆด๋ฆฌ์Šค๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ?

+1

โค๏ธ ์ง€๊ธˆ ์ถœ์‹œ๋œ๋‹ค๋ฉด

์•Œ๊ณ  ์žˆ์ง€๋งŒ ํ˜„์žฌ ์ฐจ๋‹จ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๐Ÿ™ ์—ฌ๊ธฐ์—์„œ ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: https://github.com/axios/axios/issues/1657#issuecomment -410766031

0.19.0-beta.1์˜ ์ผ๋ถ€๋กœ ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

npm install [email protected] ๋˜๋Š” npm install axios@next ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„ค์น˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋งˆ๋„ ์ด๋Ÿฐ ๊ฒƒ?

interface AxiosInstance {
  request<T = any, R = AxiosResponse<T>> (config: AxiosRequestConfig): Promise<R>;
}

๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถ€๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

axios.request<User, string>({
  method: 'get',
  url: '/user?id=12345'
})
  .then((foo: string) => { // <-- you could leave out the type annotation here, it's inferred
    console.log(foo)
  })

๋ฐฉ๊ธˆ ๋กœ์ปฌ์—์„œ ์‹œ๋„ํ–ˆ๊ณ  ์›ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์ €๋…์— ํ•จ๊ป˜ PR์„ ๋ฐ›์•„ ๋ชจ๋“  ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

User(T, ์ฒซ ๋ฒˆ์งธ ์ผ๋ฐ˜ ๋งค๊ฐœ๋ณ€์ˆ˜)๊ฐ€ ์‚ฌ์šฉ๋˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ๋ฐ˜ํ™˜ ์œ ํ˜•์„ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์ด์ƒํ•˜๊ฒŒ ๋ณด์ž…๋‹ˆ๋‹ค ๐Ÿ˜•

axios.request<void, string>({
    ...
})

void๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ๋ช…ํ™•ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@emilyemorehouse ๊ฐ์‚ฌํ•˜์ง€ ์•Š๊ฒŒ ๋“ค๋ฆฌ์ง€๋งŒ 0.19-๋ฒ ํƒ€๊ฐ€ 3๊ฐœ์›” ๋™์•ˆ ๊ณต๊ฐœ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. GA ๋ฆด๋ฆฌ์Šค์— ๋Œ€ํ•œ ETA๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ์—๋Š” ์ด๋Ÿฌํ•œ ์ˆ˜์ • ์‚ฌํ•ญ ์ค‘ ํ•˜๋‚˜๊ฐ€ ํ•„์š”ํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” Gitter ์ฑ„๋„์—์„œ ์ด๊ฒƒ์„ ๋ฌผ์—ˆ์ง€๋งŒ ์œ ์ง€ ๋ณด์ˆ˜๊ฐ€ ๊ฑฐ๊ธฐ์—์„œ ์‘๋‹ตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค ...

๋ฆด๋ฆฌ์Šค ์ „์— ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š” ๋ฌธ์ œ๋Š” ๋ฌด์—‡์ด๋ฉฐ ์ถ”์ ํ•  ์ˆ˜ ์žˆ๋Š” ์žฅ์†Œ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์ด ๋” ๋‚˜์€ ํ‘œํ˜„์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋งŽ์€ ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์œผ๋‹ˆ ์ž‘์—…์„ ๋ถ„์‚ฐํ•˜๊ณ  ํ•„์š”ํ•œ ์ž‘์—…์„ ๋ช…ํ™•ํ•˜๊ฒŒ ์ดํ•ดํ•˜๋ฉด ์ž‘์—… ์†๋„๋ฅผ ๋†’์ด๋Š” ๋ฐ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ 0.19์— ๋Œ€ํ•œ ํ”„๋กœ์ ํŠธ ๋งˆ์ผ์Šคํ†ค์ด ์žˆ์ง€๋งŒ ๋‚˜์—ด๋œ ํ‹ฐ์ผ“์€ ๋ช‡ ๋‹ฌ ๋™์•ˆ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์—†์Šต๋‹ˆ๋‹ค.

const func1: ๋ชจ๋“  = () => { axios.request(...) ๋ฐ˜ํ™˜ }

๋‚ด axios.d.ts AxiosResponse ์žฌ์ •์˜:

import axios from 'axios'

declare module 'axios' {
  export interface AxiosResponse<T = any> extends Promise<T> {}
}

์ด ๋ฌธ์ œ๋ฅผ ๋ฒ”ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค ... ๋ฐฉ๊ธˆ AxiosInstance ์ •์˜๋ฅผ ๋กœ์ปฌ ํƒ€์ดํ•‘์— ๋ณต์‚ฌํ–ˆ์„ ๋•Œ ์•Œ์•˜์ง€ ๋งŒ ๊ตฌํ˜„ ๋œ ์†”๋ฃจ์…˜์€ ๋‚ด ์ƒ๊ฐ์— ๋งค์šฐ ์žฅํ™ฉํ•ฉ๋‹ˆ๋‹ค. (Typescript ์ „๋ฌธ๊ฐ€๊ฐ€ ์•„๋‹˜) ์ž˜๋ชป๋œ ์ผ์„ํ•˜์ง€ ์•Š๋Š” ํ•œ. axios.create ๋กœ ์ƒ์„ฑ๋œ ๋ณ„๋„์˜ axios ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์ด ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์—:

AxiosClient.interceptors.response.use(
  response => response && response.data,
  error => error && error.response && error.response.data
);

์—ฌ๊ธฐ์„œ response.data ๋Š” ํ•ญ์ƒ ๋‹ค์Œ ํ˜•์‹์„ ๊ฐ–์Šต๋‹ˆ๋‹ค.

export interface APIResponse<T = any> {
  data: T;
  message: string;
  status: boolean;
}

๋‹ค์Œ๊ณผ ๊ฐ™์ด AxiosClient.post ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

AxiosClient.post<EndpointAPIResponse, APIResponse<EndpointAPIResponse>>('/endpoint', { someData });

.then ์— ์ ์ ˆํ•œ ์œ ํ˜•์„ ๊ฐ–์Šต๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์—ฌ๊ธฐ์—์„œ ๋ญ”๊ฐ€ ์ž˜๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๊นŒ, ์•„๋‹ˆ๋ฉด ์ •๋ง ์žฅํ™ฉํ•ด์•ผํ•ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ ์˜ˆ์ƒ๋˜๋Š” ์‘๋‹ต ์Šคํ‚ค๋งˆ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ํ›จ์”ฌ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ž‘๋™ํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค.

export interface AxiosInstance<R> {
  <T = any>(config: AxiosRequestConfig): Promise<R<T>>;
  <T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
  defaults: AxiosRequestConfig;
  interceptors: {
    request: AxiosInterceptorManager<AxiosRequestConfig>;
    response: AxiosInterceptorManager<R>;
  };
  getUri(config?: AxiosRequestConfig): string;
  request<T = any>(config: AxiosRequestConfig): Promise<R<T>>;
  get<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
  delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
  head<T = any>(url: string, config?: AxiosRequestConfig): Promise<R<T>>;
  post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R<T>>;
  put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R<T>>;
  patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<R<T>>;
}

export interface AxiosStatic extends AxiosInstance<AxiosResponse> {
  create<T = AxiosResponse>(config?: AxiosRequestConfig): AxiosInstance<T>;
  Cancel: CancelStatic;
  CancelToken: CancelTokenStatic;
  isCancel(value: any): boolean;
  all<T>(values: (T | Promise<T>)[]): Promise<T[]>;
  spread<T, R>(callback: (...args: T[]) => R): (array: T[]) => R;
}

์ œ๋„ค๋ฆญ ์œ ํ˜•์ด ์—†๋Š” axios.create() ๋˜๋Š” axios ์—์„œ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฉ๋‹ˆ๋‹ค.

const AxiosClient = axios.create<APIResponse>({
  // ...
});

๊ทธ๋Ÿฐ ๋‹ค์Œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. AxiosClient.post<string>('/endpoint').then(value => value.data) , value.data has type... T. ๊ฒŒ๋‹ค๊ฐ€ ์œ„์˜ ๋ฒ„์ „์€ ์‹ค์ œ๋กœ node_modules์—์„œ ์ด๋Ÿฌํ•œ ํƒ€์ดํ•‘์„ ๊ต์ฒดํ•˜๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์™„์ „ํžˆ ๋’ค์„ž์ด๊ณ  ์ €๋Š” ์ด์ฒด์ ์ธ ์žฌ๋‚œ์œผ๋กœ ๋๋‚ฉ๋‹ˆ๋‹ค. ๋ˆ„๊ตฌ๋“ ์ง€ ์ด๊ฒƒ์œผ๋กœ ๋‚˜๋ฅผ ๋„์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

ํŽธ์ง‘: ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ์‹์œผ๋กœ ์ œ๋„ค๋ฆญ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค(R์ด ์ œ๋„ค๋ฆญ ์œ ํ˜•์ผ ๋•Œ R<T> ๋Š” ์˜ฌ๋ฐ”๋ฅธ ๊ตฌ๋ฌธ์ด ์•„๋‹ˆ์ง€๋งŒ ์–ด๋–ค ์ด์œ ๋กœ WebStorm์ด ๊ฐ•์กฐ ํ‘œ์‹œ๋˜์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด); https://github.com/Microsoft/TypeScript/issues/1213 ์ด๊ฒƒ์ด ํ•ด๊ฒฐ๋  ๊ฒƒ์ด๋ผ๊ณ  ๊ฐ€์ •ํ•˜์ง€๋งŒ ๊ตฌํ˜„๋˜๋Š”์ง€ ์—ฌ๋ถ€๋Š” ์•Œ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

const request = <T>(options: AxiosRequestConfig) => {
    return axios.request<IResponse<T>>(options).then<T>(response => {
        const data = response.data;
        if (data.c !== '0') {
            return Promise.reject(new Error(data.m || 'error'));
        }
        return data.d;
    });
}

์‚ฌ์šฉ:

request<IApiGetBrandGoodsInfoByIds>({
        method: 'GET',
        url: '/api/a/b',
    });

@zcei ์•„์ง ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜๋‚˜์š”? ๋‹ค์Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

// so I created an axios instance:
const instance = axios.create(someOptions);

// then used interceptors
instance.interceptors.response.use((res) => res.data.data);   // server response will always have 'data'

// then when using the following to make a request
instance.get<string>(someURI);  // suppose server response was {data: 'some message'}

// ^^ the above returns type AxiosPromise<string>. How do I get it to return type Promise<string> instead?

๊ฐ™์€ ๋ฌธ์ œ๊ฐ€ ์žˆ์–ด์„œ ๋ฒ„์ „ 0.19beta๋ฅผ ์„ค์น˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์˜ฌ๋ฐ”๋ฅธ ์œ ํ˜•์„ ๊ตฌ๋ฌธ ๋ถ„์„ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‚ด axios.d.ts AxiosResponse ์žฌ์ •์˜:

import axios from 'axios'

declare module 'axios' {
  export interface AxiosResponse<T = any> extends Promise<T> {}
}

์˜ค ๋‹ˆ์šฐํ”ผ

์ €๋Š” ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ response => response.data ์™€ ๊ฐ™์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ AxiosResponse ๋ž˜ํผ๋ฅผ ์™„์ „ํžˆ ์ œ๊ฑฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋งˆ์นจ๋‚ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋๋‚ฉ๋‹ˆ๋‹ค.

import axios from 'axios'

declare module 'axios' {
  export interface AxiosInstance {
    request<T = any> (config: AxiosRequestConfig): Promise<T>;
    get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    head<T = any>(url: string, config?: AxiosRequestConfig): Promise<T>;
    post<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
    put<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
    patch<T = any>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
  }
}

์‚ฌ์šฉ ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฅด๋Š” ์‚ฌ๋žŒ์ด ์žˆ๋Š” ๊ฒฝ์šฐ:

  1. ์œ ํ˜•์„ ์–ด๋”˜๊ฐ€์— ์ž‘์„ฑํ•˜์‹ญ์‹œ์˜ค(์˜ˆ: src/types/axios/axios.d.ts ) .
  2. ์˜ˆ๋ฅผ ๋“ค์–ด tsconfig.json ์„ ์—…๋ฐ์ดํŠธํ•˜์‹ญ์‹œ์˜ค.
{
  "compilerOptions": {
    "typeRoots": [
        "./node_modules/@types",
        "./src/types/",
    ]
  }
}

์ด๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

Api.boards.createBoard = jest.fn((name:string) => {
      const mockBoardResult = {
        created_on: mockBoardData.date,
        name,
        threads: [],
        updated_on: mockBoardData.date,
        _id: mockBoardData._id
      };
      return Promise.resolve({data:mockBoardResult}) as Promise<AxiosResponse<any>>
    });

์žฌ์ •์˜ํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ•

import * as axios from 'axios'

declare module 'axios' {
  interface AxiosInstance {
    (config: AxiosRequestConfig): Promise<any>
  }
}

์ธํ„ฐ์…‰ํ„ฐ ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ AxiosResponse ์— ์†์„ฑ์„ ์ถ”๊ฐ€ํ•ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์ธํ„ฐ์…‰ํ„ฐ๋ฅผ ๊บผ๋‚ผ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

// @axios-exts/add-foo-to-resp
declare module 'axios' {
  interface AxiosResponse<T = any> {
    foo: string
  }
}
const addFooToResp = (res: AxiosResponse) => {
  res.foo = 'bar'
  return res
}
export default addFooToResp
// Your Project
import axios from 'axios'
import addFooToResp from '@axios-exts/add-foo-to-resp'

var id = axios.interceptors.response.use(addFooToResp)

axios.get('xx').then(res => {
  // have type defined
  // because we use `declare module 'axios'` ts can infer type
  console.log(res.foo)
})

// but if then eject?
axios.interceptors.response.eject(id)
axios.get('xx').then(res => {
  // also have type defined, it's maybe not reasonable
  console.log(res.foo)
})

์šฐ๋ฆฌ๋Š” ์™œ typescript๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ? ์šฐ๋ฆฌ ํ”„๋กœ์ ํŠธ๊ฐ€ ์•ˆ์ „ํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.
์–ธ์  ๊ฐ€ ์šฐ๋ฆฌ๊ฐ€ ๊ธฐ๋ณธ ์œ ํ‹ธ๋ฆฌํ‹ฐ์—์„œ ์†์„ฑ์„ ์ œ๊ฑฐํ•œ๋‹ค๋ฉด, ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์„ ์ฐธ์กฐํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์˜ค๋ฅ˜๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ๋ฅผ ์›ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์šฐ๋ฆฌ๋Š” ์ธํ„ฐ์…‰ํ„ฐ ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ AxiosResponse ์— ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์œ ํ˜• ์œ ์ถ”๋ฅผ ๊ฐ–๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์ธํ„ฐ์…‰ํ„ฐ๊ฐ€ ๊บผ์งˆ ๋•Œ ์œ ํ˜• ์œ ์ถ”๋ฅผ ์—…๋ฐ์ดํŠธํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•  ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋ชจ์ˆœ๋ฉ๋‹ˆ๋‹ค.

axios๊ฐ€ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•Œ๋ ค์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
์ธํ„ฐ์…‰ํ„ฐ๋Š” AxiosResponse ์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š๋Š” ๊ฒƒ์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. AxiosResponse ์†์„ฑ์„ ํ™•์žฅํ•˜๊ณ  ์œ ํ˜• ์ถ”๋ก ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด 'ํ”Œ๋Ÿฌ๊ทธ์ธ'์„ ์ข‹์•„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

// @axios-exts/add-foo-to-resp
declare module 'axios' {
  interface AxiosResponse<T = any> {
    foo: string
  }
}
const addFooToResp = (res: AxiosResponse) => {
  res.foo = 'bar'
  return res
}
export default (axios) => {
  axios.interceptors.response.use(addFooToResp)
}
// Your Project
import axios from 'axios'
import addFooToResp from '@axios-exts/add-foo-to-resp'

addFooToResp(axios)

100% ์•ˆ์ „์€ ์•„๋‹ˆ์ง€๋งŒ ๊ทธ๋ƒฅ axios.interceptors.response.use ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ๋ณด๋‹ค ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค

๊ทธ๋ฆฌ๊ณ  ์ €๋Š” axios desgin ํ”Œ๋Ÿฌ๊ทธ์ธ ์‹œ์Šคํ…œ์„ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ์ด์ œ ์šฐ๋ฆฌ๋Š” ํ•ญ์ƒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณด์ž…๋‹ˆ๋‹ค.

import axios from 'axios'
import wrapper from 'axios-cache-plugin'

let http = wrapper(axios, {
  maxCacheSize: 15
})
export default http

wrapper ์™€ ๊ฐ™์ด ํ”Œ๋Ÿฌ๊ทธ์ธ์„ axios์— ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ํ”Œ๋Ÿฌ๊ทธ์ธ์—๋Š” ๊ณตํ†ต ๊ทœ์น™์ด ์—†์œผ๋ฉฐ ์ถฉ๋ถ„ํžˆ ์šฐ์•„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” ์ข‹์•„ํ•ด์•ผํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•œ๋‹ค

import axios from 'axios'
import axiosCache from 'axios-cache-plugin'

axios.use(axiosCache, {
  // some options
})
export axios
// axios-cache-plugin
export default (axios) => {}
// or
export default {
  install(axios){}
}
// like Vue.use for Vue.js

axios.request<T>(...args) ์Šคํƒ€์ผ ์ •์˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๋ฐฐ์—ด์˜ ๋งˆ์ง€๋ง‰ ์‘๋‹ต ์ธํ„ฐ์…‰ํ„ฐ๋Š” ์•”์‹œ์ ์œผ๋กœ (currentResponse: any) => T ์™€ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ data ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฝ์šฐ:

interface ServerResponse {
  data: ServerData
}

interface ServerData {
  foo: string
  bar: number
}

๊ทธ๋Ÿฌ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

axios.request<ServerData>({
  url: 'https://example.com/path/to/data',
  transformResponse: (r: ServerResponse) => r.data
}).then((response) => {
  // `response` is of type `AxiosResponse<ServerData>`
  const { data } = response
  // `data` is of type ServerData, correctly inferred
})

Pls๋Š” tsx๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Axios ์š”์ฒญ์— ํ—ค๋” ๋ฐ ๊ตฌ์„ฑ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@MoZiadAlhafez

declare module 'axios' {
  interface AxiosRequestConfig {
    useCache: boolean
  }
}

๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๊ถŒ์žฅ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

๊ธด ์ด์•ผ๊ธฐ์ง€๋งŒ #1605์—์„œ ํ•ด๊ฒฐ๋œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. https://github.com/axios/axios/issues/1510#issuecomment -396894600์„ ์ฐธ์กฐํ•˜์„ธ์š”.

๋‚ด๊ฐ€ ๋ญ”๊ฐ€๋ฅผ ์ž˜๋ชป ์ดํ•ดํ–ˆ๋‹ค๋ฉด ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ์ƒˆ ๋ฌธ์ œ๋ฅผ ์—ฌ๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌ ํ•ด์š”.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰