TypeScript κΈ°λ³Έ


🌟 JS의 문제점

  • μžλ£Œν˜•μ„ λ„˜λ‚˜λ“œλŠ” 계산을 μˆ˜ν–‰ν•œλ‹€.
  • λ”°λΌμ„œ λ‹€μŒκ³Ό 같은 μ½”λ“œμ—μ„œ μ—λŸ¬λ₯Ό 보여주지 μ•ŠλŠ”λ‹€.
  • νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œλŠ” λ‹€μŒκ³Ό 같이 μ—λŸ¬λ₯Ό 보여쀀닀.
  • TS 컴파일 방법

  • npx tsc (νŒŒμΌμ΄λ¦„).ts
  • tsc -w
  • κ·ΈλŸ¬λ‚˜ Reactμ—μ„œ μ‚¬μš© μ‹œ μ• μ΄ˆμ— typescript둜 μ„ΈνŒ…ν•˜λ©΄ μ΄λŸ¬ν•œ 것듀을 ν•΄μ£Όμ§€ μ•Šμ•„λ„ λœλ‹€.
  • πŸ₯•Β κΈ°λ³Έ νƒ€μž…

    κΈ°λ³Έ νƒ€μž… μ§€μ • 방법

    const car: string = 'bmw';
    const age: number = 30;
    const a: number[] = [1, 2, 3];
    const a2: Array<number> = [1, 2, 3];
    const week1: string[] = ['mon', 'tue', 'wed'];
    const week2: Array<string> = ['mon', 'tue', 'wed']; // Generic
    week1.push(1); // ERROR
  • 기본적인 JSλ¬Έλ²•μ—μ„œ λ³€μˆ˜λͺ… 뒀에 :λ₯Ό μ΄μš©ν•˜μ—¬ νƒ€μž…μ„ λΆ™μ—¬μ€€λ‹€.
  • ν•΄λ‹Ή λ³€μˆ˜μ—λŠ” λΆ™μ—¬μ€€ νƒ€μž…μ˜ λ°μ΄ν„°λ§Œ ν• λ‹Ήν•  수 μžˆλ‹€.
  • λ”°λΌμ„œ μœ„ μ½”λ“œμ—μ„œ week1 배열에 숫자 νƒ€μž… 데이터λ₯Ό pushν•˜λ©΄ μ—λŸ¬κ°€ λ‚œλ‹€.
  • λ°°μ—΄μ˜ νƒ€μž…μ€ λ°μ΄ν„°νƒ€μž…[] λ˜λŠ” Array<λ°μ΄ν„°νƒ€μž…>으둜 κ²°μ •ν•  수 μžˆλ‹€.
  • νŠœν”Œ (Tuple)

    let b: [string, number];
    b = ['abc', 1];
    b = [1, 'abc']; // ERROR
    b[0].toLowerCase();
    b[1].toLowerCase(); // ERROR
  • νŠœν”Œμ€ 각 μš”μ†Œμ˜ νƒ€μž…μ΄ κ³ μ •λœ 배열이닀.
  • νŠœν”Œμ€ λ°°μ—΄μ˜ 길이도 κ³ μ •λ˜μ–΄ μžˆλ‹€.
  • μœ„ μ½”λ“œμ—μ„œ bλΌλŠ” λ°°μ—΄μ˜ 0번 μΈλ±μŠ€μ—λŠ” string νƒ€μž…λ§Œ, 1번 μΈλ±μŠ€μ—λŠ” number νƒ€μž…λ§Œ ν• λ‹Ή 될 수 μžˆλ‹€.
  • λ”°λΌμ„œ 0번 μΈλ±μŠ€μ— number νƒ€μž…μ„ ν• λ‹Ήν•˜λ©΄ μ—λŸ¬κ°€ λ‚œλ‹€.
  • .toLowerCase()λŠ” string νƒ€μž…μ—λ§Œ μ‚¬μš©ν•  수 μžˆλŠ” λ©”μ†Œλ“œ μ΄λ―€λ‘œ b[1](number νƒ€μž…)에 ν•΄λ‹Ή λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ μ—λŸ¬κ°€ λ‚œλ‹€.
  • Null, Undefined

    const n: null = null;
    const u: undefined = undefined;
  • null λ˜λŠ” undefined νƒ€μž…λ„ 선언해쀄 수 μžˆλ‹€.
  • Enum

  • Enum(μ—΄κ±°ν˜•)은 μ—°κ΄€λœ μ•„μ΄ν…œλ“€μ„ λ¬Άμ–΄μ„œ ν‘œν˜„ν•  수 μžˆλŠ” μˆ˜λ‹¨μ΄λ‹€.
  • enum Os { // 보톡 enum의 이름은 λŒ€λ¬Έμžλ‘œ μ‹œμž‘ν•œλ‹€.
    Window,
    Ios,
    Android,
    }
    let myComputer: Os;
    myComputer = Os.Window;
    myComputer = 'Window'; // ERROR
    console.log(myComputer); // 0
  • μ˜ˆμ‹œλ‘œ Os λΌλŠ” enum을 μƒμ„±ν•˜λ©΄, 이λ₯Ό νƒ€μž…μ²˜λŸΌ μ‚¬μš©ν•  수 μžˆλ‹€.
  • enum의 이름을 myComputerλΌλŠ” λ³€μˆ˜μ— νƒ€μž…μœΌλ‘œ μ„ μ–Έν•˜λ©΄ ν•΄λ‹Ή enum의 λ‚΄μš©λ§Œ ν• λ‹Ήν•  수 μžˆλ‹€.
  • λ”°λΌμ„œ λ¬Έμžμ—΄λ‘œ β€˜Window’라고 μ μ–΄μ„œ ν• λ‹Ήν•œλ‹€κ³  해도 μ—λŸ¬κ°€ λ‚œλ‹€.
  • 그런데 μ—¬κΈ°μ„œ myComputerλ₯Ό μ½˜μ†”μ— μ°μ—ˆμ„ λ•Œ 0이 λ‚˜μ˜€λŠ” μ΄μœ λŠ” ν•΄λ‹Ή enum이 숫자 μ—΄κ±°ν˜•μ΄κΈ° λ•Œλ¬Έμ΄λ‹€.
  • // 숫자 μ—΄κ±°ν˜•
    enum Os {
    Window = 1,
    Ios,
    Android = 10,
    }
    console.log(Os.Window); // 1
    console.log(Os.Ios); // 2
    console.log(Os.Android); // 10
  • enum의 각 ν‚€μ›Œλ“œλ“€μ΄ κ°’μœΌλ‘œ κ°–λŠ” μˆ«μžλŠ” λ‹€μŒμ²˜λŸΌ 지정해쀄 수 μžˆλ‹€.
  • μ§€μ •λ˜μ§€ μ•ŠμœΌλ©΄ 이전 κ°’μ˜ λ‹€μŒ 값을 κ°€μ§„λ‹€.
  • // λ¬Έμžμ—΄ μ—΄κ±°ν˜•
    enum Os {
    Window = 'Window',
    Ios = 'Ios',
    Android = 'Android',
    }
    console.log(Os.Window); // Window
    console.log(Os.Ios); // Ios
    console.log(Os.Android); // Android
  • λ¬Έμžμ—΄ μ—΄κ±°ν˜•μœΌλ‘œ μœ„μ²˜λŸΌ μ„ μ–Έν•˜λ©΄ 각각의 ν‚€μ›Œλ“œκ°€ λ¬Έμžμ—΄μ„ κ°’μœΌλ‘œ 갖도둝 ν•  수 μžˆλ‹€.
  • Any

  • λͺ¨λ“  νƒ€μž…μ— λŒ€ν•˜μ—¬ ν—ˆμš©ν•œλ‹€.
  • κΈ°μ‘΄ μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μž‘λ™ν•˜λ˜ μ„œλΉ„μŠ€λ₯Ό μ μ§„μ μœΌλ‘œ TS둜 λ³€ν™˜ν•  λ•Œ ν™œμš©λœλ‹€.
  • let str: any = 'hi';
    let num: any = 12;
    let arr: any = [1, 2];

    Object

  • κ°μ²΄λŠ” λ‹€μŒμ²˜λŸΌ νƒ€μž…μ„ μ •ν•΄ 쀄 수 μžˆλ‹€.
  • let jkeObj: { name: string; age: number; hobbies: string[] } = {
    name: 'jke',
    age: 27,
    hobbies: ['Music', 'BasketBall'],
    };
  • νƒ€μž…μ„ μ§€μ •ν•˜λŠ” λΆ€λΆ„μ—μ„œλŠ” , λŒ€μ‹  ;λ₯Ό μ‚¬μš©ν•œλ‹€.
  • Union

  • μ—¬λŸ¬ νƒ€μž… λ˜λŠ” 값이 λ“€μ–΄μ˜¬ 수 μžˆλ„λ‘ ν•  수 μžˆλ‹€.
  • // Union
    let unionType: number | string | number[] = 1;
    unionType = 'jke';
    unionType = 1;
    unionType = [1, 2, 3];
    // μ΄λ ‡κ²Œ μ‚¬μš© μ‹œ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ μ˜λ―Έκ°€ μ‚¬λΌμ§€λŠ” κ²ƒμ΄λ―€λ‘œ
    // μΆ”μ²œλ˜λŠ” 방법은 μ•„λ‹ˆλ‹€.
    let gender: 'M' | 'F' = 'M';
    gender = 'F';
    gender = 'T'; // error

    Void

    function sayHello(): void {
    console.log('hello');
    }
  • ν•¨μˆ˜κ°€ 아무것도 λ°˜ν™˜ν•˜μ§€ μ•ŠλŠ” 경우, void νƒ€μž…μœΌλ‘œ 선언해쀄 수 μžˆλ‹€.
  • μœ„ μ½”λ“œμ²˜λŸΌ μ„ μ–Έν•΄μ£Όλ©΄ ν•΄λ‹Ή ν•¨μˆ˜κ°€ 무언가λ₯Ό return ν•˜λ €κ³  ν•  경우 μ—λŸ¬κ°€ λ‚œλ‹€.
  • ν•΄λ‹Ή μœ„μΉ˜μ— λ‹€λ₯Έ νƒ€μž…μ„ μ„ μ–Έν•˜λ©΄ ν•΄λ‹Ή νƒ€μž…λ§Œ 리턴할 수 μžˆλ‹€.
  • Never

    function showError(): never {
    throw new Error();
    }
    function infLoop(): never {
    while (true) {
    // Do Something ...
    }
    }
  • ν•¨μˆ˜μ˜ return νƒ€μž…μœΌλ‘œ never νƒ€μž…μ„ 선언해쀄 경우 항상 였λ₯˜λ₯Ό 좜λ ₯ν•˜κ±°λ‚˜ 리턴 값을 μ ˆλŒ€λ‘œ 내보내지 μ•ŠμŒμ„ μ˜λ―Έν•œλ‹€.
  • 이λ₯Ό λ³€μˆ˜μ— μ§€μ •ν•˜λ©΄ never κ°€ μ•„λ‹Œ νƒ€μž…μ€ ν• λ‹Ήν•  수 μ—†λ‹€.
  • Unknown

    let variable: unknown
    variable = true // OK (boolean)
    variable = 1 // OK (number)
    variable = 'string' // OK (string)
    variable = {} // OK (object)
    let anyType: any = variable // OK
    let booleanType: boolean = variable
    // Error: Type 'unknown' is not assignable to type 'boolean'.(2322)
    let numberType: number = variable
    // Error: Type 'unknown' is not assignable to type 'number'.(2322)
    let stringType: string = variable
    // Error: Type 'unknown' is not assignable to type 'string'.(2322)
    let objectType: object = variable
    // Error: Type 'unknown' is not assignable to type 'object'.(2322)
  • unknown νƒ€μž…μ€ any처럼 λͺ¨λ“  νƒ€μž…μ„ ν—ˆμš©ν•œλ‹€.
  • ν•˜μ§€λ§Œ anyλŠ” νƒ€μž… 검사λ₯Ό λŠμŠ¨ν•˜κ²Œ ν•˜μ—¬ μ• ν”Œλ¦¬μΌ€μ΄μ…˜μ—μ„œ 예기치 λͺ»ν•œ λ¬Έμ œκ°€ λ°œμƒν•  κ°€λŠ₯성이 λ†’λ‹€.
  • unknown은 μœ„ 예제처럼 νƒ€μž…μ„ 체크해주기 λ•Œλ¬Έμ— any보닀 μ‚¬μš©μ΄ ꢌμž₯λœλ‹€.
  • πŸ”¦Β Advanced Type

    literal type

  • λ²”μš©μ μΈ string, number λ“±μ˜ νƒ€μž…μ΄ μ•„λ‹ˆλΌ μ •ν™•ν•œ 값을 νƒ€μž…μœΌλ‘œ μ§€μ •ν•  수 μžˆλ‹€.
  • constλ₯Ό μ‚¬μš©ν•΄ numberλ‚˜ string 등을 μ„ μ–Έν•˜λ©΄ literal type으둜 μΆ”λ‘ λœλ‹€.
  • let age:3 = 3;
    age = 5; // Error
    let name:"jke" = "jke";
    name = "jkejkejke" // Error
    // literal type으둜 μΆ”λ‘ 
    const age = 1;
    const name = "jke"

    as const

  • νƒ€μž…μ„ literal둜 μ •ν™•νžˆ μ§€μ •ν•  λ•Œ μ‚¬μš©ν•œλ‹€.
  • μ΄λ ‡κ²Œ μ§€μ •ν•˜λ©΄ μƒμˆ˜λ‘œ μ§€μ •ν•œ 값을 λ‹€λ₯Έ νŒŒμΌμ—μ„œ μž‘μ„±ν•  λ•Œλ„ λ³Ό 수 μžˆμ–΄ νŽΈν•˜λ‹€.
  • const numbers = [1,2,3] // number[]둜 μΆ”λ‘ 
    const numbers = [1,2,3] as const // [1,2,3]
    const obj = {x:1, y:2} // {x:number, y:number}
    const obj = {x:1, y:2} as const // {x:1, y:2}

    Generic

  • νƒ€μž…μ„ 인자처럼 ν™œμš©ν•  수 μžˆλ‹€.
  • μ•„λž˜ μƒν™©μ—μ„œλŠ” ν•΄λ‹Ή ν•¨μˆ˜μ— μ–΄λ–€ νƒ€μž…μ˜ arrayκ°€ λ“€μ–΄μ˜¬ μ§€ λͺ¨λ₯΄λŠ” μƒν™©μ΄μ§€λ§Œ arrayλŠ” number의 array둜 μ •μ˜λ˜μ–΄ μžˆλ‹€.
  • function map(array:number[], callback:(...args:any[]) => any;) {
    const result = [];
    for(const element of array){
    result.push(callback(element));
    };
    return result;
    }
    map([1,2,3,4], x => x + 1); // Good
    map(["hello", "world"], x => x.toUpperCase());
    // Type 'string' is not assignable to type 'number'.
  • μ΄λ ‡κ²Œ 되면 λ¬Έμžμ—΄λ‘œ 된 arrayλ₯Ό map ν•¨μˆ˜μ— 인자둜 λ„£μ–΄ μ‚¬μš©ν•˜κ³  싢을 경우 또 λ‹€λ₯Έ map ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄μ£Όμ–΄μ•Ό ν•œλ‹€.
  • 이와 같은 상황을 ν•΄κ²°ν•˜κΈ° μœ„ν•΄ Generic을 μ‚¬μš©ν•  수 μžˆλ‹€.
  • function map<T>(array:T[], callback:(...args:any[]) => any;) {
    const result = [];
    for(const element of array){
    result.push(callback(element));
    };
    return result;
    }
    map<number>([1,2,3,4], x => x + 1);
    map<string>(["hello", "world"], x => x.toUpperCase());
  • μ΄λ ‡κ²Œ ν•˜λ©΄ mapν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  λ•Œμ— νƒ€μž…μ„ λ°›μ•„ κ·Έ νƒ€μž…μ΄ array의 νƒ€μž…μœΌλ‘œ μ§€μ •λ˜λ„λ‘ ν•  수 μžˆλ‹€.
  • TλŠ” μž„μ˜μ˜ 이름이고 λ‹€λ₯Έ 이름을 μ‚¬μš©ν•΄λ„ λœλ‹€.
  • keyof

  • 객체 νƒ€μž…μ—μ„œ key만 μΆ”μΆœν•˜λŠ” 방법이닀.
  • type People = {name: string, age:number, gender:"male" | "female", hobby:string};
    type KeyOfPeople = keyof People; // name | age | gender | hobby
    const key:KeyOfPeople = 'name';
    const key2:KeyOfPeople = 'email'; // Error
  • μ£Όμ˜ν•  점은 object에 μ“°λŠ” 것이 μ•„λ‹ˆλΌ type에 μ“°λŠ” 것이닀.
  • typeof

  • 객체 λ“± κ°’μ—μ„œ νƒ€μž…μ„ μΆ”μΆœν•˜λŠ” 방법이닀.
  • const jke = {
    name:"jke",
    age:27,
    gender:"male",
    hobby:"basketball"
    };
    type People = typeof jke;
    /*
    {
    name: string;
    age: number;
    gender: string;
    hobby: string;
    }
    */
    // keyof와 typeof κ²°ν•©
    type KeyOfPeople = keyof typeof jke;
    // name | age | gender | hobby

    narrowing

  • ifλ¬Έ 등을 μ‚¬μš©ν•˜μ—¬ νƒ€μž…μ˜ λ²”μœ„λ₯Ό μ’νžˆλŠ” 방법이닀.
  • function toUpper(arg:string | number){
    arg.toUpperCase() // Error
    /*
    Property 'toUpperCase' does not exist on type 'string | number'.
    Property 'toUpperCase' does not exist on type 'number'.
    */
    }
    // narrowing
    function toUpper(arg:string | number){
    if(typeof arg === "string"){
    arg.toUpperCase() // OK!
    }
    }
    function addFive(num?:number){
    return num + 5; // Error
    /*
    (parameter) num: number | undefined
    Object is possibly 'undefined'.
    */
    }
    // narrowing
    function addFive(num?:number){
    if(num){
    return num + 5
    } else {
    throw new Error("Argument num is not a number")
    }
    }

    πŸͺƒΒ Interface

    Type을 λ³€μˆ˜μ— λ„£μ–΄μ„œ μ‚¬μš©

  • νƒ€μž… 자체λ₯Ό λ³€μˆ˜μ— λ„£μ–΄μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.
  • // μ˜ˆμ‹œ1
    type numOrStr = string | number;
    let data: numOrStr = 1;
    data = '1';
    let typeArr: numOrStr[] = [1, '2', 3, '4'];
    // μ˜ˆμ‹œ 2
    type grade = 'A' | 'B' | 'C' | 'D' | 'E';
    const jkeGrade: grade = 'A';

    κΈ°λ³Έ μ‚¬μš©λ²•

  • TSμ—μ„œ λ³΅μž‘ν•œ 객체λ₯Ό μ‚¬μš©ν•  λ•Œ Interface μ‚¬μš©ν•œλ‹€.
  • InterfaceλŠ” typeκ³Ό λ‹€λ₯΄κ²Œ κ°μ²΄μ—λ§Œ μ‚¬μš©ν•  수 μžˆλ‹€.
  • 일반 Typeκ³Ό κ΅¬λΆ„ν•˜κΈ° μœ„ν•˜μ—¬ μ²«κΈ€μžλ₯Ό λŒ€λ¬Έμžλ‘œ μ‚¬μš©ν•œλ‹€.
  • interface User {
    name: string;
    id: string;
    age: number;
    isMember: boolean;
    }
    const jkeInfo: User = {
    name: 'jke',
    id: 'j56237',
    age: 27,
    isMember: true,
    };