Inspect the fixed example
The paragraph supplies data-enabled="false" and data-line-count="3". Compare raw values, Boolean conversion, an explicit true check and numeric conversion.
<style>html{font-size:16px}body{margin:12px;font:1rem/1.5 system-ui,sans-serif;color:#17332d;background:#fff}p{overflow-wrap:anywhere}output{display:block;margin-block:12px;overflow-wrap:anywhere;white-space:pre-wrap}button,input{font:inherit;max-width:100%;box-sizing:border-box}button{margin:4px;padding:8px}label{display:block;margin-block:8px}button:focus-visible,input:focus-visible{outline:3px solid #23715d;outline-offset:2px}ul{padding-inline-start:24px}li{overflow-wrap:anywhere}.highlight{border:2px solid green}</style>
<p id="note" data-enabled="false" data-line-count="3">Workshop note</p><output id="result"></output>
<script>const data=document.querySelector('#note').dataset;const result={raw:data.enabled,type:typeof data.enabled,truthy:Boolean(data.enabled),explicit:data.enabled==='true',count:Number(data.lineCount)};
document.querySelector('#result').textContent=JSON.stringify(result);
console.log(JSON.stringify(result));
</script>{"raw":"false","type":"string","truthy":true,"explicit":false,"count":3}| Inspection | Supplied input or action | Result |
|---|---|---|
| enabled | "false" | type: string; truthy: true |
| Explicit flag rule | enabled==='true' | false |
| lineCount | "3" | Number: 3 |
Follow the native mechanism
dataset exposes attribute values as strings and maps data-line-count to lineCount. A nonempty string such as false is truthy. Comparing with the literal true string implements this fixture’s flag rule; Number("3") converts this fixed valid input, not arbitrary data validation. Missing attributes yield undefined.
Compare the material alternative
Boolean is not a parser for the words true and false. Here a nonempty invalid number produces NaN after Number conversion; String keeps NaN visible rather than allowing JSON to turn it into null.
<style>html{font-size:16px}body{margin:12px;font:1rem/1.5 system-ui,sans-serif;color:#17332d;background:#fff}p{overflow-wrap:anywhere}output{display:block;margin-block:12px;overflow-wrap:anywhere;white-space:pre-wrap}button,input{font:inherit;max-width:100%;box-sizing:border-box}button{margin:4px;padding:8px}label{display:block;margin-block:8px}button:focus-visible,input:focus-visible{outline:3px solid #23715d;outline-offset:2px}ul{padding-inline-start:24px}li{overflow-wrap:anywhere}.highlight{border:2px solid green}</style>
<p id="note" data-enabled="false" data-line-count="three">Workshop note</p><output id="result"></output>
<script>const data=document.querySelector('#note').dataset;const result={enabled:Boolean(data.enabled),numeric:String(Number(data.lineCount))};
document.querySelector('#result').textContent=JSON.stringify(result);
console.log(JSON.stringify(result));
</script>{"enabled":true,"numeric":"NaN"}Work the boundary
What is the difference between a missing data-enabled and an explicitly empty one?
Show the worked answer
Missing gives undefined and no attribute; empty gives a present attribute and the empty string. Both Boolean conversions are false, so that conversion alone loses the distinction.
<style>html{font-size:16px}body{margin:12px;font:1rem/1.5 system-ui,sans-serif;color:#17332d;background:#fff}p{overflow-wrap:anywhere}output{display:block;margin-block:12px;overflow-wrap:anywhere;white-space:pre-wrap}button,input{font:inherit;max-width:100%;box-sizing:border-box}button{margin:4px;padding:8px}label{display:block;margin-block:8px}button:focus-visible,input:focus-visible{outline:3px solid #23715d;outline-offset:2px}ul{padding-inline-start:24px}li{overflow-wrap:anywhere}.highlight{border:2px solid green}</style>
<p id="missing">Missing attribute</p><p id="empty" data-enabled="">Empty attribute</p><output id="result"></output>
<script>const missing=document.querySelector('#missing'),empty=document.querySelector('#empty');const result={missingType:typeof missing.dataset.enabled,missingPresent:missing.hasAttribute('data-enabled'),empty:empty.dataset.enabled,emptyPresent:empty.hasAttribute('data-enabled'),truthy:[Boolean(missing.dataset.enabled),Boolean(empty.dataset.enabled)]};
document.querySelector('#result').textContent=JSON.stringify(result);
console.log(JSON.stringify(result));
</script>{"missingType":"undefined","missingPresent":false,"empty":"","emptyPresent":true,"truthy":[false,false]}