はじめに
- 「JavaScript における Null ガードは何なのか」を調べていく内に "Null合体演算子" に行き着いたものの、どうも特殊な挙動をすると分かったので調査
Null合体演算子 (??
) は「"falsy な値"を偽値と評価する」わけでは無い
- "Null合体演算子"は"論理 OR (
||
,||=
) 演算子"とは異なる動作をする
Null合体演算子 |
Null と undefined だけ を偽値とみなす |
論理 OR 演算子 | falsy な値を偽値とみなす |
- Null合体演算子の場合だと、
false
を評価しても偽値と見なされない - Null合体演算子の場合だと、falsy な値である
0
''(空文字)
を評価しても偽値と見なされないNull
とundefined
だけを偽値とみなす
コード
sample.ts
interface DownloadedUserData {
id: number;
name: string;
age?: number;
hasRole?: boolean;
gender?: string;
grade?: number;
}
const downloadedUserData: DownloadedUserData = {
id: 1,
name: 'Alice',
// age: 20,
hasRole: false,
gender: '',
grade: 0,
};
// Optional chaining
console.log(downloadedUserData.age?.toString());
// Nullish coalescing operator
let userAge = downloadedUserData.age ?? 'no-user';
console.log(userAge); //=> no-user
let hasRole = downloadedUserData.hasRole ?? 'no-user';
console.log(hasRole); //=> no-user
//////////////////////////////////
/* OR演算子との違い
* null、undefinedは同じく検知できる
*/
userAge = downloadedUserData.age || 'no-user';
console.log(userAge);
/* ただし 空文字 や 0 の検知には違いが出る
* `||` は falsy な値を検知する
* `??` は null か undefined だけを検知する
*/
// false
let userHasRole: (boolean | string) = downloadedUserData.hasRole || 'no-role';
console.log(userHasRole); //=> no-role
userHasRole = downloadedUserData.hasRole ?? 'no-role';
console.log(userHasRole); //=> false
// ''(空文字)
let userGender = downloadedUserData.gender || 'no-gender';
console.log(userGender); //=> no-gender
userGender = downloadedUserData.gender ?? 'no-gender';
console.log(userGender); //=> ''
// 0
let userGrade = downloadedUserData.grade || 'no-grade';
console.log(userGrade); //=> no-grade
userGrade = downloadedUserData.grade ?? 'no-grade';
console.log(userGrade); //=> 0
所感
- 「Ruby の nil ガード」を想像していたため、そもそも Ruby と JavaScript の falsy な値の定義が異なる点から注意が必要だと気づけた
- 「Ruby の nil ガード想定」であるなら
??
は不適切
- 「Ruby の nil ガード想定」であるなら
参考資料