TIL 10/2

Rami·2024년 10월 2일

TodayILearn

목록 보기
14/61
type Config = {
    path : string;
    state : object;
}

type Push = {
    (path:string):void; 
    (config: Config):void;
}

const push: Push = (config) => { // (parameter) config: string | Config 

}

TypeScript에서 config(parameter) config: string | Config로 추론되는 이유:
Push 타입이 함수 오버로딩으로 정의되어 있기 때문

함수 오버로딩(Overloading) 이해하기

함수 오버로딩은 여러 가지 호출 시그니처(Signature)를 사용하여 동일한 함수 이름다양한 형태로 호출할 수 있도록 만드는 기능입니다. TypeScript는 오버로드된 함수를 정의할 때, 여러 개의 함수 시그니처를 기반으로 인자의 타입을 추론합니다.

Push 타입을 보면 다음과 같이 두 가지 호출 시그니처를 가지고 있습니다:

type Push = {
    (path: string): void; // 첫 번째 시그니처
    (config: Config): void; // 두 번째 시그니처
};
  • 첫 번째 시그니처: 인자로 string 타입의 path만 받을 수 있습니다.
  • 두 번째 시그니처: 인자로 Config 타입({ path: string, state: object })의 config 객체를 받을 수 있습니다.

이 두 시그니처를 합치면, TypeScript는 해당 함수 push가 다음과 같은 형태로 호출될 수 있다고 추론합니다:

  1. push("somePath")처럼 문자열을 인자로 받을 수 있고,
  2. push({ path: "somePath", state: {} })처럼 객체를 인자로 받을 수도 있습니다.

string | Config로 추론되는가?

TypeScript는 함수의 구현부(함수 본문)에서 전달된 인자의 타입을 보고 자동으로 가장 포괄적인 타입으로 추론하려고 합니다.

const push: Push = (config) => {};

위 코드를 살펴보면, push 함수는 Push 타입을 구현하고 있습니다. Push 타입은 stringConfig라는 두 가지 시그니처를 가지고 있기 때문에, TypeScript는 다음과 같이 자동으로 config의 타입을 string | Config로 추론하게 됩니다:

const push: Push = (config: string | Config) => {};

즉, config첫 번째 시그니처의 인자인 string이 될 수도 있고, 두 번째 시그니처의 인자인 Config 객체가 될 수도 있다는 뜻입니다.

타입 추론 예시

다음 예제를 통해 함수 오버로딩과 타입 추론이 어떻게 이루어지는지 확인해 보겠습니다:

type Config = {
    path: string;
    state: object;
};

type Push = {
    (path: string): void; // 첫 번째 시그니처
    (config: Config): void; // 두 번째 시그니처
};

const push: Push = (config) => {
    console.log(config);
};

위 코드에서 configstring일 수도 있고 Config 타입일 수도 있습니다. 따라서 TypeScript는 configstring | Config 타입으로 추론합니다. 이렇게 추론이 되면 함수 내부에서 config의 타입을 확실하게 구분하지 않으면 pathstate에 접근할 때 타입 오류가 발생할 수 있습니다.

개선 방안: 타입 가드 사용

함수 내부에서 stringConfig 타입을 명확히 구분하기 위해 타입 가드를 사용할 수 있습니다. 예를 들어:

const push: Push = (config) => {
    if (typeof config === "string") {
        // config가 문자열일 때 실행할 로직
        console.log("String path:", config);
    } else {
        // config가 Config 객체일 때 실행할 로직
        console.log("Config object:", config.path, config.state);
    }
};

위와 같이 typeof를 사용하여 config가 문자열인지 객체인지 확인하면 타입 오류 없이 안전하게 접근할 수 있습니다.

요약

  • 함수 오버로딩을 사용하면 여러 호출 시그니처를 정의할 수 있으며, TypeScript는 구현부에서 가장 포괄적인 타입(string | Config)을 추론합니다.
  • Push 타입은 (path: string): void(config: Config): void 두 가지 시그니처를 가지고 있으므로, TypeScript는 config의 타입을 string | Config로 추론합니다.
  • 함수 내부에서 타입 가드를 사용하여 stringConfig를 구분하면 더욱 안전하게 코드를 작성할 수 있습니다.

Generic

아래 두 함수 합쳐놓은 것

function superPrint<T>(a: T[]){
    return a[0]
}

제네릭 기본 사용 방법

type SuperPrint = {
    <T>(arr: T[]): T
}
const superPrint: SuperPrint = (arr) => arr[0]

3.4

type Player<E> = {
    name:string
    extraInfo: E
}

const nico : Player<{favFood:string}> = {
    name: "nico",
    extraInfo: {
        favFood: "kimchi"
    }
}

// 위 코드를 둘로 나눈것 1
type NicoPlayer = Player<{favFood:string}>
const nico : NicoPlayer = {
    name: "nico",
    extraInfo: {
        favFood: "kimchi"
    }
}

// 위 코드를 둘로 나눈것 2
type NicoPlayer = Player<NicoExtra>
type NicoExtra = {
    favFood: string
}
const nico : NicoPlayer = {
    name: "nico",
    extraInfo: {
        favFood: "kimchi"
    }
}

const lynn : Player<null> = {
    name: "lynn",
    extraInfo: null
}

4.0 class

what is 객체지향 프로그래밍?

constructor

class  Player {
    constructor(
        private firstName: string,
        private lastName: string
    ) {}
}

실제 javascript에서는

"use strict";
class Player {
    constructor(firstName, lastName){
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

abstract 추상클래스

추상클래스 : 다른 클래스가 상속받을 수 있는 클래스 but 직접 새로운 인스턴스를 만들 수는 없다.

abstract class User{
    constructor(
        private firstName: string,
        private lastName: string,
        public nickName: string
    ) {}
    getFullName(){
        return `${this.firstName} ${this.lastName}`
    }
}

class  Player extends User{
}

const nico = new Player("nico" , "las", "니꼬");
nico.getFullName() 

4.2 interfaces

타입 사용방법1

type Player1 = {
    nickname: string,
    healthBar: number
}
const nico1 : Player1 = {
    nickname: "nico1",
    healthBar: 10
}

타입 사용방법2

type Food = string;
const kimchi : Food = "delicious"

타입 사용방법3

type Nickname = string
type Health = number
type Friends = Array<string> // type Friends = string[]

type Player2 = {
    nickname: Nickname,
    healthBar: Health
}
const nico2 : Player2 = {
    nickname: "nico2",
    healthBar: 10
}
profile
YOLO

0개의 댓글