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

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

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

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

TypeScript

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

Q&A

0回答

267閲覧

Factory関数でインスタンス生成時に発生する型エラーを解決したい

tera__

総合スコア4

Vue.js

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

TypeScript

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

0グッド

0クリップ

投稿2019/08/19 16:06

Factory関数でインスタンス生成時に発生する型エラーを解決したい

TypeScriptを使用し、クライアント側からajax操作時、インターフェイスを統一したモジュールを作成しています。
その際以下のエラーメッセージが、エディタ(VSCode)上で表示されます。

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

型 'PostsRepository | UsersRepository' を型 'repositoryTypes[T]' に割り当てることはできません。 型 'PostsRepository' を型 'repositoryTypes[T]' に割り当てることはできません。 型 'PostsRepository' を型 'PostsRepository & UsersRepository' に割り当てることはできません。 型 'PostsRepository' を型 'UsersRepository' に割り当てることはできません。 プロパティ 'all' の型に互換性がありません。 型 '() => Promise<IPostsModel[]>' を型 '() => Promise<IUsersModel[]>' に割り当てることはできません。 型 'Promise<IPostsModel[]>' を型 'Promise<IUsersModel[]>' に割り当てることはできません。 型 'IPostsModel[]' を型 'IUsersModel[]' に割り当てることはできません。 Type 'IPostsModel' is missing the following properties from type 'IUsersModel': age, sex

該当のソースコード

簡易版ですが、作成しているモジュールは以下の構造になっています。

TypeScript

1import axios, { AxiosInstance } from 'axios' 2class Adapter { 3 private request(): AxiosInstance { 4 return axios.create({ 5 baseURL: '/' 6 }) 7 } 8 async get<T, U = void>(endpoint: string, req?: U): Promise<T> { 9 const result = await this.request() 10 .get<T>(endpoint, req) 11 .catch(e => { 12 throw new Error(`${e} at ${endpoint}`) 13 }) 14 return result.data 15 } 16} 17abstract class AbstractRepository<Model, Query> { 18 private adapter: Adapter 19 private rootUri: string 20 constructor(adapter: typeof Adapter, rootUri) { 21 this.rootUri = rootUri 22 this.adapter = new adapter() 23 } 24 public async all() { 25 const result = await this.adapter.get<Model[]>(`${this.rootUri}/`) 26 return result 27 } 28} 29 30export interface IPostsQuery { 31 id?: number 32 name?: string 33} 34 35export interface IPostsModel { 36 id: number 37 name: string 38 title: string 39 context: string 40} 41 42class PostsRepository extends AbstractRepository<IPostsModel, IPostsQuery> { 43 constructor(adapter: typeof Adapter) { 44 const rootUri = 'posts' 45 super(adapter, rootUri) 46 } 47} 48 49interface IUsersQuery { 50 id?: number 51 name?: string 52 age?: string 53} 54 55interface IUsersModel { 56 id: number 57 name: string 58 age: string 59 sex: string 60} 61 62class UsersRepository extends AbstractRepository<IUsersModel, IUsersQuery> { 63 constructor(adapter: typeof Adapter) { 64 const rootUri = 'users' 65 super(adapter, rootUri) 66 } 67} 68 69const repositories = { 70 users: UsersRepository, 71 posts: PostsRepository 72} 73type repositoryTypes = { 74 users: UsersRepository 75 posts: PostsRepository 76} 77function getRepository<T extends keyof repositoryTypes>( 78 name: T 79): repositoryTypes[T] { 80 const result = new repositories[name](Adapter) 81 // この行で前述のエラーメッセージが表示されます 82 return result 83} 84 85const postsRepository = getRepository('users') 86const posts = postsRepository.all() 87

試したこと

tsconfig.jsonの設定変更

baseUrlの値を.から./srcに変更したところエラーメッセージは消えましたが@でのimportがエラーになりました。

getRepository()関数の戻り値型指定変更

盲目的にgetRepository()関数の戻り値型指定を以下のように変更してみました。

diff

1 2function getRepository<T extends keyof repositoryTypes>( 3 name: T 4- ): repositoryTypes[T] { 5+ ): UsersRepository | PostsRepository { 6 const result = new repositories[name](Adapter) 7 return result 8}

エラーメッセージは表示されなくなりましたが、getRepository()関数からの戻り値型がconst postsRepository: UsersRepository | PostsRepositoryとなり、そもそも実現したいことから離れてしまっているので、この方法は選択しませんでした。

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

json

1 2{ 3 "compilerOptions": { 4 "target": "esnext", 5 "module": "esnext", 6 "resolveJsonModule": true, 7 "strict": true, 8 "jsx": "preserve", 9 "jsxFactory": "h", 10 "importHelpers": true, 11 "moduleResolution": "node", 12 "experimentalDecorators": true, 13 "esModuleInterop": true, 14 "allowSyntheticDefaultImports": true, 15 "sourceMap": true, 16 "baseUrl": ".", 17 "strictPropertyInitialization": false, 18 "noImplicitAny": false, 19 "types": [ 20 "webpack-env", 21 "jest", 22 "json-server", 23 "dotenv", 24 "firebase", 25 "@types/node", 26 "@nuxt/vue-app", 27 ], 28 "paths": { 29 "@/*": [ 30 "./src/*" 31 ], 32 "~/*": [ 33 "./src/*" 34 ] 35 }, 36 "lib": [ 37 "esnext", 38 "dom", 39 "dom.iterable", 40 "scripthost" 41 ] 42 }, 43 "include": [ 44 "**/*.ts", 45 "**/*.tsx", 46 "**/*.vue", 47 "test/**/*.ts", 48 "test/**/*.tsx" 49 ], 50 "exclude": [ 51 "node_modules" 52 ] 53} 54

こちらの解決方法をご存知の方がいらっしゃいましたら、お伝えくださると大変助かります。
何卒よろしくお願い致します。

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

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

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

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

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

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

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

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

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問