타입스크립트

오민준·2024년 1월 25일
0

1. 타입이란

타입을 지정해 코드에서 사용하는 유효한 값의 범위를 제한해 런타임에서 발생할 수 있는 유효하지 않은 값에 대한 에러를 방지한다.

function double(n) {
  return n * 2
}

double(2) //4
double("z") // NaN

double()의 내부 동작은 숫자를 인자로 받을 것으로 기대하나 그 외의 타입에 해당하는 값을 전달하면 의도하지 않은 작업을 수행해 원하는 값을 얻지 못한다.

function double(n : number) {
  return n * 2;
}

double(2) //4
double("z") // NaN

타입을 제한하면 타입스크립트 컴파일러는 함수를 호출할 때 호환되는 인자로 호출했는지를 판단한다. 따라서 string 타입인 "z"를 호출한 경우 number에 할당이 불가능해 에러가 발생한다.

이 때, 타입스크립트의 컴파일 결과물은 여전히 사람이 이해 가능한 자바스크립트 파일이다.
타입스크립트의 탄생 이유는 고수준-저수준의 코드 변환을 위해서가 아닌 자바스크립트의 런타임 에러를 잡아내기 위한 것으로 타입스크립트를 컴파일 하면 타입이 모두 제거된 자바스크립트 소스코드만이 남게 된다.

2. 타입 시스템

  • 타입 에너테이션 방식

    • 우리가 흔히 아는 방식으로 변수/상수/인자/반환 값 등에 타입을 명시적으로 선언하여 컴파일러에 직접 알려주는 문법이다.
  • 구조적 타이핑

    • 이름으로 타입을 구분하는 명목적인 타입 언어의 특징과 달리 타입스크립트는 구조로 타입을 구분한다.
    • 이러한 구조적 타이핑의 특징 때문에 예기치 못한 결과가 발생할 수도 있다.
    • interface에 추가 속성 타입이 정의되는 경우 기존 필드의 타입으로 예측하여 판단하나 추가 속성은 다른 타입을 가질 수 있으므로 에러가 발생한다.
  • 구조적 서브타이핑

    • 타입 시스템을 집합으로 이해하여 객체가 가지고 있는 속성을 바탕으로 타입을 구분한다.
    • 이름이 다르더라도, 가진 속성이 동일하다면 서로 호환이 가능한 동일한 타입으로 여긴다.
interface Pet {
  name: string;
}

interface Cat
  name: string;
  age: number;
}

let pet: Pet;
let cat: Cat = {name: "Zag", age: 2}

// OK
pet = cat

Cat과 Pet이 다른 타입으로 선언되었으나, Pet이 갖고 있는 name 속성을 가지고 있으므로 Cat타입으로 설정한 cat을 Pet타입으로 설정한 pet에 할당할 수 있다.

  • 값과 타입
    • 값 : value 은 프로그램이 처리하기 위해 메모리에 저장하는 모든 데이터이다. 따라서, 숫자와 같은 데이터는 물론이고 반환하는 결괏값, 문자열, 매개변수 등도 값에 해당된다.

    • 11; // 숫자 값
      "hello typescript" // 문자열 값
      let foo = "bar" //  변수값
      
      // 함수 역시 변수에 할당할 수 있는 값임을 알 수 있다.
      function goWork(developer) {
      	console.log(`tired ${developer}`)
      }
      
      // 이 예시는 developer라는 변수에 "zig"라는 문자열 값을 할당했다
      const developer = "zig"
    • 입스크립트 문법인 type으로 선언한 내용은 자바스크립트 런타임에서 제거되기 때문에 값 공간과 타입 공간의 이름은 서로 충돌하지 않기 때문에 타입과 변수를 같은 이름으로 정의할 수 있다.

    • 타입은 주로 타입 선언(:) 또는 단언 문(as)으로 작성하고 값은 할당 연산자(=)로 작성한다.

    • 타입스크립트에서 값과 타입의 구분은 맥락에 따라 달라지기 때문에 혼동할 때도 있다.

    • function email(option: { person: Person; subject: string; body: string}) {
      	//..
      }
      	
      // 위의 코드를 구조 분해 할당하면 아래와 같다.
      function email({ person, subject, body}) {
      	//..
      }
    • 자바스크립트의 구조 분해 할당을 사용하면 email 함수의 매개변수로 넘기는 options 객체를 아래와 같이 풀어 쓸 수 있다. 그러나 같은 코드를 타입스크립트에서 구조 분해 할당 하면 오류가 발생한다.

    • 이는 값의 관점에서 Person과 string이 해석되었기 때문이다. 개발자의 의도와 달리 Person과 string이 값 공간에 있는 것으로 해석해 person과 Person이 각 함수의 매개변수 객체 내부 속성의 키-값 쌍에 해당되는 것으로 해석했기 때문이다.

    • 이와 같은 값-타입 공간을 혼동하는 문제를 해결하기 위해 아래와 같이 값과 타입을 구분해서 작성한다.

    • function email({person, subject, body} : { person: Person; subject: string; body: string; }) {
      //...
      }
    • 이와 다르게 클래스와 enum은 값과 타입 공간에 동시에 존재할 수도 있다.

    • 클래스의 실제 동작은 함수와 같으며 동시에 타입으로도 사용 가능하다

    • enum의 경우 클래스처럼 타입공간에서 타입을 제한하는 역할을 하지만 런타임에 객체로 변환되어 실제 객체로 존재하며 함수로도 표현 가능하고 실제 값으로도 사용될 수 있다.

💥 enum과 union
다른 타입을 하나의 그룹으로 묶는 데 사용될 수 있으나, 그 용도와 작동 방식에 차이가 있다.

  • Enum
    • Enum은 한정된 몇 가지 선택지 중 하나를 나타내는 데 사용됩니다.
    • 일반적으로 상수 값의 집합을 정의하는 데 사용됩니다.
    • enum은 값이기 때문에 순회가 가능하다.
    • 자바스크립트로 컴파일될 때 성능에 영향을 준다는 우려가 있다.
  • union
    • Union은 여러 다른 타입 중 하나를 가질 수 있는 타입을 나타낸다.
    • 서로 다른 타입들을 하나의 그룹으로 묶을 때 사용된다.
    • 각 타입은 각각의 구성원을 가질 수 있다.
    • union 타입은 어떤 타입을 가졌는지 전부 기억해야 해 리팩토링에 번거로움이 있다.
    • union 타입은 말 그대로 타입이므로 순회가 불가능하다.

💥 type과 interface

  • type
    • type을 사용해야만 하는 경우는 union이나 intersection을 활용할 때
    • 타입 별칭을 정할 때
    • computed value를 사용할 때
    • generic type이나 literal types을 사용할 때 등이 있다.
    • scope의 제한을 두고 한정적으로 사용할 때 쓰는게 좋다.
  • interface
    • interface를 사용해야만 하는 경우는 클래스나 객체를 구조화해 명세할 때
    • 상속을 통한 타입 확장을 할 때 등이 있다.
    • 전역으로 사용할 때 사용하는게 좋다.
profile
ChatGPT-Driven Development를 지양합니다.

0개의 댓글