타입스크립트 (2) - 기본형, 배열, any, 함수

김태완·2024년 11월 7일

기본형

  • 기본형의 종류는 아래와 같이 나타낼 수 있다.
  • 이때 변수의 이름 뒤에 콜론(:)과 함께 변수의 타입을 정의하는 문법을 '타입 주석' 또는 '타입 어노테이션' 이라고 부른다.
number

  • number 타입은 자바스크립트에서 숫자를 의미하는 모든 값을 포함하는 타입이다. 단순 정수 뿐만 아니라 소수, 음수, Infinity, NaN등의 특수한 숫자들도 포함한다.
  • number 타입으로 정의한 변수에는 number 타입을 제외한 값을 할당할 수 없으며, number 타입의 값이 사용할 수 없는 toUpperCase 등의 메서드는 사용할 수 없다.
string

  • string 타입은 문자열을 의미하는 타입이다. 단순 쌍따옴표 문자열 뿐만 아니라 작은 따옴표, 백틱, 템플릿 리터럴로 만든 모든 문자열을 포함한다.
boolean

  • boolean 타입은 참과 거짓만을 저장하는 타입이다. true 또는 false만 이 타입에 해당된다.
리터럴

  • 딱 하나의 값만 포함하는 타입도 존재한다. 다음과 같이 변수의 타입을 숫자 10으로 설정하는 것 또한 가능하다.
  • 변수 numA의 타입을 숫자 10으로 설정했다. 이렇게 설정하면 이제 numA에는 10 이외의 값을 저장할 수 없게 된다.
  • 이렇듯 하나의 값만 포함하도록 값 자체로 만들어진 타입을 ‘리터럴 타입’이라고 부릅니다.
  • 숫자 값 뿐만 아니라 문자열이나 boolean 타입의 값도 모두 리터럴 타입으로 만들 수 있다.
null, undefined

  • null 타입은 오직 null 값만 포함하는 타입이다.
  • undefined 타입 역시 null 타입과 마찬가지로 오직 하나의 값 undefined만 포함하는 타입이다.
  • undefined와 null이 서로 다른 값이듯 타입도 서로 다르다.
    • 참고로 자바스크립트에서는 특별한 숫자들이 있는데,
      예를 들어,
      숫자를 0으로 나누거나(infinity),
      0을 0으로 나누었을때(NaN)
      이것들도 모두 number 타입이다.
      그래서 만약 잘못된 값이 걱정된다면 number 타입을 검사하는 것만으로 충분하지않고 number에 있는 is 메소드를 활용해야한다.

null 값을 변수의 임시값으로 활용하고 싶다면?

  • tsconfig.json 파일의 strictNullChecks 옵션을 false로 설정하면 된다.
  • strictNullChecks 옵션은 타입스크립트에서 null 값을 null 타입 이외의 타입의 변수에 할당하는 것을 금지할지 허락할지 여부를 결정하는 옵션이다.
  • 기본값은 true이며 이 옵션이 true로 켜져있을 경우 엄격하게 null 값을 검사해 null 타입이 아닌 변수에는 null 값을 할당할 수 없도록 제한한다. 그런데 false로 설정해 이 옵션을 끌 경우 어떤 타입의 변수든 null 값을 자유롭게 할당할 수 있다.
  • 또 이 옵션은 strict 옵션의 하위 옵션이다. 따라서 strict 옵션이 true이면 자동으로 true로 설정되며, 반대로 strict 옵션이 false이면 자동으로 false로 설정된다.

배열과 튜플

  • 배열을 저장하는 변수의 이름 뒤에 타입 주석의 시작을 의미하는 콜론(:)을 작성한 다음 배열요소타입[] 형식으로 배열 타입을 정의한다.
  • 또는 Array<배열요소타입> 형태로도 배열의 타입을 정의할 수 있다. 이렇게 꺽쇠와 함께 타입을 작성하는 문법을 타입스크립트에서는 ‘제네릭’ 이라고 부릅니다. 위 두가지 방법은 모양만 다를뿐 기능은 동일하다.
  • 만약 배열에 들어가는 요소들의 타입이 다양하다면????
    • 소괄호와 바(|) 를 이용해 배열 요소가 둘 중 하나의 타입에 해당하도록 타입을 정의하면 된다.
    • 이때 (…)[] 형식에서 소괄호는 앞서 배열 요소의 타입을 의미하고, 소괄호 내부의 number | string은 배열 요소의 타입이 stirng이거나 number 일 것을 의미한다.
    • 따라서 이렇게 정의한 배열 타입은 요소가 number 타입이거나 string 타입이어야 한다.
    • 이렇듯 바(|)를 이용해 여러 타입중 하나를 만족하는 타입을 정의하는 문법을 유니온(Union) 타입 이라고 부릅니다.
  • 문자열 배열 타입을 만들고 싶다면 타입을 먼저 쓰고 대괄호를 열었다가 닫으면 된다.
    • 여기에다가 문자열을 푸시하다가 실수로 숫자형을 푸시하면 타입오류가 발생한다.
  • 배열의 배열도 어렵지 않아요! (다차원 배열)
    • 앞의 타입을 하나의 타입으로보고 뒤에다가 대괄호를 열었다가 닫으면 된다.
  • 배열타입에는 크기가 정해져 있지 않다.
    • 그래서 mySize 처럼 갯수가 다르거나 없더라도 오류가 발생하지 않는다.
    • 만약, 배열이지만 개수를 명확하게 하고 싶다면 튜플 타입을 쓰면 된다.
    • 튜플타입은 마치 배열의 값을 정하듯이 쓰면 되는데, 다른점은 요소 자리에 타입이 들어간다는 것이다.
    • 숫자형 두개로 된 튜플로 타입을 정했기 때문에 갯수가 다르거나 혹은 타입이 다르면 타입오류가 생긴다.
    • 참고로 튜플은 모두가 꼭 같은 타입일 필요는 없다.
  • 튜플도 결국 배열이다. tsc를 이용해 튜플 타입이 정의된 타입스크립트 코드를 컴파일 해 보면 결국 튜플은 자바스크립트 배열로 변환되는 것을 확인할 수 있다.
  • 그러므로 배열 메서드인 pushpop을 이용해 고정된 길이를 무시하고 요소를 추가하거나 삭제할 수 있다.
    • 튜플은 길이와 타입이 고정되어있다며???
      -> 튜플에 배열 메서드를 사용하면 길이 제한이 발동하지 않는다. 자바스크립트의 배열이라고 생각하기 때문이다.
    • 이런 경우 튜플 활용하면 좋을 듯!(실수를 빨리 잡을 수 있다.)

튜플 타입과 다차원 배열을 헷갈리지 말자!
1. 다차원 배열
ex) const matrix: number[][] = [[1, 2], [3, 4]];
다차원 배열에는 위 코드처럼 [ ] 를 두번 사용합니다. 즉, number 배열로 이루어진 배열이라는 뜻이죠.
그래서 내부의 값에 접근할 때 인덱스를 두번 사용하죠?
matrix[0][1]; // 2
2. 튜플
- 튜플은 배열 "하나"에 안에 들어가는 요소의 타입과 갯수를 지정한거에요.
const score: [string, number] = ["blue team", 19];
- 그럼 당연히 배열 하나니까 인덱스를 하나만 사용해서 접근할 겁니다.
score[1] // 19
- 인덱스를 두번 써서 접근하는 건 튜플 타입 선언 뒤에 대괄호를 하나 더 붙여서 배열로 만들면 됩니다.
const scores: [string, number][] = [["blue team", 19], ["red team", 10]];
이렇게 선언하면 아래처럼 인덱스 두개를 써서 접근하게 됩니다.
score[1][0] // red team

  • 튜플은 선언을 할 때 값의 개수도 함께 지정합니다. 그래서 push 메소드로 튜플의 길이를 늘리려고 하면 오류가 납니다.

객체 타입

  • 객체에 값을 할당할때랑 비슷한 문법이다.
  • 값 대신에 타입을 쓰고 세미콜론을 쓴다는 점이 다르다.
  • 객체 타입을 정하면 프로퍼티를 외우고 있지 않아도 vscode에서 프로퍼티 네임을 추천해준다.(Ctrl + i)
  • 이렇게 객체 타입을 정의하는 방법은 2가지가 있다.
      1. object로 정의하기
      • user의 타입을 객체를 의미하는 object로 정의한다.
      • 그런데 이렇게 하면 user.id 처럼 점 표기법으로 객체의 특정 프로퍼티에 접근하려고 하면 오류가 발생한다.
      • 왜냐하면 object 타입은 단순 값이 객체임을 표현하는 것 외에는 아무런 정보도 제공하지 않기 때문이다!("이 변수가 객체이긴 한데...그 이상은 잘 몰라!!!")
      1. 객체 리터럴 타입

        - 변수 user의 타입을 number 타입의 id 그리고 string 타입의 name 프로퍼티를 갖는 객체 타입으로 정의했다. 이렇듯 객체 리터럴과 비슷한 문법으로 객체 타입을 정의한 타입을 객체 리터럴 타입이라고 부른다.
        - 변수의 타입을 객체 리터럴 타입으로 정의하면 이제 타입내에 정의되어있는 프로퍼티에 이상 없이 접근할 수 있게 된다. 지금은 점 표기법으로 접근했지만 괄호 표기법을 사용할 때에도 동일하게 잘 접근된다.

        여기서 한가지 알 수 있는 사실은 타입스크립트는 기존의 정적 타입 시스템을 따르는 언어인 C나 Java(명목적 타입 시스템)와는 달리 객체의 타입을 정의할 때 프로퍼티를 기준으로 객체의 구조를 정의하듯이 타입을 정의한다는 점이다.
        타입스크립트의 이런 특징을 구조적 타입 시스템이라고 부른다. 객체의 구조를 결정하는 것은 프로퍼티입니다. 따라서 타입스크립트는 이 객체에 어떤 프로퍼티들이 있어야 하는지 정의하는 방식으로 객체의 타입을 정의한다.

  • 가끔 객체에서 어떤 프로퍼티는 필수가 아닌 경우가 있다.
    • 조건에 따라 동작하는 프로퍼티가 있다면 변수 옆에 ?를 붙여서 옵셔널 프로퍼티를 사용한다.

      정리하자면,
      객체 타입은 { } 안에 프로퍼티 이름을 적고, 콜론 뒤에 프로퍼티 값의 타입을 적습니다. 객체 타입에서 각 프로퍼티는 쉼표가 아닌 세미콜론으로 구분한다.

  • 특정 프로퍼티를 읽기 전용으로 만들고 싶다면 프로퍼티의 이름 앞에 readonly 키워드를 붙이면 된다.
    • 읽기 전용 프로퍼티는 프로퍼티의 값을 수정하려고 하면 오류가 발생하게 된다. 이를 통해 의도치 않은 프로퍼티의 수정을 방지할 수 있다.
  • 그리고 자바스크립트 문법에서 객체에 값을 할당할때 프로퍼티 이름에 변수를 쓰고 싶으면 대괄호를 쓰는데,타입스크립트에도 비슷한 문법이 있다.
  • 프로퍼티의 개수를 알 수 없거나, 개수를 정해놓고 싶지 않은 경우에 프로퍼티 값에 타입만 지정할 수 있다.
  • 이전에는 객체 타입을 정할 때 프로퍼티 이름을 정확하게 적어줬지만 이번에는 프로퍼티 이름으로 아무 문자열이나 쓸수 있도록 정해줄 수 있다.
  • 그래서 여러 값들을 넣어 줄 수 있는데 만약 타입에 맞지 않는 값을 넣으면 타입오류가 발생한다.

타입 별칭(Type Alias)

  • 타입 별칭을 이용하면 변수를 선언하듯 타입을 별도로 정의할 수 있다.
  • type 타입_이름 = 타입 형태로 타입을 정의한다.
  • 참고로 동일한 스코프에 동일한 이름의 타입 별칭을 선언하는 것은 불가능합니다. 마치 변수 선언과 유사하다.
  • 그러나 스코프가 다르다면 중복된 이름으로 여러개의 별칭을 선언해도 상관 없다.

인덱스 시그니쳐(Index Signature)

  • 객체 타입을 유연하게 정의할 수 있도록 돕는 특수한 문법이다.
  • 이렇게 프로퍼티가 엄청 많아지면 타입 정의에도 각 프로퍼티를 모두 정의해줘야 하기에 불편하다.
  • 이렇게 인덱스 시그니쳐를 이용하면 다음과 같이 간단하게 타입을 정의할 수 있다.
    • [key : string] : string 은 인덱스 시그니쳐 문법으로 이 객체 타입에는 key가 string 타입이고 value가 string 타입인 모든 프로퍼티를 포함된다 라는 의미이다.

any

  • 특별한 타입이 있다.
  • 타입스크립트에서 없는 변수를 출력하려고 하면 타입 오류가 뜬다.
  • 그런데 자바스크립트에서는 오류가 안뜨지.
  • 그래서 자바스크립트랑 똑같은 상태로 만들어 주는 타입이 있다.
  • 바로 any 이다. (타입 검사를 받지 않는 특수한 타입)
  • product 변수를 any로 만들면 타입 오류가 사라진다.
  • 이렇듯 any 타입은 타입 검사를 받지 않기에 아무 타입의 값이나 범용적으로 담아 사용할 수 있고, 다양한 타입의 메서드도 마음대로 호출해서 사용해도 문제가 되지 않는다.
  • 또한, any 타입의 값은 어떤 타입으로 정의된 변수던 문제 없이 다 할당할 수 있다.
  • 그럼 무조건 any를 쓰면 되느냐??
  • 타입스크립트를 쓰는 이유는 타입검사를 해서 오류를 미리 발견하는 것이다.
  • 그래서 되도록 any는 사용하지 않는게 좋지만, 어쩔수없이 타입이 any가 될때가있다.
  • 예를들어 JSON.parse 함수에서는 어떤 문자열이 어떤 객체 타입으로 될지 알 수 없어서 그 결과값이 any 타입이다.
  • 이럴때도 anmy타입을 그대로 쓰기보다는 타입을 정의해주는 것이 좋다. 아래와 같이 3가지 방법이 있다.
    1) 일반변수에 :을 써서 타입을 정해주는 방법

    2) 값 뒤에다가 as 라는 키워드를 써서 타입을 정해주는 방법

    3) 값에다가 타입을 정하는데, 값 앞에 꺽쇠를 열고 타입 적고 꺽쇠를 닫는 방법(문법적인 문제로 잘 쓰지않아!)

함수에 타입 정의하기

  • tsconfig 파일에 "strict": true로 되어있으면 noImplicitAny가 true 로 되어있다.
  • 이 옵션은 암묵적으로 any를 선언하는 것을 방지하는 옵션이다.
  • 그래서 이 상태에서 함수의 타입을 선언하지 않으면 암묵적으로 애니를 선언하는 것이라 타입 오류가 난다.
  • 파라미터의 타입을 정할때는 파라미터 이름 옆에 : 을 쓰고 타입을 적어준다.
  • 마찬가지로 함수의 리턴 타입은 괄호 다음에 : 을쓰고 타입을 적어주면 된다.
  • 그런데 만약 파라미터에 기본값을 준다면 그냥 파라미터에 곧바로 기본값 적어도 된다.

이번에는 함수 자체에 타입을 정해보자
이거는 화살표 문법이랑 비슷하다.

  • 레스트 파라미터를 사용하는 경우에 타입을 지정할때는 일반적인 파라미터에 타입을 지정하듯이 : 을 써주고, 이번에는 레스트 파라미터니깐 배열로 지정해준다.
  • 그런데 리턴 값이 없다면 비워두면 안되고 void를 적어둬야한다.

정리한번하자

  • 배열과 튜플
    배열 타입을 만들려면 타입을 적고 [ ]를 붙입니다.
    만약에 배열의 배열을 만들고 싶다면 배열 타입 뒤에 [ ]를 붙이면 됩니다.
    튜플은 개수랑 순서가 정해져 있는 배열입니다.
    [ ] 안에 순서대로 타입을 쉼표로 구분해서 씁니다.
    // 배열
    const cart: string[] = [];
    cart.push('c001');
    cart.push('c002');
    // 배열의 배
    const carts: string[][] = [
    ['c001', 'c002'],
    ['c003'],
    ];
    // 튜플
    let mySize: [number, number, string] = [175, 30, 'L'];

  • 객체 타입
    { } 안에다가 프로퍼티 이름을 쓰고 콜론 다음에 타입을 씁니다. 각 프로퍼티는 세미콜론으로 구분합니다.
    필수가 아닌 프로퍼티는 프로퍼티 이름 뒤에 물음표를 붙입니다.
    let product: {
       id: string;
       name: string;
       price: number;
       membersOnly?: boolean; // 필수가 아닌 프로퍼티
       sizes: string[];
     } = {
      id: 'c001',
      name: '코드잇 블랙 후디',
      price: 129000,
      sizes: ['M', 'L', 'XL'],
    };
    if (product.membersOnly) {
       console.log('회원 전용 상품');
    } else {
       console.log('일반 상품');
    }

  • 프로퍼티의 개수를 정하지 않고, 프로퍼티 값의 타입을 정하고 싶다면 아래와 같은 문법을 활용해 보세요.
    let stock: { [id: string]: number } = {
      c001: 3,
      c002: 0,
      c003: 2,
    };

  • any 타입
    • 자바스크립트를 사용할 때와 마찬가지로 자유롭게 쓸 수 있는 타입입니다.
    • 되도록이면 any 타입으로 지정하지 않는 것을 권장합니다.
    • 어쩔 수 없이 any 타입을 사용하는 경우 as 키워드를 써서 타입을 지정하거나, 콜론으로 타입을 지정할 수 있습니다.


      const parsedProduct = JSON.parse('{ "name": "코드잇 토트백", "price": 12000 }') as { name: string; price: number };


      const parsedProduct: { name: string; price: number } = JSON.parse('{ "name": "코드잇 토트백", "price": 12000 }');

  • 함수 타입
    리턴 타입을 지정하는 경우에는 다음 코드처럼 작성하면 됩니다.
    function addToCart( id: string, quanity: number): boolean  {
      if (어떤 조건) {
        return false;
      }
      return true;
    }

    • 리턴 타입을 미리 주지 않고 리턴 값으로부터 추론하게 할 수도 있습니다.
      function addToCart(id: string, quanity: number) {
         if (어떤 조건) {
        return false;
        }
        return true;
      }

  • 함수를 값으로 사용하는 경우 화살표 함수처럼 작성합니다.
    (id: string, quanity: number) => boolean
  • Rest 파라미터는 배열 타입으로 씁니다. 값을 리턴하지 않는 경우 리턴 타입을 void로 할 수 있습니다.
    (...ids: string[]) => void;

이미지 출처: <한 입 크기로 잘라먹는 타입스크립트>
https://www.inflearn.com/course/%ED%95%9C%EC%9E%85-%ED%81%AC%EA%B8%B0-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8?inst=68d752f7&utm_source=instructor&utm_medium=referral&utm_campaign=inflearn_%ED%8A%B8%EB%9E%98%ED%94%BD_promotion-link

profile
중고

0개의 댓글