Static vs dynamic typing

정적·동적 타입

Static checks catch type errors before running; dynamic checks encounter value behavior during execution.

···
html
<div class="visual timing" data-step="0"><div class="visual-head"><strong>CHECK TIMING</strong><i></i></div><div class="visual-scene"><div class="time-row"><b>Static</b><div class="time-track"><span>edit</span><span>check</span><span>run</span><i></i></div></div><div class="time-row"><b>Dynamic</b><div class="time-track"><span>edit</span><span>run</span><span>error</span><i></i></div></div></div><div class="visual-caption"></div><div class="visual-dots"><b></b><b></b><b></b><b></b></div></div>
css
.visual{width:min(95vw,760px);height:min(91vh,330px);padding:clamp(9px,2.5vmin,18px);display:flex;flex-direction:column;gap:clamp(6px,1.7vmin,11px);border:1px solid var(--line);border-radius:13px;background:var(--surface);font:500 clamp(12px,3.4vmin,16px)/1.25 var(--font-sans,-apple-system),sans-serif}
.visual-head{display:flex;align-items:center;justify-content:space-between;gap:8px;min-height:19px;color:var(--accent)}.visual-head strong{font-size:1em}.visual-head i{display:block;width:8px;height:8px;flex:none;border-radius:50%;background:var(--accent);animation:visual-pulse 1.3s infinite}@keyframes visual-pulse{50%{opacity:.25}}
.visual-scene{position:relative;flex:1;min-height:0;overflow:hidden}.visual-caption{min-height:2.4em;display:grid;place-items:center;text-align:center}.visual-dots{display:flex;justify-content:center;gap:4px}.visual-dots b{display:block;width:15px;height:3px;border-radius:3px;background:var(--line)}.visual-dots b.on{background:var(--accent)}
.visual-scene *{box-sizing:border-box}.visual-scene .mono{font-family:ui-monospace,monospace}.visual-scene .muted{color:var(--muted)}.visual-scene .lit{border-color:var(--accent)!important;background:color-mix(in srgb,var(--accent) 14%,var(--surface))!important;color:var(--fg)!important}
.timing .visual-scene{display:flex;flex-direction:column;justify-content:center;gap:17px}.time-row{display:flex;gap:7px;align-items:center}.time-row b{width:58px;flex:none}.time-track{position:relative;flex:1;display:flex;justify-content:space-between;border-top:2px solid var(--line);padding-top:8px}.time-track span{font-size:12px}.time-track i{position:absolute;width:13px;height:13px;border-radius:50%;background:var(--accent);top:-8px;left:0;transition:left .4s}.timing[data-step="1"] .time-row:first-child i{left:47%}.timing[data-step="2"] .time-row:nth-child(2) i{left:47%}.timing[data-step="3"] .time-row:nth-child(2) i{left:94%}.timing[data-step="1"] .time-row:first-child span:nth-child(2){color:var(--accent);font-weight:700}.timing[data-step="3"] .time-row:nth-child(2) span:last-of-type{color:var(--accent-3);font-weight:700}
js
const root=document.querySelector('.visual'),cap=root.querySelector('.visual-caption'),dots=[...root.querySelectorAll('.visual-dots b')],captions=["Both begin with an edit","Static check catches the call","Dynamic execution reaches the call","Runtime reports the error"];let step=0;function advance(){root.dataset.step=String(step);cap.textContent=captions[step];dots.forEach((d,i)=>d.classList.toggle('on',i===step));if(root.classList.contains('generic')){root.querySelector('.generic-input').textContent=step===3?'"hi"':'7';root.querySelector('.generic-output').textContent=step===3?'"hi" : string':'7 : number'}if(root.classList.contains('union'))root.querySelector('.set-value').textContent=step%2?'value: "seven"':'value: 7';step=(step+1)%captions.length}advance();let timer=setInterval(advance,1100);root.addEventListener('pointerdown',()=>{clearInterval(timer);advance()})

A statically typed language checks type relationships before execution. A dynamically typed language decides whether an operation is valid for the actual value at runtime.

The demo compares when the same invalid method call is discovered in each lane. Both approaches still need tests and input validation.

When to use

Use this distinction when choosing language tooling and deciding where errors should surface.

Open as page ↗