러닝 타입스크립트_Part 1 개념

bongbong·2023년 6월 7일
1
post-thumbnail

Chapter 1 자바스크립트에서 타입스크립트로

1.1 자바스크립트의 역사

  • 자바스크립트는 넷스케이프에서 10일만에 완성된 스크립트 언어

1.2 바닐라 자바스크립트의 함정

보조적인 기능을 목적으로 만들었기 때문에 태생적 한계가 존재.

  • 동적 분석으로 인한 자유로움 : 런타임시 타입이 정해졌고 이로 인해 예상치 못한 버그 발생
  • 문서(주석) 관리의 어려움 : JSDoc으로 변수와 함수를 설명하는 주석을 다는 방법이 있었으나 프로젝트 크기가 커질수록 관리가 어려워짐.
  • 부족한 개발자 도구

1.3 타입스크립트

  • 프로그래밍 언어 : 자바스크립트의 기능은 가지고 있으면서 type과 annotation 기능을 추가로 제공해주는 상위 언어
  • 타입 검사기 : 타입 시스템을 통해 잘못 구성된 타입에 대해 알려주는 프로그램
  • 컴파일러 : 타입스크립트로 작성된 코드를 자바스크립트로 컴파일 해주는 프로그램
  • 언어 서비스 : 타입 검사기를 사용해 IDE에서 오류를 표시하고 자동완성 기능을 도와줌.

1.4 타입스크립트 특징

  • 정적 분석 : 런타임 이전에 코드를 분석하여 IDE에서 타입 에러 및 힌트를 실시간으로 제공 받을 수 있다.
  • 타입 지정 : 코드를 지정한 방법으로만 사용하도록 제한할 수 있다.
  • 정확한 문서화 : type과 annotation을 통해 정확한 타입 정보를 제공한다.
  • 강력한 개발자 도구 : IDE에 타입스크립트를 지원하여 자동완성, 타입 힌트, 타입 에러를 실시간으로 제공해주어 개발자가 더 편리하게 코드 작성이 가능해진다.

1.5 로컬에서 시작하기

  • 전역에 설치
    • tsc(타입스크립트 컴파일러) 사용 가능해짐
npm i -g typescript
  • 설치 및 버전 확인
tsc --version
  • 로컬에서 실행 및 세팅
    • tsconfig.json 파일 생
tsc --init

1.6 타입스크립트에 대한 오해

  • 코드 스타일 의견을 강요하지 않으며, 특정 앱 프레임워크와도 연관되어 있지 않는다.
  • 런타임 시에는 코드에 영향을 주지 않고, 개발시에만 사용되는 주석 형태로 작동한다.
  • 타입스크립트는 빌드시 자바스크립트로 컴파일되며, 자바스크립트 런타임에는 영향을 끼치지 않는다.

Chapter 2 타입 시스템

2.1 타입의 종류

  • 타입 : 값의 형태
  • null, undefined, boolean, string, number, bigint, symbol
  • 초깃값을 갖는 변수의 타입을 유추한다.

2.1.1 타입 시스템

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

2.1.2 오류 종류

  • 구문 오류 : 잘못된 문법으로 인해 javascript로 컴파일 되지 못하도록 차단한 경우
  • 타입 오류 : 타입 검사기에 따라 일치하지 않는 것이 감지된 경우

2.2 할당 가능성

  • 할당된 값이 예상 가능한 타입인지 확인하는 것.

2.2.1 할당 가능성 오류 이해하기

  • Type X is not assignable to type Y
  • 할당하려는 X 타입이 이미 할당되어 있는 Y 타입과 일치하지 않아서 생기는 오류로 가장 일반적인 오류

2.3 타입 애너테이션

  • 변수에 초깃값을 설정하지 않으면 any 타입으로 지정
  • any는 모든 타입이 들어올 수 있기 때문에 타입스크립트를 쓰는 이유가 없어진다.
  • 초깃값이 없는 변수에는 타입 애너테이션 설정으로 타입 선언이 가능
let rocker :string;
rocker = "seyoung";

2.3.1 불필요한 타입 애너테이션

  • 타입스크립트는 원시타입에 대해 자동 추론이 가능하다.
    • undefined, null, boolean, string, number, symbol, bigint
  • 변수가 명확한 타입일 때는 자동으로 유추하기 때문에 annotation을 추가할 필요 없다.
let name : string = "seyoung";
let name = "seyoung"; // string type임을 자동으로 추론한다.

Chapter 3 유니언과 리터럴

3.1 유니언 타입

  • 상황에 따라 두 가지 이상의 타입이 쓰일 때 사용
let score = 20;
let result : string | number = scroe < 80 : "불합격" : score; 

3.2 내로잉

  • 유니언 타입 설정으로 타입이 2가지가 되어버린 상황에서 타입을 명확하게 좁힐 때 사용
  • 내로잉 방법
    • 값 할당을 통한 내로잉

      let inventory : string | number = "water";
      
      inventory.toUppercase(); //WATER
      
      invertory.toFixed();
      // Error : Property 'toFixed; does not exist on type 'string'
    • 조건 검사를 통한 내로잉

    • typeof 검사를 통한 내로잉

3.3 리터럴 타입

  • 값 자체를 타입으로 사용하는 것

  • 변수가 제한된 값들을 가질 때 안전하게 제한하여 사용할 수 있다.

  • 유니온 타입으로 지정

type btnType = "default" | "error";
type btnColor = "red" | "black" | "green";
type btnStyele = `${btnType}-${btnColor}`
  • const 로 변수 선언

const는 변경이 불가능typescript에서 자동으로 literal type으로 추론한다.

  • const assertion(const 단언, 주장)

as const 를 변수 선언 후 뒤에 추가하면 literal type으로 추론해준다.

const Color = {
	red : "FF2031",
	black : "000000"
} as const

3.4 엄격한 null 검사

  • null 또는 undefined가 될 수 있는 경우를 타입스크립트에서는 엄격하게 검사하고 있으며 이를 해결하기 위해서는 참 검사를 통한 내로잉을 할 수 있다..

3.5 타입 별칭

type RawData = boolean | number | string | null
  • type도 javascript 변수처럼 별칭을 만들어서 선언할 수 있다.
    • 그러나 javascript 가 아니라는 점을 주의.
    • 개발시에만 사용되는 코드이며 실제 런타임 코드에서는 참조할 수 없다.
  • 선언한 type은 재사용이 가능하다.
  • 파스칼케이스로 이름을 지정한다.
  • 타입 별칭은 결합이 가능하다
type Id = number | string;
type IdMaybe = Id | undefined | null;

Chapter 4 객체

  • 복잡한 객체 형태를 설명하는 방법
  • 타입스크립트가 객체의 할당 가능성을 확인하는 방법

4.1 객체 타입

4.1.1 객체 타입 선언

  • 객체 타입을 명시적으로 선언하기
let poetLate :{
    born:number;
    name:string;
} = {
    born:1935,
    name:"seyoung"
}

4.1.2 별칭 객체 타입

  • 객체 타입 선언 방법은 코드가 길어지면서 가독성이 떨어지며 재사용성도 떨어지기 때문에 보통 타입 별칭을 할당해 사용하는 방법이 일반적.
type Poet = {
    born:number;
    name:string;
}

let poetLate :Poet = {
    born:1995,
    name:"seyoung"
}

4.2 구조적 타이핑

  • 구조적 타이핑 : 런타임 이전에 타입체크를 하는 것.
  • 덕 타이핑 : 런타임 때 타입체크를 하는 것.

4.2.1 사용 검사

  • type에 설정된 프로퍼티를 잘 사용했는지 검사한다.
    • type에 설정한 property를 모두 사용했는지
    • 설정한 type이 맞는지
type FirstAndLastNames = {
    first: string;
    last : string;
}

const hasBoth : FirstAndLastNames = {
    first:"Sarojini",
    last:"Naidu"
}

const hasOnlyOne : FirstAndLastNames = {
    first:"Sappho"
    // Error : 
		// Property 'last' is missing in type '{ first: string; }' but required in type 'FirstAndLastNames'.
}

4.2.2 초과 속성 검사

  • 예상되는 타입 이외에 초과 속성을 설정하면 타입 오류가 발생한다.
  • 기존 객체 리터럴을 제공하면 초과 속성 검사를 우회한다.
type Poet = {
    born : number;
    name : string;
}

const existingObject = {
    activity : "walking",
    born:1233,
    name:"seyoung"
}

const extraPropertyButOk: Poet = existingObject;

4.2.3 중첩된 객체 타입

  • 중첩된 객체의 type을 따로 추출하면 에러 메세지를 읽을 때 가독성 더 좋아진다.
type Author = {
    firstName : string;
    lastName: string;
}

type Poem = {
    author : Author;
    name: string;
}

const PoemMismatch : Poem = {
    author : {
        name:"seyoung"
        // Error : Type '{ name: string; }' is not assignable to type 'Author'.
        // Object literal may only specify known properties, and 'name' does not exist in type 'Author'.
    },
    name:"young"
}

4.2.4 선택적 속성

  • 선택적 속성으로 : 앞에 ? 를 추가하면 해당 속성은 생략가능해진다.

4.3 객체 타입 유니언

4.3.1 유추된 객체 타입 유니언

  • 변수에 여러 객체 타입 중 하나가 될 수 있는 초깃값이 할당되면 타입스크립트는 객체 타입 유니언으로 유추한다.
const poem = Math.random() > 0.5 ? { name:"크다", pages:7} : { name:"작다", rhymes:true}

// 타입스크립트가 자동으로 추론한 타입
// {
//     name: string;
//     pages: number;
//     rhymes?: undefined;
// } | {
//     name: string;
//     rhymes: boolean;
//     pages?: undefined;
// }

4.3.2 명시된 객체 타입 유니언

  • 위의 자동 추론된 타입에서는 rhymes와 pages가 존재하지 않을 때도 접근이 가능하다.
  • 객체 타입 유니언을 명시해줌으로써 존재하지 않는 속성에 대한 접근을 막아 코드의 안전을 지킬 수 있다.
type PoemWithPages = {
    name:string;
    pages:number;
}

type PoemWithRhymes = {
    name:string;
    rhymes:boolean;
}
type Poem = PoemWithPages | PoemWithRhymes;
const poem: Poem = Math.random() > 0.5 ? { name:"크다", pages:7} : { name:"작다", rhymes:true}

4.3.3 객체 타입 내로잉

  • 객체 타입 유니온도 내로잉을 통해 타입을 좁혀야줘야 한다.
type PoemWithPages = {
    name:string;
    pages:number;
}

type PoemWithRhymes = {
    name:string;
    rhymes:boolean;
}
type Poem = PoemWithPages | PoemWithRhymes;
const poem: Poem = Math.random() > 0.5 ? { name:"크다", pages:7} : { name:"작다", rhymes:true}

if("pages" in poem){
    console.log(poem.pages) // PoemWithPages로 좁혀짐
} else {
    console.log(poem.rhymes) // PoemWithRhymes로 좁혀짐
}

4.3.4 판별된 유니언

  • type의 속성을 객체의 형태로 나타낼 수 있다.
type PoemWithPages = {
    name:string;
    pages:number;
    type:'pages';
}

type PoemWithRhymes = {
    name:string;
    rhymes:boolean;
    type:'rhymes';
}

type Poem = PoemWithPages | PoemWithRhymes;
const poem: Poem = Math.random() > 0.5 
    ? { name:"크다", pages:7, type:'pages'} 
    : { name:"작다", rhymes:true, type:'rhymes'}

if(poem.type === "pages"){
    console.log("pages")
} else {
    console.log("rhymes")
}

4.4 교차 타입

  • 유니온 타입이 | 연산자로 둘 중 하나의 타입을 나타낸다면
  • & 연산자로 여러 타입을 묶어서 교차시키는 것도 가능하다.
  • & , | 연산자를 결합하여 타입을 표현할 수도 있다.

4.4.1 교차 타입의 위험성

  • assignable error(할당 가능성 오류) 메세지가 길어지면서 읽기 어려워 질 수 있다.
  • type을 분리하여 별칭 이름으로 오류 메세지가 뜨게 하면 읽기가 훨씬 쉬워진다.
type ShortPoemBase = {author : string};
type Haiku = ShortPoemBase & {kiho : string; type :'haiku'}
type Villanelle = ShortPoemBase & {meter : number; type :'villanelle'}
type ShortPoem = Haiku | Villanelle;
  • 원시타입에서 교차타입을 지정하면 never 타입이 된다.
    • never타입은 어떠한 값도 제공할 수 없다는 의미
    • 코드에서 불가능한 상태를 나타낼 때 제공

0개의 댓글