TypeScriptでbool値に"|="を用いたところエラーが発生し、JavaScriptでもbool値に対してビットを操作するタイプの代入演算子を実行すると数値にキャストされていることを知りました。
TypeScript
1let x = false; 2x |= true; // エラー
JavaScript
1let x = false; // x = false 2x |= true; // x = 1
JavaScriptなら数値にキャストされても使う分にはそこまで問題ありませんが、前述の通りTypeScriptではエラーになってしまいます。
もちろん明示的にキャストすればTypeScriptでも使えるのですが、多くの条件に対して論理和や論理積を連続して計算したい場合、毎回キャストするのは面倒に感じます。
かと言って左辺を"x=true"の代わりに"x=1"のように書くのも可読性を下げるような気がしますし、比較する右辺はbool値であることが多いと思うので、やはりキャストは避けられません。
この操作を行いたいときはどのように書くのがスマートでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答3件
0
ベストアンサー
こんにちは
2つの booleanである x
と y
があったときに、ビットごとのOR |
ではなく論理OR ||
にも代入演算子があって、
x ||= y
と書くことができて、質問者様の意図しているような代入演算をしてくれたらいいなと思うときが、確かに時々ありますね。ですがこれは代入演算子の一覧
- MDN: 代入演算子
に無く、SyntaxErrorになってしまうので、
TypeScript
1x = x || y
としておくところかなと思います。
以上参考になれば幸いです。
投稿2019/07/13 02:00
編集2019/07/13 02:18総合スコア9058
0
ビット演算子
JavaScript
1let x = false; // x = false 2x |= true; // x = 1
ビット演算子は Number 型の値を返す処理なので、Boolean 型が代入されるコードに違和感を覚えてしまいます(可読性が低いと感じられます)。
元の書き方に準ずるなら、下記コードに書き換えられますが、
JavaScript
1x = x | true;
いずれにしても、Number 型の値が入る問題があります。
ビットを使うなら、私はむしろ、1と0でフラグ管理した方が分かりやすいと感じます。
代入演算子
ご質問の状況なら、私は下記コードを書きます。
JavaScript
1x = true;
結果は同じはずですが、短絡評価に意義があるのなら、
JavaScript
1if (!x) x = true;
と書きます。
配列の各要素に対して順番に論理和
コメントよりコードを引用します。
JavaScript
1x = false; 2for(let i=0; i<10; ++i){ 3x |= isTrue(data[i]); 4}
このコードの場合、
isTrue(data[i])
を実行する- x が truthy なら、代入値は必ず 1
x が falsy なら、isTrue() の返り値であるBoolean値を Number 型に変換した値 (1 or 0)
となるわけですが、x が truthy であっても、isTrue() が必ず呼び出されてしまうという問題があります。
ですので、私なら前述の通り、if
文を使います。
JavaScript
1'use strict'; 2function isTrue (number) { 3 return number < 100; 4} 5 6function sample1 (data) { 7 let x = false; 8 9 for (let i = 0; i < 10; ++i) { 10 x |= isTrue(data[i]); 11 } 12 13 return x; 14} 15 16function sample2 (data) { 17 let x = false; 18 19 for (let i = 0; i < 10; ++i) { 20 if (!x) x = isTrue(data[i]); 21 } 22 23 return x; 24} 25 26 27function test (args, fn1, fn2) { 28 const result1 = fn1(args), result2 = fn2(args); 29 console.log(result1, result2); 30} 31 32test([1,2,3,100], sample1, sample2); // 1 true 33test([100,101,102], sample1, sample2); // 0 false
「break
文を使えば、論理和さえ不要」という考え方もありますが、そこは「別の処理の関係でbreak出来ない」という事にしておきます。
ビット列
今回の命題にはオーバースペックですが、ビット列を利用すると、各要素に対応する flag
を一つの変数で管理することが出来ます。
JavaScript
1function sample3 (data) { 2 let x = 0; 3 4 for (let i = 0; i < 10; ++i) { 5 x += isTrue(data[i]) * Math.pow(2, i); 6 } 7 8 return x; 9} 10 11const flags = sample3([100,2,103,4]); 12 13console.log(flags.toString(2)); // 1010
今回の命題としては、
JavaScript
1flags !== 0
が変数 x
に期待される値という事になります。
加算演算子
ビット列と同じ理屈で「論理和」を「加算」に置き換える方法もあります。
JavaScript
1for (let i = 0; i < 10; ++i) { 2 x += isTrue(data[i]); 3}
isTrue が Boolean 値を返すなら、x
に加算されるのは 0 or 1 です。
x には各要素が truthy だった数が代入され、値が 0 でなければ、論理和が成立している事になります。
※こちらも「無駄にisTrueが実行されてしまう」という問題があるので、論理和だけが必要であれば、if
文を私は使います。
Re: brsice さん
投稿2019/07/13 06:46
編集2019/07/13 09:46総合スコア18194
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
どうしても特定の型が必要という状況でなければ、let x: any = true;
と型付けを放棄してしまうのも1つの選択肢かもしれません。
投稿2019/07/13 04:18
総合スコア146550
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/07/13 07:09
2019/07/13 07:43
2019/07/13 08:52