4 minute read

1. 타입의 종류

타입스크립트의 가장 기본적인 타입은 자바스크립트의 일곱 가지 기본 원시 타입 (primitive type)과 동일

원시 타입

1. null
2. undefined
3. boolean
4. string
5. number
5. bigint
7. symbol

2. 타입 시스템

타입 시스템은 프로그래밍 언어가 프로그램에서 가질 수 있는 타입을 이해하는 방법에 대한 규칙 집합이다.

타입스크립트 타입 시스템 동작과정

  1. 코드를 읽고 존재하는 모든 타입과 값을 분석

  2. 각 값이 초기 선언에서 가질 수 있는 타입 확인
  3. 각 값이 추후 코드에서 어떻게 사용될 수 있는지 모든 방법 확인
  4. 값의 사용법과 타입이 일치하지 않을 시 사용자에게 오류 표시

3. 오류 종류

  1. 구문 오류 : 타입스크립트가 자바스크립트로 변환되는 것을 차단

  2. 타입 오류 : 타입 검사기에 따라 일치하지 않는 것이 감지

3.1. 구문 오류

  • 타입스크립트가 코드로 이해할 수 없는 잘못된 구문을 감지할 시 발생

    (별도의 도구와 설정에서 변환시 필요한 코드를 가져와 자바스크립트 코드를 생성할 수도 있음)

  • 타입스크립트 파일에서 자바스크립트 파일을 올바르게 생성할 수 없도록 차단

3.2. 타입 오류

  • 타입스크립의 타입 검사기가 프로그램의 타입에서 오류를 감지시 발생
  • 오류가 발생했다고 해서, 타입스크립트의 구문이 자바스크립트로 변환되는 것을 차단하지는 않음

    ex. console.blub()와 같은 코드를 작성하더라도, 컴파일을 실행시 js파일이 생성됨

4. 할당 가능성

앞서 서술했듯이, 타입스크립트는 변수의 초깃값을 읽고 해당 변수가 허용되는 타입을 결정한다.

나중에 해당 변수에 새로운 값이 할당될 시, 새롭게 할당된 값의 타입이 변수의 타입과 동일한지 확인한다.

변수에 동일한 타입의 다른 값이 할당될 시에는 별다른 문제가 없다.

그러나, 변수에 다른 타입의 값이 할당될 시에는 타입 오류가 발생한다.

이처럼 타입스크립트에서 함수 호출이나 변수에 값을 제공할 수 있는지 여부를 확인하는 것을 할당 가능성 (assignability)라고 한다.

결국, 할당 가능성이라는 것은 전달된 값이 예상된 타입으로 할당 가능한지의 여부를 확인하는 것이다.

5. 타입 애너테이션

변수에 타입스크립트가 읽어야 할 초기값이 없는 경우, 타입스크립트는 나중에 사용할 변수의 초기 타입을 파악하려고 하지 않고, 기본적으로 변수를 암묵적인 any타입으로 간주한다.

이와 같이 초기 타입으로 유추가 불가능한 변수를 진화하는 any라고 부른다.

let testString; // any type

testString = "test" // type: string
testString.toUpperCase(); // string 타입의 메서드 호출 가능

testString = 18.45 // type : number
testString.toPrecision(1); // number 타입의 메서드 호출 가능

testString.toUpperCase(); // Error : string타입의 메서드 호출 불가

위와 같이 자유롭게 타입이 변화 가능하다면, 개발 과정에서 해당 변수가 string 타입에서 number 타입으로 진화 가능하도록 코드를 짠 것이 처음부터 의도된 것인지에 대한 여부를 명확히 파악하기 어려울 수 있다.

즉, 이러한 any타입을 허용하도록 하면, TypeScript의 가장 큰 목적 중 하나인 타입 검사를 쓸모없게 만드는 것이다.

타입스크립트는 해당 변수나, 매개변수 등의 값이 어떤 타입인지를 알고 있을 땓 가장 잘 작동 된다.

따라서, 위와 같은 문제를 해결하기 위해 타입스크립트는 초기값을 할당하지 않고도, 변수의 타입을 선언할 수 있는 구문인 타입 애너테이션 (Type annotation) 을 제공한다.

let testString : string;
testString = "test";

위와 같은 타입 애너테이션은 타입스크립트에만 존재하며, 런타임 코드에 영향을 주지도 않고 유효한 자바스크립트 구문도 아니다. (tsc 명령어를 사용해 소스 코드를 자바스크립트 코드로 컴파일 하면 해당 코드는 삭제가 된다.)

위와 같이 타입 애너테이션을 이용해 선언한 변수에 정의한 타입 이외의 값을 할당하게 되면, 타입 오류가 발생한다.

5.1 타입 애너테이션이 불필요한 경우

let testString = "test"

위와 같이 초깃값이 있는 변수의 경우, 타입스크립트는 초깃값을 바탕으로 해당 변수에 어떤 타입이 할당 가능한지를 판단한다.

즉, 위와 같이 초깃값이 있는 변수에 타입 애너테이션을 사용하더라도, 타입스크립트는 별도의 정보를 얻지 못한다. 이미 해당 변수의 초깃값을 바탕으로 해당 변수에 할당 가능한 타입 정보를 분석했기 때문이다.

물론, 코드를 명확하게 문서화하거나 실수로 변수 타입이 변경되지 않도록 하기 위해서 변수에 명시적으로 타입 애너테이션을 포함하는 것은, 경우에 따라서 유용할 수 있다.

6. 모듈

ECMAScript 2015에서는 파일 간에 import/export 구문을 표준화하기 위해 ECMAScript Modules (ESM)이 추가되었다.

(ECMAScript는 Ecma 인터내셔널에 의해 제정된 ECMA-262 기술 규격에 의해 정의된 범용 스크립트 언어로, JavaScript는 이러한 ECMAScript의 사양을 준수하는 범용 스크립트 언어이다. 자세한 내용은 추후 별도의 포스팅에서 다루겠다.)

import {value} from "./values";

export const doubled = value*2;

위의 모듈 파일은 ./values 파일에서 value를 가져오고, 변수 doubled를 내보낸다.

ECMAScript사양에 따라 다음과 같은 명명법을 사용할 수 있다.

  • 모듈 : export 또는 import가 있는 파일
  • 스크립트 : 모듈이 아닌 모든 파일

모듈 파일에서 선언된 모든 것은 해당 파일에서 명시한 export 문에서 내보내지 않는 한, 한 모듈 파일 내부에서만 사용할 수 있다.

한 모듈에서 다른 파일에서 가져온 변수와 동일한 이름의 변수를 사용하게 되면 이름 충돌이 발생한다.

만약 파일이 스크립트라면 타입스크립트는 해당 파일을 전역 스코프로 간주하므로 모든 파일이 해당 파일의 내용에 접근할 수 있다.

즉, 스크립트 파일에 선언된 변수는 다른 스크립트 파일에 선언된 변수와 동일한 이름을 가질 수 없다.

//a.ts
const shared = "testA" 
// b.ts
const shared = "testB"

위의 a.ts와 b.ts 파일은 모두 스크립트 파일이므로, 타입 스크립트는 이를 전역 시코프로 간주하기 때문에, 동일한 이름의 변수를 사용할 때 충돌이 일어난다.

(위의 두 파일을 tsc로 컴파일하면, 텅 빈 a.js와 b.js파일만 생성된다.)

만약 상황상 서로 다른 스크립트에서 동일한 이름을 사용해야 한다면, ECMAScript의 사양에 맞춰, 파일의 아무 곳에나 export{}; 를 추가하여, 강제로 해당 스크립트 파일이 모듈이 되도록 만든다.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var shared = "testB";

그렇게 한 뒤에 컴파일을 하게 되면 위와 같은 형태의 자바스크립트 파일이 만들어진다.

cf) 타입스크립트는 CommonJS(자바스크립트 모듈을 만들기 위한 프로젝트)와 같은 이전 모듈을 사용해 작성된 타입스크립트 파일의 import,export 형태를 인식하지 못한다고 한다. (일반적으로 CommonJS 스타일의 require 함수에서 반환된 값을 any 타입으로 인식한다.)