setTimeout is async, i.e. it's non-blocking and will never work like this. The for loop would race ahead and make 100 setTimeouts all at once, then they'd all fire at more or less the same time, not 100 ms after each other.
Also, Endy0816 is right that the null cannot be used. You do need to call a function, or have a string that evaluates to code, or use a lambda (arrow function).
This works:
<html>
<head></head>
<body>
<p>Test:</p>
<script>
let i = 100;
setTimeout(ShowDot, 100);
function ShowDot() {
document.write(".");
if (i-- > 1) {
setTimeout(ShowDot, 100);
}
}
</script>
</body>
</html>
If you want the first dot to show immediately, just replace the first:
setTimeout(ShowDot, 100);
With:
ShowDot();
See: https://developer.mozilla.org/en-US/docs/Web/API/setTimeout