質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

0回答

947閲覧

【Vue3】res.headersの返り値の型を指定する方法について

yuito_syz

総合スコア4

Vue.js

Vue.jsは、Webアプリケーションのインターフェースを構築するためのオープンソースJavaScriptフレームワークです。

Vue CLI

Vue CLIは、Vue.jsでアプリケーション開発を行うためのコマンドラインインタフェース(CLI)に基づいた開発ツールです。インタラクティブなプロジェクトの雛形や設定なしで使用できるプロトタイプの作成など、さまざまな機能が用意されています。

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2022/02/03 01:11

前提・実現したいこと

バックエンドはRails、フロントエンドはVueでポートフォリオを作成しています。
フロント側のログイン機能を実装中にエラーメッセージが発生しました。
自前で作成したAuthHeadersのデータ型(後術します)とaxios由来のAxiosResponseHeadesのデータ型が異なるのが原因だと予想しています。
AxiosResponseの返り値は原則anyになります(axios/index.d.ts at master · axios/axios, 130行目export interface AxiosResponse...を参照)
どのファイルでどのようなコードを書けばエラーが解消するか分からず困っています。また、この機能を実装するにあたって参考にした記事はこちらになります。

使用中の主な言語とフレームワークリンク
Vue3(vue-cli)https://cli.vuejs.org/
axioshttps://github.com/axios/axios
typescripthttps://www.typescriptlang.org/ja/
ファイル構成
src ┣ api ┃ ┣ auth.ts ┃ ┣ client.ts ┃ ┣ post.ts ┃ ┗ user.ts ┣ assets ┃ ┗ logo.png ┣ components ┃ ┣ AppPost.vue ┃ ┣ HelloWorld.vue ┃ ┗ NavBar.vue ┣ router ┃ ┣ authGuard.ts ┃ ┗ index.ts ┣ state ┃ ┣ global-state.ts ┃ ┗ use-state.ts ┣ types ┃ ┣ auth.ts ┃ ┣ current_otp.ts ┃ ┣ post.ts ┃ ┗ user.ts ┣ utils ┃ ┗ auth-data.ts ┣ views ┃ ┣ About.vue ┃ ┣ Account.vue ┃ ┣ Home.vue ┃ ┣ Login.vue ┃ ┣ NewPost.vue ┃ ┗ Post.vue ┣ App.vue ┣ main.ts ┗ shims-vue.d.ts

発生している問題・エラーメッセージ

型 'AxiosResponseHeaders' の引数を型 'AuthHeaders' のパラメーターに割り当てることはできません。 型 'AxiosResponseHeaders' には 型 'AuthHeaders' からの次のプロパティがありません: 'access-token', 'uid', 'client', 'expiry', 'Content-Type'ts(2345) (property) AxiosResponse<User, any>.headers: AxiosResponseHeaders

spa-front/src/api/auth.ts(後述します)
のLoginにおいてsetAuthDataFromResponse(res.headers)でエラーが発生しています。

typescript

1export const login = async (email: string, password: string, otp_code: string) => { 2 return await Client.post<User>('/auth/sign_in', { email, password, otp_code}) 3 .then((res: AxiosResponse<User>) => { 4 setAuthDataFromResponse(res.headers) //ここでエラーが発生 5 return res 6 }) 7 .catch((err: AxiosError) => { 8 return err.response 9 }) 10}

該当のソースコード

  • spa-front/src/api/auth.ts

typescript

1import Client from '@/api/client' 2import { User } from '@/types/user' 3import { 4 getAuthDataFromStorage, 5 removeAuthDataFromStorage, 6 setAuthDataFromResponse 7} from '@/utils/auth-data' 8import { AxiosResponse, AxiosError } from 'axios' 9 10export const login = async (email: string, password: string, otp_code: string) => { 11 return await Client.post<User>('/auth/sign_in', { email, password, otp_code}) 12 .then((res: AxiosResponse<User>) => { 13 setAuthDataFromResponse(res.headers) 14 return res 15 }) 16 .catch((err: AxiosError) => { 17 return err.response 18 }) 19} 20 21export const logout = async () => { 22 return await Client.delete('/auth/sign_out', { headers: getAuthDataFromStorage() }) 23 .then(() => { 24 removeAuthDataFromStorage() 25 }) 26} 27 28export const validateToken = async () => { 29 return await Client.get('/auth/validate_token', { headers: getAuthDataFromStorage() }) 30 .then((response) => { 31 setAuthDataFromResponse(response.headers) 32 return response.data 33 }) 34}
  • spa-front/src/api/client.ts

ts

1import axios from 'axios' 2 3export default axios.create({ 4 baseURL: process.env.VUE_APP_API_BASE 5})
  • spa-front/src/types/user.ts

ts

1export type User = { 2 allow_password_change: boolean; 3 email: string; 4 id: string; 5 image: string | null; 6 nickname: string; 7 provider: string; 8 uid: string; 9 otp_required_for_login: boolean; 10}
  • spa-front/src/utils/auth-data.ts

ts

1import { AuthHeaders } from '@/types/auth' 2 3export const getAuthDataFromStorage = (): AuthHeaders => { 4 return { 5 'access-token': localStorage.getItem('access-token'), 6 'client': localStorage.getItem('client'), 7 'expiry': localStorage.getItem('expiry'), 8 'uid': localStorage.getItem('uid'), 9 'Content-Type': 'application/json' 10 } 11} 12 13export const setAuthDataFromResponse = (authData: AuthHeaders): void => { 14 if (authData['access-token'] && authData['client'] && authData['uid'] && authData['expiry']) { 15 localStorage.setItem('access-token', authData['access-token']) 16 localStorage.setItem('client', authData['client']) 17 localStorage.setItem('uid', authData['uid']) 18 localStorage.setItem('expiry', authData['expiry']) 19 } 20} 21 22export const removeAuthDataFromStorage = (): void => { 23 localStorage.removeItem('access-token') 24 localStorage.removeItem('client') 25 localStorage.removeItem('uid') 26 localStorage.removeItem('expiry') 27} 28 29export const getAuthDataFromStorageWithFormData = (): AuthHeaders => { 30 return { 31 'access-token': localStorage.getItem('access-token'), 32 client: localStorage.getItem('client'), 33 expiry: localStorage.getItem('expiry'), 34 uid: localStorage.getItem('uid'), 35 'Content-Type': 'multipart/form-data' 36 } 37}
  • spa-front/src/types/auth.ts

ts

1export type AuthHeaders = { 2 'access-token': string | null; 3 'uid': string | null; 4 'client': string | null; 5 'expiry': string | null; 6 'Content-Type': string; 7} 8 9export type AccessToken = Pick<AuthHeaders, 'access-token'>

試したこと&解決策候補

  • src/types/auth.tsやsrc/types/user.tsでデータ型を指定する 
  • src/utils/auth-data.tsにコードを追加する

補足情報(FW/ツールのバージョンなど)

$ npm list spa-front@0.1.0 ~/portfolio/spa-front ├── @chenfengyuan/vue-qrcode@2.0.0-rc.1 ├── @typescript-eslint/eslint-plugin@4.33.0 ├── @typescript-eslint/parser@4.33.0 ├── @vue/cli-plugin-babel@4.5.15 ├── @vue/cli-plugin-eslint@4.5.15 ├── @vue/cli-plugin-router@4.5.15 ├── @vue/cli-plugin-typescript@4.5.15 ├── @vue/cli-service@4.5.15 ├── @vue/compiler-sfc@3.2.29 ├── @vue/eslint-config-standard@5.1.2 ├── @vue/eslint-config-typescript@7.0.0 ├── autoprefixer@9.8.6 ├── axios@0.25.0 ├── core-js@3.20.3 ├── eslint-plugin-import@2.25.4 ├── eslint-plugin-node@11.1.0 ├── eslint-plugin-promise@4.3.1 ├── eslint-plugin-standard@4.1.0 ├── eslint-plugin-vue@7.20.0 ├── eslint@6.8.0 ├── postcss@7.0.35 ├── qrcode@1.5.0 ├── sass-loader@8.0.2 ├── sass@1.49.0 ├── tailwindcss@npm:@tailwindcss/postcss7-compat@2.0.3 ├── typescript@4.1.6 ├── vue-router@4.0.12 └── vue@3.2.29
  • package.json
{ "name": "spa-front", "version": "0.1.0", "private": true, "scripts": { "serve": "vue-cli-service serve", "build": "vue-cli-service build", "lint": "vue-cli-service lint" }, "dependencies": { "@chenfengyuan/vue-qrcode": "^2.0.0-rc.1", "axios": "^0.25.0", "core-js": "^3.6.5", "qrcode": "^1.5.0", "vue": "^3.2.29", "vue-router": "^4.0.0-0" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^4.18.0", "@typescript-eslint/parser": "^4.18.0", "@vue/cli-plugin-babel": "~4.5.0", "@vue/cli-plugin-eslint": "~4.5.0", "@vue/cli-plugin-router": "~4.5.0", "@vue/cli-plugin-typescript": "~4.5.0", "@vue/cli-service": "~4.5.0", "@vue/compiler-sfc": "^3.0.0", "@vue/eslint-config-standard": "^5.1.2", "@vue/eslint-config-typescript": "^7.0.0", "autoprefixer": "^9.8.6", "eslint": "^6.7.2", "eslint-plugin-import": "^2.20.2", "eslint-plugin-node": "^11.1.0", "eslint-plugin-promise": "^4.2.1", "eslint-plugin-standard": "^4.0.0", "eslint-plugin-vue": "^7.0.0", "postcss": "^7.0.35", "sass": "^1.26.5", "sass-loader": "^8.0.2", "tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.3", "typescript": "~4.1.5" } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだ回答がついていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問