TypeScript | 함수

Kate Jung·2021년 12월 28일
0

TypeScript

목록 보기
3/10
post-thumbnail

📌 정의 가능한 타입

웹 애플리케이션 구현 시, 자주 사용되는 함수는 타입스크립트로 크게 다음 3가지 타입을 정의 가능

  • 함수의 파라미터(매개변수) 타입
  • 함수의 반환 타입
  • 함수의 구조 타입

📌 기본적인 타입 선언 방법

// JavaScript
function sum(a, b) {
  return a + b
}

// TypeScript
function sum(a: number, b: number): number {
  return a + b
}

→ 기존 JS 함수 선언 방식에서 매개변수 & 함수의 반환 값에 타입 추가

  • Tip

    함수의 반환 값 에 타입을 정하지 않을 때 → void라도 사용

📌 함수의 인자

🔹 필수 값으로 간주

타입스크립트는 함수의 인자를 필수 값으로 간주

  • 따라서

    • 함수의 매개변수 설정 시, undefined나 null이라도 인자로 넘겨야 함.

    • 컴파일러에서 정의된 매개변수 값이 넘어 왔는지 확인

  • 즉, 받을 수 있는 것

    • 정의된 매개변수 값 → o

    • 추가 인자 받을 수 → x

  • 예시 코드

    function sum(a:number, b:number):number {
        return a + b
    }
    
    sum(10, 20)
    sum(10,20,30) // [error] Expected 2 arguments, but got 3.
    sum(10) // [error] Expected 2 arguments, but got 1.

🔹 옵셔널 (?)

정의된 매개변수의 갯수만큼 인자를 안넘겨도 되게 함.

  • JS의 특성 살림

  • 기본 예시 코드

    function sum(a:number, b:number):number {
    	return a + b
    }
        
    sum(10, 20)
    sum(10,20,30) // [error] Expected 2 arguments, but got 3.
    sum(10) // [error] Expected 2 arguments, but got 1.

◽ 특징 & 예시 코드

  1. 문제

    function hello(name: string){
      return `hello, ${name || "world"}` // name이 있으면 쓰고 없으면 "world" 출력.
    }
    
    const result = hello() 
    /* 
    - 결과: 에러 발생. (1개의 매개변수 필요)
    - 해결 방법: name 없을 때를 대비한 코드가 있지만 ts는 명시적으로 적어야 함. */
  2. [해결] 선택적 매개변수(==옵셔널 파라미터)

    // [해결] 선택적 매개변수(==옵셔널 파라미터)
    function hello(name?: string){ // name은 있어도/없어도 됨. 옵셔널도 타입 지켜야 함. (undefined이거나 만약 있다면 string)
      return `hello, ${name || "world"}`
    }
    
    const result = hello() // 에러 사라짐
    const result2 = hello("Sam") // 사용 가능
    const result3 = hello(123) // 에러 발생
  3. [리팩토링] 매개변수의 디폴트 값 활용

    function hello2(name = "world"){
      return `hello, ${name}`
    }
    
    /* 
    hello2에 호버 시: 
    - 위와 같은 형태 
    - function hello2(name?: string): string. */

◽ 선택적 매개 변수의 위치

필수 매개변수 뒤

  • 필수 매개변수 앞에 오면 에러 발생.

    이유: 옵셔널한 값은 입력을 안해줘도 되기 때문.

  • 앞에 두고 싶다면

    • 올바른 코드
      function hello(age: number | undefined, name: string): string { // age를 number와 undefined로 받을 수 있게 함.
        if (age !== undefined) {
          return `Hello, ${name}. You are ${age}.`
        } else {
          return `Hello, ${name}`
        }
      }
      
      console.log(hello(30,"Sam"))
      console.log(hello(undefined,"Sam")) // 명시적으로 undefined를 전달하는 방식.
    • 기존 코드
      function hello(name: string, age?: number): string {
        if (age !== undefined) {
          return `Hello, ${name}. You are ${age}.`
        } else {
          return `Hello, ${name}`
        }
      }
      
      console.log(hello("Sam", 30))
      console.log(hello("Sam"))
    • 에러 코드
      function hello(age?:number, name: string): string { // [name] A required parameter cannot follow an optional parameter.
        if (age !== undefined) {
          return `Hello, ${name}. You are ${age}.`
        } else {
          return `Hello, ${name}`
        }
      }
      
      console.log(hello("Sam", 30)) // Argument of type '"Sam"' is not assignable to parameter of type 'number | undefined'.
      console.log(hello("Sam")) // An argument for 'name' was not provided.

🔹 매개변수 초기화

ES6 문법과 동일

  • 예시 코드
    function sum(a: number, b = '100'): number {
      return a + b;
    }
    sum(10, undefined); // 110
    sum(10, 20, 30); // error, too many parameters
    sum(10); // 110

📌 REST 문법이 적용된 매개변수

  • 예시 코드
    function add(...nums:number[]) { // Rest 파라미터(나머지 매개변수) 사용. -> 타입: 배열 형태
      return nums.reduce((acc,cur)=>acc+cur,0)
    }
    
    console.log(add(1,2,3)); // 6
    console.log(add(1,2,3,4,5,6,7,8,9,10)); // 55

📌 this

🔹 타입 위치

함수 첫 번째 매개변수 자리

interface User {
  name: string;
}

const Sam: User = { name: "Sam" }

function showName(this: User){ // 👈 this 타입
  console.log(this.name) 
	// 이 this: 사용 방법에 따라 달라짐. this 타입 결정 안되면 빨간 줄 뜸.
}

const a = showName.bind(Sam) // bind 이용 -> this를 Sam객체로 강제함.
a() // "Sam"

🔹 매개변수가 있을 경우

전달할 매개 변수 위치: this 다음부터 적용

function showName(this: User, age:number, gender: 'm' | 'f'){
  console.log(this.name, age, gender)
}

const a = showName.bind(Sam)
a(30, 'm') // "Sam",  30,  "m"

📌 오버로드

전달받은 매개변수의 갯수 or 타입에 따라 다른 동작을 하게 하는 것

▼ 예시 코드

  • 에러 발생
    interface User {
      name: string;
      age: number;
    }
    
    /*
    나이: 숫자라면 User을, 아니라면 string을 리턴
    -> 반환 값 타입에 User | string을 기입
    -> join()은 문제가 없어보이지만 실사용시, 문제 발생 */
    function join(name: string, age: number | string): User | string {
      if(typeof age === 'number') {
        return {
          name,
          age
        }
      } else {
        return "나이는 숫자로 입력해주세요."
      }
    }
    
    /* 
    👉 문제 
    - 분기 처리 여부: 코드는 됨. 타입들은 안됨.
    	JS는 동일한 매개변수라도 타입을 다르게 줄 수 있음.
    - 이 함수는 전달받은 매개 변수(age) 타입에 따른 리턴 값(User | string)이 다름.
    
    👉 해결 방법
    - '오버로드' 사용. 
    - 사용법: join 함수 위에 똑같은 모습으로 작성. */
    
    const sam: User = join("sam", 30) // [에러 발생] 이유: User를 반환한다는 확신 無. string을 반환할 수 있다고 판단.
    const jane: string = join("jane", "33") // [에러 발생]
  • 해결
    (...생략)
    
    // 오버로드
    function join(name: string, age: number): User; // age를 number로 받았을 때, User 반환
    function join(name: string, age: string): string; // age를 string으로 받았을 때, string 반환
    function join(name: string, age: number | string): User | string {
      (...생략)
    }
    
    (...생략)

참고:

profile
복습 목적 블로그 입니다.

0개의 댓글