🔥 첫 타입 주석: let, function, return

793자
9분

변수 선언과 함수 시그니처가 두 카드로 나란히 놓이고 각 콜론마다 'colon = type annotation' 라벨이 붙어 있는 표지

tsconfig.json 을 한 번 정해 두고 나서 처음으로 직접 적는 .ts 파일은 한 줄짜리 변수 선언인 경우가 많다. 나도 그랬다. bun init 으로 만든 디렉토리에서 hello.ts 를 열고 let name = "Mejoo" 한 줄을 적었더니 호버에 string 이라고 떴다. 그다음에 나는 let name: string = "Mejoo" 로 콜론 + 타입을 직접 적었다. 실행 결과는 같았다. 그래서 두 줄 사이에서 무엇이 달라졌는지를 한참 살폈다.

콜론은 TypeScript 의 타입 주석을 표시하는 단 하나의 기호다. 변수 선언 옆, 함수 매개변수 옆, 함수 반환 타입 옆 세 곳에서 같은 의미로 작동한다.

변수 옆에 콜론을 적는다

가장 단순한 형태는 let 다음에 변수 이름을 쓰고, 그 뒤에 콜론과 타입을 붙이는 단계다. string, number 처럼 TypeScript 가 미리 알고 있는 원시 타입 이름이면 충분하다.

let name : string = "Mejoo" 코드 한 줄 아래에 변수 이름 / 콜론 = 타입 표시 / 원시 타입 이름 세 라벨이 화살표로 가리키는 다이어그램

ts
// file: var-annotation.ts
export {};
 
let name: string = "Mejoo";
let count: number = 3;
 
console.log(name, count);
 
// 잘못된 대입 한 줄. 주석을 풀면 컴파일러가 멈춘다.
// let count2: number = "3";
ts
// file: var-annotation.ts
export {};
 
let name: string = "Mejoo";
let count: number = 3;
 
console.log(name, count);
 
// 잘못된 대입 한 줄. 주석을 풀면 컴파일러가 멈춘다.
// let count2: number = "3";

bunx tsc --noEmit 으로 검사하면 두 줄 모두 통과한다. bunx tsx var-annotation.ts 로 실행하면 Mejoo 3 한 줄이 나온다. 마지막 주석 줄을 풀면 컴파일러는 Type 'string' is not assignable to type 'number'. 메시지를 띄우고 멈춘다.

콜론은 한 가지 약속을 적는다. 이 변수는 이 타입의 값만 받는다. 한 번 적어 두면 같은 변수를 다른 타입으로 다시 대입할 수 없다. 주석을 직접 적지 않은 변수도 TypeScript 가 초깃값을 보고 같은 타입으로 추론한다. 그래도 의도를 분명히 남기고 싶을 때, 또는 초깃값보다 더 좁은 타입을 강제하고 싶을 때는 콜론을 직접 적는다.

let count: number = "3" 코드 한 줄에서 "3" 값에 빨간 동그라미가 붙고 그 아래 터미널 박스에 Type "string" is not assignable to type "number" 메시지가 떠 있는 다이어그램

함수 시그니처 두 곳

함수 한 개에는 콜론이 두 종류로 들어간다. 매개변수 옆에 한 번씩, 그리고 매개변수 목록을 닫는 괄호 뒤에 한 번. 앞쪽은 매개변수가 받을 타입을 약속하고, 뒤쪽은 함수가 돌려줄 값의 타입을 약속한다.

function add(a: number, b: number): number 시그니처에서 세 콜론 위치마다 param colon / param colon / return colon 라벨이 화살표로 붙어 있는 다이어그램

ts
// file: param-return.ts
export {};
 
function add(a: number, b: number): number {
  return a + b;
}
 
console.log(add(2, 3));
 
// 잘못된 호출 한 줄. 주석을 풀면 호출 줄에서 컴파일러가 멈춘다.
// console.log(add("2", 3));
ts
// file: param-return.ts
export {};
 
function add(a: number, b: number): number {
  return a + b;
}
 
console.log(add(2, 3));
 
// 잘못된 호출 한 줄. 주석을 풀면 호출 줄에서 컴파일러가 멈춘다.
// console.log(add("2", 3));

bunx tsc --noEmit 은 그대로 통과하고, bunx tsx param-return.ts5 한 줄을 출력한다. 마지막 주석을 풀면 컴파일러는 add 호출의 첫 인자에서 Argument of type 'string' is not assignable to parameter of type 'number'. 메시지를 띄운다. 호출 쪽이 검사 대상이 된다는 점이 중요하다. 함수 본문에서는 abnumber 로 다룬다. 그래서 a + b 같은 number 연산을 바로 쓸 수 있다.

반환 타입 주석은 두 가지 일을 한다. 첫째, 호출하는 쪽이 받을 값의 타입을 미리 적어 둔다. 둘째, 함수 본문이 그 타입의 값을 반환하는지 컴파일러가 다시 검사한다. function add(...): number 라고 적어 두고 본문이 return "5" 라고 돌려주려고 하면, 컴파일러는 그 줄에서 멈춘다. 반환 타입을 직접 적어 두면 함수의 의도가 또렷하게 남는다.

add("2", 3) 호출에서 첫 인자 "2" 에 빨간 동그라미가 붙고 그 아래 터미널 박스에 Argument of type "string" is not assignable to parameter of type "number" 메시지가 떠 있는 다이어그램

같은 콜론, 다른 단계

let name: string 의 콜론과 (a: number, b: number): number 의 콜론들은 같은 기호 한 개다. 이건 이 타입이다 라는 한 약속을 세 단계에 같은 표기로 적는다.

  • 변수 선언: 변수 이름과 타입 이름 사이에 콜론.
  • 함수 매개변수: 매개변수 이름과 타입 이름 사이에 콜론.
  • 함수 반환 타입: 매개변수 목록을 닫는 괄호와 반환 타입 이름 사이에 콜론.

세 가지 모두 결과 .js 에는 한 글자도 남지 않는다. 콜론 + 타입은 컴파일 시점에만 검사되는 표시이고, bunx tsx 로 실행할 때는 콜론과 타입을 모두 떼어 낸 자바스크립트 코드가 돌아간다. TypeScript 의 타입 주석은 항상 그렇게 컴파일러 쪽에서만 일을 한다.

세 단계가 같은 기호를 쓰기 때문에, 한 단계에서 익힌 질문을 나머지 두 단계에도 그대로 쓴다. 콜론을 본 줄에서는 왼쪽 이름이 어떤 타입을 갖는가 한 가지만 묻는다. let name: string 이면 namestring 이다. a: numberanumber 다. (): number 면 함수가 돌려주는 값이 number 다. 같은 질문에 같은 표기로 답한다.

variable / parameter / return 세 라벨이 왼쪽에 붙은 세 줄 (let name: string, (a: number, b: number), (): number) 이 세로로 정렬되고 각 콜론을 가리키는 화살표가 오른쪽에서 들어오는 비교 다이어그램

다음 단계로 가기 전에

콜론 + 타입을 한 번 익숙하게 적기 시작하면, 다음으로 자연스럽게 떠오르는 질문이 있다. 언제 적고 언제 추론에 맡기는가. TypeScript 는 변수 선언 단계에서 초깃값을 보고 타입을 자동으로 추론한다. 그래서 모든 단계에 콜론을 적을 필요는 없다.

지금은 변수 선언과 함수 시그니처에 적은 콜론이 모두 같은 일을 한다는 점만 기억하면 충분하다.

YouTube 영상

채널 보기
트라이(Trie)에서 단어를 삭제하는 방법 | Trie 자료구조 이야기
AI는 데이터를 어떻게 분류할까? 벡터의 거리와 KNN 알고리즘 | 선형대수학
마지막편, 트라이 노드를 50% 이상 줄이는 방법? 압축 트라이 성능 분석 | Trie 자료구조 이야기
AI를 위한 선형대수학 - 소개 | 선형대수학
직교성과 벡터 투영 | 선형대수학
AI는 왜 수백 차원의 벡터를 사용할까? 고차원 공간과 행렬 | 선형대수학
내적의 기하학적 의미와 코사인 유사도 원리 | 선형대수학
투영과 예측, 그리고 선형 결합 | 선형대수학