📝 TypeScript と ioredis のソースコード
TypeScript で Redis 使いたい場合は ioredis で書いてこんな感じのコードになる(ちなみに ES6 で Promise 導入されてからはレガシーなままの node_redis 使ってる人も少ないと思う)。
sample.ts
import * as Redis from 'ioredis';
(async () => {
const redis = new Redis();
const pong = await redis.ping(); // => PONG
})();
このコードは正しく動く。
🌡 Jest のテストコード
ところが Jest でテスト書いたら実行できなくてハマってしまった。
sample.spec.ts
import * as Redis from 'ioredis';
describe('Redis', () => {
it('should be reply pong', async () => {
const redis = new Redis();
const pong = await redis.ping();
redis.disconnect();
expect(pong).toBe('PONG');
})
});
.ts
ファイルを直接実行するので ts-jest を入れている。
$ jest
TypeError: Redis is not a constructor
4 |
5 | it('should be reply pong', async () => {
> 6 | const redis = new Redis();
| ^
7 | const pong = await redis.ping();
8 | redis.disconnect();
9 | expect(pong).toBe('PONG');
at Object.it (src/sample.spec.ts:6:19)
TypeError: Redis is not a constructor
😵 なんでやねん
import * as Redis from 'ioredis';
const redis = new Redis();
のところでコンストラクタじゃないと言われる。書き方は正しいのに。
import Redis from 'ioredis';
に直したら動いた。間違ってるのに。
まぁそんなこともあるのかな、と思って現実逃避したりもしたけど、テストファイルをコンパイルして .js
ファイルにしてテスト実行してみるとエラーになる。
TypeError: ioredis_1.default is not a constructor
4 | describe('Redis', () => {
5 | it('should be return pong', async () => {
> 6 | const redis = new ioredis_1.default();
| ^
7 | const pong = await redis.ping();
8 | redis.disconnect();
9 | expect(pong).toBe('PONG');
at Object.it (dist/sample.spec.js:6:23)
TypeError: ioredis_1.default is not a constructor
やっぱり間違ってるいるわけだ。
👾 原因
ts-jest
にバグがあったようだ。でも Issue からは見つけられなかった。
"devDependencies": {
"@types/ioredis": "^4.0.3",
"@types/jest": "^23.3.5",
"jest": "^23.6.0",
"ts-jest": "^21.2.4",
"typescript": "^3.1.3"
}
yarn upgrade --latest ts-jest
して 23.10.4
にしたら治った。