テンプレートリテラル
テンプレートリテラルはJavaScriptにおける文字列の表現方法の1つです。バッククォート(`
)を用いて`hello`
のように式を記述します。
テンプレートリテラルは記述中に異なる式を埋め込めることが特徴的です。ドル$
と波括弧{}
を用いて式を埋め込みます。
const familyName = 'Einstein';
const givenName = 'Albert';
// Albert Einstein
const fullName = `${givenName} ${familyNmae}`
上記の例ではテンプレートリテラルを用いてfamilyName
とgivenName
を埋め込んだ文字列fullName
を生成しています。
タグ付きテンプレート
テンプレートリテラルは稀に下記のように利用されることがあります。
tag`${givenName} ${familyNmae}`
tag
という関数に対してテンプレートリテラルを押し付けるような形です。
Next.jsの利用例としてServer Actions内でSQLを呼ぶ例が執筆当時では話題となっていて、そこでも@vercel/postgres
のsql
関数でタグ付きテンプレートを利用しています(話題となっている理由は別のところですが)。
sql`SELECT * FROM posts WHERE likes > ${likes};`
これはテンプレートリテラルのより高度な形式でタグ付きテンプレートと呼ばれます。この形式におけるタグとはtag
やsql
のようなテンプレートリテラル前の関数を指しています。
関数では押し付けられたテンプレートリテラルについて詳細な情報を引数から扱えます。
const analysisTemplateLiterals = (
strings,
...keys
) => {
console.log(strings);
console.log(keys);
};
// ['', ' ', '', raw: Array(3)]
// ['Albert', 'Einstein']
analysisTemplateLiterals`${givenName} ${familyNmae}`;
上記の関数で入力を確認すると、第1引数はテンプレートリテラルの埋め込み単位で分割した文字列が配列で渡されます(raw: Array(3)
については後述)。第2引数以降は残余引数として埋め込んだ式が渡されます。
これらを利用してHTMLエスケープする便利な関数escapeHtml
を作成できます(ここで作成する関数が完全にHTMLエスケープすることは保証しません)。
const escapeHtml = (
strings,
...keys
) => {
const escapedValues = keys.map(key => {
return String(key)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
});
let result = '';
for (let i = 0; i < strings.length; i++) {
result += strings[i];
if (i < escapedValues.length) {
result += escapedValues[i];
}
}
return result;
};
ユーザの入力を元にした値をこれを利用することによってescapeHtml`Hello ${userInput}!`
簡単にHTMLエスケープした文字列として扱えます。
話は戻ってタグが受け取る第1引数にあったraw: Array(3)
について注目します。
以下のようにraw
の部分と比較するようにタグを記述して動作を見ます。
const analysisRaw = (strings) => {
console.log(strings);
console.log(strings.raw);
};
analysisRaw`Good Morning\nGood Evening`
// ['Good Morning\nGood Evening', raw: Array(1)]
// ['Good Morning\\nGood Evening']
const analysisRawFirst = (strings) => {
console.log(strings[0]);
console.log(strings.raw[0]);
};
analysisRawFirst`Good Morning\nGood Evening`
// Good Morning
// Good Evening
// Good Morning\nGood Evening
console
では\n
による改行がされていない元の文字列が出力されました。raw
はこのようにテンプレートリテラルが入力された時の文字列をそのまま持つ配列で、第一引数の配列に対応してそれぞれ格納されています。
このように第1引数はstring
の配列以外にもraw
を持つのでTypeScriptではTemplateStringsArray
として実装されています。
interface TemplateStringsArray extends ReadonlyArray<string> {
readonly raw: readonly string[];
}
さいごに
この記事ではタグ付きテンプレートについて紹介しました。知っていない時にこの表現を見ると理解し難い式ですが、知っていると綺麗にハマるケースも多いので活用できるようになりたいです。