Skip to content

ja_JP: cont_TypeScript に関する備考

Komohachi Fujishiki edited this page Apr 4, 2022 · 1 revision

TypeScript に関する備考

プレースホルダ

SQL を クエリビルダで組み立てる際、使用するプレースホルダは重複してはいけません。

例えば:

query.andWhere(new Brackets(qb => {
	for (const type of ps.fileType) {
		qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type });
	}
}));

のように実装すると、ループ中で type というプレースホルダが 複数回使われてしまうため、不具合を生じます。 したがって、次のように実装する必要があります。

query.andWhere(new Brackets(qb => {
	for (const type of ps.fileType) {
		const i = ps.fileType.indexOf(type);
		qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
	}
}));

TypeORM では null を使用しない

例えば:

const foo = await Foos.findOne({
	bar: Not(null)
});

のような クエリ(barnullではない) は期待通りに動作しません。 したがって、次のように実装する必要があります。

const foo = await Foos.findOne({
	bar: Not(IsNull())
});

SQL での null

SQL を発行する際、パラメータが null になる可能性のある場合は、SQL文を分けて発行する必要があります。

例えば:

query.where('file.folderId = :folderId', { folderId: ps.folderId });

という処理では、 ps.folderIdnull の場合、結果的に file.folderId = null のようなクエリが発行されてしまいます。 これは、正しい SQL ではないので、期待した結果が得られません。 したがって、次のように実装する必要があります。

if (ps.folderId) {
	query.where('file.folderId = :folderId', { folderId: ps.folderId });
} else {
	query.where('file.folderId IS NULL');
}

SQL での [](空の配列)

SQL を発行する際、IN のパラメータが [](空の配列) になる可能性のある場合は、SQL文を分けて発行する必要があります。

例えば:

const users = await Users.find({
	id: In(userIds)
});

という処理では、 userIds[] の場合、結果的に user.id IN () のようなクエリが発行されてしまいます。 これは、正しい SQL ではないので、期待した結果が得られません。 したがって、次のように実装する必要があります。

const users = userIds.length > 0 ? await Users.find({
	id: In(userIds)
}) : [];

SQL での 配列のインデックス

SQL では 配列のインデックス は 1始まり です。 [a, b, c]a にアクセスしたい場合、 [0] ではなく [1] と書きます。

簡素な undefined チェック

データベースからレコードを取得する場合、undefined になる可能性が限りなく低い場合でも、 TypeScript では undefined チェックを行う必要があります。 そこで、簡素な undefined チェックが可能な ensure というユーティリティ関数を用意しています。

例えば:

const user = await Users.findOne(userId);
// この時点で user の型は User | undefined
if (user == null) {
	throw 'missing user';
}
// この時点で user の型は User

という処理で ensure を使うと

const user = await Users.findOne(userId).then(ensure);
// この時点で user の型は User

という実装が可能です。 万が一 undefined だった場合、Promise が Reject され後続の処理は実行されません。

const user = await Users.findOne(userId).then(ensure);
// 万が一 Users.findOne の結果が undefined の場合、ensure でエラーが発生するので
// この行に到達することはありません
// なので、.then(ensure) は
// if (user == null) {
//	throw 'missing user';
// }
// の糖衣構文のような扱いです