エラー時の状況
TypeORMの0.3系でfindOne
メソッドの使い方ではまったので備忘録。
エラーは以下の通り
src/todo/todo.service.ts:20:46 - error TS2559: Type 'string' has no properties in common with type 'FindOneOptions<Todo>'.
20 return await this.todoRepository.findOne(id);
~~
問題のコード。
todo.service.ts
@Injectable()
export class TodoService {
constructor(
@InjectRepository(Todo)
private readonly todoRepository: Repository<Todo>,
) {}
async findOne(id: string): Promise<Todo> {
return await this.todoRepository.findOne(id);
}
}
環境
package.json
{
// ...
"dependencies": {
"@nestjs/common": "^8.0.0",
"@nestjs/config": "^2.2.0",
"@nestjs/core": "^8.0.0",
"@nestjs/mapped-types": "*",
"@nestjs/platform-express": "^8.0.0",
"@nestjs/typeorm": "^9.0.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.13.2",
"pg": "^8.8.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0",
"typeorm": "^0.3.9"
},
"devDependencies": {
"@nestjs/cli": "^8.0.0",
"@nestjs/schematics": "^8.0.0",
"@nestjs/testing": "^8.0.0",
"@types/express": "^4.17.13",
"@types/jest": "27.5.0",
"@types/node": "^16.0.0",
"@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^8.0.1",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-prettier": "^4.0.0",
"jest": "28.0.3",
"prettier": "^2.3.2",
"source-map-support": "^0.5.20",
"supertest": "^6.1.3",
"ts-jest": "28.0.1",
"ts-loader": "^9.2.3",
"ts-node": "^10.0.0",
"tsconfig-paths": "4.0.0",
"typescript": "^4.3.5"
},
// ...
}
エラーの原因の仮説
パラメータの渡し方もしくは、型になにかしら問題がありそう。
- TypeORMの
findOne
メソッドの引数に渡すパラメーターが間違っている? - 型定義が間違っている?
仮説を検証してみる
エラーにも書いてあるように、パラメーターの渡し方が悪そうなので、一旦FindOneOptions<T>
を見てみる。
FindOneOptions<T>
にはid
は渡せなさそう…
TypeORMの公式ドキュメントでfindOne
メソッドについて調べている。
すると…
findOne(id) signature was dropped. Use following syntax instead:
const user = await userRepository.findOneBy({ id: id // where id is your column name })
「findOne(id)
は使えなくなったよ。代わりにfindOneBy
を使ってね。」的な事が書いてありました。
公式ドキュメントの通りコードを修正する
以下のようにコードを修正すると…
エラーが解消されました!
修正したAPIにリクエストを送ると、問題なく動作しました!
todo.service.ts
@Injectable()
export class TodoService {
constructor(
@InjectRepository(Todo)
private readonly todoRepository: Repository<Todo>,
) {}
async findOne(id: string): Promise<Todo> {
- return await this.todoRepository.findOne(id);
+ return await this.todoRepository.findOneBy({ id });
}
}
🎉🎉🎉
原因
このエラーの原因は以下の通りです。
-
findOne
メソッドに渡すパラメータのかたちが間違っていた - そもそも、TypeORM
0.3.0
以降から、findOne
メソッドが廃止されていた- NestJS
8.0.0
でCRUD generatornest g resource <resource-name>
を使うと、自動的にfindOne
メソッドを使うようになっている
- NestJS
Source and Thanks