事の発端
開発してるWEBアプリケーションで使ってたnpmパッケージが全体的に古くなってきたので、パッケージの更新を行った。
・・・すると、コンパイルが失敗するようになってしまい、アプリケーションが動かなくなってしまった!
問題なったコード
関連箇所のみ抜粋。
{
"dependencies": {
"query-string": "^6.2.0",
},
"devDependencies": {
"@types/query-string": "6.1.0",
}
}
import * as React from 'react';
import { parse } from 'query-string';
class App extends React.Component {
private id: number;
constructor(props: Readonly<{}>) {
super(props);
// ここから問題箇所。
// query-stringというOSSのparseメソッドを使って
// URLのクエリからidのパラメータが数字の文字列なら、変数idを代入する事をしたい
const parsedHash = parse(location.search);
// @types/query-string のバージョンが6.1.1だと、この下の行でコンパイルエラーになる
if (isFinite(parsedHash.id)) {
this.id = Number(parsedHash.id);
}
}
render() {
// 略
}
}
起こった出来事について
原因は「@types/query-string」のバージョンアップでした。
※「@types/」から始まる名前のパッケージについて知らない方はこちらをご覧ください。
6.1.0から6.1.1に更新したことによって、parseメソッドの返り値の型が変わってしまいました。
version | parseの返り値の型 |
---|---|
6.1.0 | any |
6.1.1 | OutputParams(実態は [key: string]: string | string[] | undefined;) |
返り値の型が違うので、parsedHashに結果を代入する時に型推論の結果が変わってしまい、その後の処理の型の整合性が合わなくなってしまった・・・ということでした。
その後、新しい型定義に合うようコードを修正して解決しました。
const parsedHash = parse(location.search);
if (isFinite(Number(parsedHash.id))) {
this.id = Number(parsedHash.id);
}
まとめ
「@types/」から始まる名前のパッケージを更新するときや、自プロダクトで書いた型定義を更新する時はちゃんとコンパイルが通るかを確認しましょう(当たり前なことではありますががが)
「@types/」から始まる名前のパッケージを更新する時に、どんな事が起こる可能性があるのかが想像できてなかったのでいい勉強になりました。
今回の例は「@types/query-string」でしたが、他のパッケージでも起こる可能性はあるので、気をつけましょう。