[TypeScript] Primitive Types
정의
Primitive Types 는 TypeScript 의 가장 기본 타입 계열입니다. JavaScript 의 7가지 primitive 값 + 특수 타입 (void, never, unknown, any) 을 포함합니다.
목록
| 타입 | 값 예시 | 언제 |
|---|---|---|
string | "hello" | 문자열 |
number | 42, 3.14 | 정수/실수 (double) |
boolean | true, false | 참거짓 |
bigint | 9007199254740993n | 임의 정밀도 정수 |
symbol | Symbol() | 고유 식별자 |
null | null | 명시적 null |
undefined | undefined | 값 없음 |
void | 리턴 없음 | 함수 반환 |
never | 없음 | 절대 발생하지 않음 |
unknown | 모든 값 | 타입 모름 (안전) |
any | 모든 값 | 타입 검사 해제 (위험) |
string
let s: string = "hello";
let s2 = "world"; // 추론
const name = "kim"; // literal type: "kim"
// Template literal
let greeting = `Hello, ${name}`;
Literal type: const 로 선언된 문자열은 정확한 문자열 리터럴 타입 이 됩니다.
let a: string = "hello"; // string
const b = "hello"; // "hello" (literal type)
number
let x: number = 42;
let y: number = 3.14;
let z: number = 0xFF; // 헥스
let w: number = 0b1010; // 이진
let v: number = 1_000_000; // 구분자
const PI = 3.14; // literal 3.14
JavaScript 는 정수/실수 구분 없음. 모두 64-bit double.
boolean
let flag: boolean = true;
const isReady = false; // literal false
bigint
임의 정밀도 정수. n 접미사.
let big: bigint = 9007199254740993n;
let big2 = BigInt(123);
// number 와 혼합 불가
big + 1; // 오류
big + 1n; // OK
언제: DB primary key, blockchain wei, 큰 timestamp.
symbol
고유 식별자. 두 symbol 은 절대 동등하지 않음.
const s1 = Symbol("foo");
const s2 = Symbol("foo");
s1 === s2; // false
// 객체의 unique key 로
const KEY = Symbol();
const obj = {[KEY]: "value"};
Symbol.iterator, Symbol.asyncIterator 등 well-known symbol 이 프로토콜 정의.
null / undefined
두 값이 유사하지만 미묘하게 다름:
undefined: 변수가 초기화되지 않음, 함수 리턴 없음null: 명시적 으로 값 없음
let x: string | null = null;
let y: string | undefined;
if (x != null) {
x.toUpperCase(); // null 과 undefined 모두 배제
}
strictNullChecks (기본 활성) 하에서는 string 타입에 null/undefined 를 못 넣음. 명시적 union 필요.
void
함수가 아무것도 반환하지 않음:
function log(msg: string): void {
console.log(msg);
}
const cb: () => void = () => 42; // OK, void 는 반환 값 무시
void 리턴 타입 함수의 반환값은 사실상 무시 (() => any 와 다름). 콜백 시그니처에 유용.
never
절대 발생하지 않는 값:
function throwError(msg: string): never {
throw new Error(msg);
}
function loop(): never {
while (true) {}
}
Exhaustive check
type Shape = {kind: "circle", r: number} | {kind: "square", s: number};
function area(s: Shape): number {
switch (s.kind) {
case "circle": return Math.PI * s.r ** 2;
case "square": return s.s ** 2;
default:
const _exhaustive: never = s; // 새 case 추가 시 컴파일 오류
return _exhaustive;
}
}
Discriminated union 의 모든 case 를 다뤘음을 컴파일러가 검증.
never 는 모든 타입의 subtype
type Result = never | number; // number 로 축약
unknown
타입을 모른다 는 것을 안전하게 표현. any 대체.
let x: unknown = JSON.parse(rawJson);
// 바로 사용 불가
x.toUpperCase(); // 오류
// narrowing 후 사용
if (typeof x === "string") {
x.toUpperCase(); // OK
}
if (typeof x === "object" && x !== null && "name" in x) {
console.log(x.name);
}
언제: 외부 데이터 (JSON.parse, API 응답, event.data). 검증 후 좁혀서 사용.
any
타입 검사 해제. 위험.
let x: any = 5;
x = "string";
x.foo.bar(); // 컴파일 통과, 런타임 오류
언제 (제한적으로 허용):
- 마이그레이션 임시 회피
- 진짜로 타입을 알 수 없고 검증 안 할 때
noImplicitAny: false는 위험
unknown 이 대개 더 안전한 대안.
Anti-pattern: any[], Record<string, any>, Function 남용.
Union 조합
let id: string | number = "abc";
id = 42;
function print(v: string | number | boolean): void {
console.log(v);
}
자세한 것은 Union / Intersection 참조.
Literal Type
let status: "pending" | "active" | "closed" = "pending";
type Direction = "north" | "south" | "east" | "west";
function move(dir: Direction): void {
...
}
move("north"); // OK
move("northwest"); // 오류
- Enum 대신 자주 사용됨 (자세한 것은 Enums 참조)
- 상수의 타입을 그대로 표현
Object literal type
let user: {name: string, age: number} = {name: "kim", age: 30};
// Optional
let config: {debug?: boolean, port: number} = {port: 8000};
// Readonly
let point: {readonly x: number, readonly y: number} = {x: 1, y: 2};
point.x = 5; // 오류
// Index signature
let scores: {[key: string]: number} = {alice: 90, bob: 85};
Interface 나 type alias 로 이름 붙이는 편이 관용.
Array
let ns: number[] = [1, 2, 3];
let ns2: Array<number> = [1, 2, 3]; // 동일
let matrix: number[][] = [[1, 2], [3, 4]];
// Readonly
let ro: readonly number[] = [1, 2, 3];
ro.push(4); // 오류
Tuple
let pair: [string, number] = ["a", 1];
pair[0].toUpperCase();
pair[1].toFixed(2);
// Optional
let mixed: [string, number?] = ["a"];
// Named tuple
let range: [start: number, end: number] = [0, 100];
// Rest in tuple
let strs: [string, ...number[]] = ["a", 1, 2, 3];
자주 하는 실수
실수 1: Number (대문자)
let x: Number = 5; // Boxed wrapper 타입, 사용 안 함
let y: number = 5; // 정답 (primitive)
String, Boolean, Object 도 마찬가지. 대문자는 wrapper 객체 타입, 소문자가 primitive.
실수 2: Object
let x: Object = {}; // 거의 아무거나
let y: object = {}; // primitive 아닌 것
let z: {} = {}; // null/undefined 제외 모든 것
이 셋은 미묘하게 다르며 대개 원하는 건 명시적 shape ({name: string}) 이거나 Record<K, V>.
실수 3: any 남용
function f(x: any): any {
return x.foo();
}
이 함수 안에서는 무엇이든 가능. 호출부에도 any 가 퍼짐. unknown 이나 정확한 시그니처로 대체.
함정
WARNING
any 는 감염됩니다. any 를 리턴하는 함수의 결과는 any. any 로부터 파생된 것들 모두 any. 초기부터 unknown 을 습관화.
CAUTION
null vs undefined. API 응답에서 필드가 없음 (undefined) 과 명시적 null 은 다름. 둘 다 처리하려면 x ?? default (nullish coalescing).
WARNING
Number.isNaN 을 씁시다. 전역 isNaN("abc") 은 true (문자열도 강제 형변환). Number.isNaN 만 정확한 NaN 검사.
IMPORTANT
bigint 는 JSON 안 됨. JSON.stringify(1n) 오류. 문자열 직렬화 후 파싱 필요.
CAUTION
unknown narrowing 을 잊지 마세요. unknown 은 안전하지만 그만큼 사용 전에 검증 필수.
관련 위키
- TypeScript - 상위 개요
- Interfaces - 객체 shape
- Type Aliases
- Union / Intersection
- Type Narrowing - typeof, in, is
- Enums - Literal union 대안
- JavaScript null/undefined
- JavaScript NaN/Infinity
- JavaScript BigInt
- JavaScript Number
- JavaScript String
이 글의 용어 (11개)
- [Javascript] BigIntjavascript
- 정의 는 임의 정밀도 정수. 를 넘어가는 정수를 정확히 표현. ES2020 도입. 사용 상황 | 상황 | 권장 타입 | |:---|:---| | 64-bit 정수 ID (DB의 …
- [Javascript] boolean / null / undefinedjavascript
- 정의 JavaScript 의 3 가지 primitive. - : , - : 의도적인 "없음" - : 자동으로 부여된 "없음" (초기화 안 됨) 사용 상황 | 상황 | 권장 값 /…
- [Javascript] NaN / Infinityjavascript
- 정의 - (Not a Number) : 의미 없는 수치 연산의 결과 - , : 너무 큰/작은 수, 0 으로 나누기 IEEE 754 표준에 따른 특수 값. 타입이지만 특이한 동작.…
- [Javascript] Numberjavascript
- 정의 JavaScript 의 는 IEEE 754 double-precision float (64-bit). 정수와 실수를 같은 타입으로 표현. 정수 안전 범위는 . IEEE 75…
- [Javascript] Stringjavascript
- 정의 JavaScript 의 은 UTF-16 코드 유닛의 불변 시퀀스. 작은따옴표, 큰따옴표, 백틱 (template literal) 으로 작성. 사용 상황 | 상황 | 권장 패…
- [TypeScript] Enumstypescript
- 정의 Enum 은 여러 관련 상수를 하나의 이름 아래 그룹화하는 TypeScript 기능입니다. Numeric enum, string enum, const enum, hetero…
- [TypeScript] Interfacestypescript
- 정의 Interface 는 객체의 shape (형태) 을 정의하는 TypeScript 문법입니다. 필드, 메서드, 인덱스 시그니처, 호출 시그니처를 선언하며, 로 상속하고 dec…
- [TypeScript] Type Aliasestypescript
- 정의 Type Alias 는 타입에 이름을 붙이는 TypeScript 문법 ( ). Interface 는 객체 shape 만 표현하지만, type alias 는 모든 타입 표현식…
- [TypeScript] Type Narrowing (Type Guards)typescript
- 정의 Type Narrowing 은 TypeScript 컴파일러가 제어 흐름 분석 (control flow analysis) 을 통해 특정 위치에서 값의 타입을 더 좁게 추론하는…
- [TypeScript] Union & Intersection Typestypescript
- 정의 - Union Type ( ): A 이거나 B (또는 둘 다) 인 값 - Intersection Type ( ): A 이면서 B 인 값 두 조합은 TypeScript 의 타…
- TypeScripttypescript
- 정의 TypeScript 는 Microsoft 가 2012년 발표한 JavaScript 의 상위 집합 프로그래밍 언어입니다. 정적 타입 시스템, 인터페이스, 제네릭, enum, …
💬 댓글