JavaScript / typeof로 데이터 타입 확인하기와 주의점
typeof는 값의 자료형을 "number", "string" 같은 문자열로 알려 주는 연산자입니다. 다만 null과 배열은 모두 "object"로 나오고, NaN도 "number"로 나오므로 세부적인 값 검사는 별도로 해야 합니다.
문법과 가능한 반환 문자열
typeof 42; // "number"
typeof "42"; // "string"
typeof (1 + "2"); // "string"
괄호는 필수 호출 문법이 아닙니다. typeof는 함수가 아니라 연산자이며, 복합 표현식을 검사할 때 괄호로 검사 범위를 분명히 할 수 있습니다. 반환값 자체도 문자열이므로 비교할 때는 typeof value === "number"처럼 자료형 이름에 따옴표를 붙입니다.
| 값 또는 종류 | 결과 문자열 | 해석 시 주의점 |
|---|---|---|
undefined |
"undefined" |
선언됐지만 값이 없는 경우도 해당 |
true·false |
"boolean" |
문자열 "false"와 다름 |
숫자·NaN·Infinity |
"number" |
유한성·정확성까지 보장하지 않음 |
42n 등 BigInt |
"bigint" |
Number와 다른 정수 자료형 |
| 문자열 | "string" |
숫자 모양의 텍스트도 문자열 |
Symbol() |
"symbol" |
고유한 식별 용도로 쓰는 기본형 |
| 함수 | "function" |
호출 가능한 함수 값 구분 |
배열·객체·null |
"object" |
배열과 null을 따로 판별해야 함 |
자료형은 변수 이름에 고정된 것이 아니라 현재 값에 연결됩니다. 예를 들어 let value = 1 이후 value = "1"로 다시 대입하면 검사 결과도 달라집니다. Number는 일반적인 JavaScript 숫자 자료형이고, BigInt는 큰 정수를 표현하기 위한 별도의 기본 자료형입니다. 전체 반환 규칙과 예외는 MDN의 typeof 문서에서 확인할 수 있습니다.
여러 값을 같은 조건으로 비교하는 전체 예제
아래 코드를 UTF-8의 typeof-demo.html 파일로 저장해 브라우저에서 여세요. 값마다 같은 typeof 연산을 적용하고, 결과 표를 DOM 요소로 만들어 표시합니다. 일반 함수와 화살표 함수 모두 함수 값이라는 점은 같지만, 여기서는 짧은 표기인 () => {}를 사용했습니다.
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>typeof 결과 비교</title>
</head>
<body>
<h1>typeof 결과 비교</h1>
<table>
<thead><tr><th>값</th><th>typeof 결과</th></tr></thead>
<tbody id="types"></tbody>
</table>
<button id="tdz" type="button">선언 전 let 검사</button>
<pre id="output"></pre>
<script>
const samples = [
["문자열", "hello"], ["숫자", 42], ["NaN", NaN],
["Infinity", Infinity], ["BigInt", 42n], ["불리언", true],
["Symbol", Symbol("id")], ["함수", () => {}],
["배열", []], ["null", null], ["일반 객체", {}],
["undefined", undefined]
];
const tbody = document.getElementById("types");
for (const [label, value] of samples) {
const row = document.createElement("tr");
for (const text of [label, typeof value]) {
const cell = document.createElement("td");
cell.textContent = text;
row.appendChild(cell);
}
tbody.appendChild(row);
}
const output = document.getElementById("output");
document.getElementById("tdz").addEventListener("click", () => {
try {
const result = typeof later;
let later = 1;
output.textContent = result;
} catch (error) {
output.textContent = error.name;
}
});
</script>
</body>
</html>
결과 표에서 숫자·NaN·Infinity 행은 모두 number입니다. 배열·null·일반 객체 행은 object, 함수 행은 function입니다. BigInt와 Symbol도 각자의 문자열을 반환합니다. 하나의 샘플 값만 바꾸고 새로고침하면 그 행의 결과만 비교할 수 있습니다. 되돌릴 때는 샘플 값을 원래대로 복구해 저장하세요.
‘선언 전 let 검사’를 누르면 ReferenceError가 표시됩니다. 이 오류는 예제가 실패했다는 뜻이 아니라, 같은 블록에서 초기화 전인 let later를 typeof로 검사해도 오류가 발생한다는 점을 확인하는 의도된 결과입니다. try...catch는 오류를 잡아 페이지의 다른 동작이 중단되지 않도록 합니다.
배열·null·유한한 숫자를 따로 검사하기
const value = [];
Array.isArray(value); // true
value === null; // false
Number.isNaN(NaN); // true
Number.isFinite(12); // true
Number.isFinite("12"); // false
Number.isFinite(Infinity); // false
typeof value === "object"만으로 배열인지 확인할 수 없습니다. 배열에는 Array.isArray(), null에는 value === null을 사용하세요. 숫자 자료형인지만 확인할지, 실제 계산에 쓸 수 있는 유한한 숫자인지까지 확인할지도 구분해야 합니다. Number.isFinite()는 문자열을 숫자로 자동 변환하지 않습니다.
문자열 입력을 계산에 사용하려면 변환과 검증을 별개로 설계합니다. 먼저 입력의 빈 값이나 허용 형식을 확인한 뒤 필요한 변환을 하고, 변환 결과를 검사하세요. typeof가 숫자라고 나왔다고 해서 NaN이나 무한대를 허용해도 된다는 뜻은 아닙니다. 숫자와 문자열 변환 자체는 Number() 변환 예제에서 비교할 수 있습니다.
선언되지 않은 이름과 초기화 전 이름의 차이
typeof neverDeclaredName; // 보통 "undefined"
{
// typeof waiting; // 실행하면 ReferenceError
let waiting = 1;
console.log(typeof waiting); // "number"
}
선언 자체가 없는 식별자를 검사할 때는 보통 "undefined"를 얻을 수 있습니다. 반면 같은 범위의 let·const·class 이름은 초기화 전까지 접근할 수 없는 구간이 있습니다. 이를 일시적 사각지대(TDZ, Temporal Dead Zone)라고 하며, typeof도 이 제한을 우회하지 못합니다. 예제에서는 오류를 유발하는 한 줄을 주석으로 두어 그대로 복사해도 뒤의 정상 결과를 확인할 수 있게 했습니다.
연산 우선순위에도 주의하세요. typeof 1 + "개"는 "number개"가 되고, typeof (1 + "개")는 문자열 연결 결과를 검사해 "string"이 됩니다. 검사하려는 표현식 전체를 괄호로 묶으면 의도가 분명해집니다. 브라우저의 오래된 호환 기능인 document.all에는 특별 취급이 있으므로, 이 값을 일반적인 자료형 판별 예제로 사용하지 않는 편이 좋습니다.




