Bitwise Flags
- What bitwise flags are
- Defining and combining flags in TypeScript and plain JavaScript
- Storing and retrieving the bitmask
- Decoding with a simple loop
- Rewriting that loop using
Array.prototype.reduce
- Pros, cons, and when to use each style
1. Understanding Bitwise Flags
A bitwise flag uses each bit in an integer to represent an on/off value:
- Set a flag:
mask |= FLAG
- Test a flag:
(mask & FLAG) !== 0
- Clear a flag:
mask &= ~FLAG
- Toggle a flag:
mask ^= FLAG
Using shifts (
1 << n
2. Defining Flags
TypeScript
enum ActivityEnum { Kitesurfing = 1 << 0, // 1 (00000001) Hiking = 1 << 1, // 2 (00000010) Cycling = 1 << 2, // 4 (00000100) Fishing = 1 << 3, // 8 (00001000) HuntingDuck = 1 << 4, // 16 (00010000) HuntingDeer = 1 << 5, // 32 (00100000) Running = 1 << 6, // 64 (01000000) Surfing = 1 << 7, // 128 (10000000) }
Plain JavaScript
const ActivityFlags = Object.freeze({ Kitesurfing: 1 << 0, // 1 Hiking: 1 << 1, // 2 Cycling: 1 << 2, // 4 Fishing: 1 << 3, // 8 HuntingDuck: 1 << 4, // 16 HuntingDeer: 1 << 5, // 32 Running: 1 << 6, // 64 Surfing: 1 << 7, // 128 })
let mask = ActivityEnum.Kitesurfing | ActivityEnum.Fishing // mask === 1 | 8 === 9
- Storing & Retrieving
// 1) Read raw string const storedString = localStorage.getItem('activities'); // e.g. "9" or null // 2) Fallback to "0" const stringOrZero = storedString !== null ? storedString : '0'; // 3) Parse to integer const mask = parseInt(stringOrZero, 10); // mask === 9
- Decoding with a Simple Loop
function decodeActivities(mask) { const active = []; for (const [name, bit] of Object.entries(ActivityFlags)) { if ((mask & bit) !== 0) { active.push(name); } } return active; } console.log(decodeActivities(9)); // → ["Kitesurfing", "Fishing"]
- Decoding with reduce
const active = Object .entries(ActivityFlags) .reduce((acc, [name, bit]) => { if ((mask & bit) !== 0) { acc.push(name); } return acc; }, []); console.log(active); // → ["Kitesurfing", "Fishing"]
Or immutably:
const activeImmutable = Object .entries(ActivityFlags) .reduce((acc, [name, bit]) => (mask & bit) !== 0 ? [...acc, name] : acc , []);