ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TypeScript | 함수형 타입
    JavaScript/TypeScript 2020. 5. 6. 15:43

    함수 타입

    함수의 타입을 정의하기 위해서는 매개변수 타입과 반환 타입이 필요
    :(콜론)을 이용해서 매개변수 타입 및 반환 타입 정의

    함수 타입 정의

    function getInfoText(name: string, age: number): string {
        const nameText = name.substr(0, 10);
        const ageText = age >= 35 ? 'senior' : 'junior';
        return `name: ${nameText}, age: ${ageText}`;
    }
    
    const v1: string = getInfoText('mike', 23);
    const v2: string = getInfoText('mike', '23'); // 타입 에러
    const v3: number = getInfoText('mike', 23); // 타입 에러
    
    console.log(v1); // name: mike, age: junior
    • 매개변수 name은 문자열 타입이기 때문에 substr 메서드 사용 가능
    • 매개변수 age는 숫자이기 때문에 다른 숫자와 크기 비교 가능
    • 매개변수 또는 반환 타입이 맞지 않는 경우 타입 에러 발생

    변수를 함수 타입으로 정의

    const getInfoText: (name: string, age: number) => string = function(name, age){
        // ...
        return `...`;
    };
    • 함수를 구현하는 코드에서는 매개변수 타입과 반환 타입을 지정하지 않음
    • 타입스크립트는 function() 매개변수의 name과 age가 각각 문자열과 숫자라는 것을 알고 있음

    선택 매개변수

    반드시 입력하지 않아도 되는 매개벼수
    매개변수 이름 오른쪽에 ?(물음표) 기호를 입력하면 선택 매개변수가 됨

    function getInfoText(name: string, age: number, language?: string): string {
        const nameText = name.substr(0, 10);
        const ageText = age >= 35 ? 'senior' : 'junior';
        const languageText = language ? language.substr(0, 10) : '';
        return `name: ${nameText}, age: ${ageText}, language: ${languageText}`;
    }
    
    const v1 = getInfoText('mike', 23, 'ko');
    const v2 = getInfoText('mike', 23);
    const v3 = getInfoText('mike', 23, 123); // 타입 에러
    
    console.log(v1); // name: mike, age: junior, language: ko
    console.log(v2); // name: mike, age: junior, language: 
    • language를 선택 매개변수로 정의
    • 함수 호출 시 선택 매개변수의 인수를 입력하지 않아도 에러는 발생하지 않음
    • 함수 내부에서 language 인수의 존재 여부를 검사하지 않고 substr 메서드를 호출하면 타입 에러 발생
    • 선택 매개변수 오른쪽에 필수 매개변수가 오면 컴파일 에러 발생
    // 컴파일 에러 발생
    function getInfoText(name: string, language?: string, age: number): string {
        // ...
        return `...`;
    }

    undefined를 이용해서 중간에 선택 매개변수 정의하기

    function getInfoText(
        name: string,
        language: string | undefined,
        age: number,
    ): string {
            // ...
            return `...`;
    }
    getInfoText('mike', undefined, 23);
    • |(유니온 타입)을 이용해서 undefined도 입력할 수 있도록 함
    • 함수 호출 시 중간에 undefined 입력
    • 컴파일 에러가 발생하지는 않지만 사용성과 가독성이 좋지 않음
      → 매개변수의 개수가 많은 경우에는 비구조화 문법을 이용해서 명명된 매개변수로 작성하는 게 좋음

    매개변수 기본값 정의하기

    function getInfoText(
        name: string,
        age: number = 15,
        language = 'korean',
    ): string {
        const nameText = name.substr(0, 10);
        const ageText = age >= 35 ? 'senior' : 'junior';
        const languageText = language ? language.substr(0, 10) : '';
        return `name: ${nameText}, age: ${ageText}, language: ${languageText}`;
    }
    
    console.log(getInfoText('mike'));
    // name: mike, age: junior, language: korean
    
    console.log(getInfoText('mike', 23));
    // name: mike, age: junior, language: korean
    
    console.log(getInfoText('jone', 36, 'english'));
    // name: jone, age: senior, language: english
    
    const f1: (
        name: string,
        age?: number,
        language?: string,
    ) => string = getInfoText;
    • 타입 오른쪽에 = 기호를 사용해서 매개변수 기본값 정의 가능
    • age의 인수를 입력하지 않으면 15가 기본값으로 사용됨
    • 타입을 입력하지 않아도 매개변수 기본값 정의 가능
      기본값이 문자열이기 때문에 매개변수 language의 타입도 문자열이 됨
    • 기본값이 있는 매개변수는 선택 매개변수

    나머지 매개변수

    나머지 매개변수의 타입은 배열로 정의 가능

    function getInfoText(name: string, ...rest: string[]): string {
        // ...
        return `...`;
    }

    this 타입

    함수의 this 타입을 정의하지 않으면 기본적으로 any 타입이 사용됨
    any 타입은 가급적 쓰지 않는 게 좋으므로 타입을 정의해 두는 것이 좋음

    this 타입을 정의하지 않은 경우

    function getParam(index: number): string {
        const params = this.splt(',');
        if(index < 0 || params.length <= index){
            return '';
        }
        return this.split(',')[index];
    }
    • this의 타입이 암묵적으로 any로 사용된다는 경고를 볼 수 있음
    • 2번째 줄에서 split을 splt로 오타를 냈지만 any 타입이기 때문에 컴파일 에러가 발생하지 않음

    this 타입 정의하기

    함수의 this 타입은 첫 번째 매개변수 위치에서 정의 가능

    function getParam(this: string, index: number): string {
        const params = this.splt(','); // 타입 에러 발생
        // ...
        return '';
    }
    • 매개변수 index는 두 번째 자리에 정의
    • 하지만 this 타입은 매개변수가 아니므로 index가 첫 번째 매개변수가 됨
    • this의 타입을 정의했기 때문에 splt 오타에서 타입 에러 발생

    원시 타입에 메서드 추가하기

    원시(primitive) 타입에 메서드를 등록할 때는 인터페이스 이용

    interface String {
        getParam(this: string, index: number): string;
    }
    
    function getParam(this: string, index: number): string {
        const params = this.split(',');
        if(index < 0 || params.length <= index){
            return '';
        }
        return this.split(',')[index];
    }
    
    String.prototype.getParam = getParam;
    console.log('asdf, 1234, ok'.getParam(1)); // 1234
    • 인터페이스를 이용해서 이미 존재하는 문자열 타입에 getParam 메서드 추가
    • 문자열의 프로토타입에 직접 작성한 getParam 함수 등록
    • 문자열에 등록된 getParam 메서드 호출 가능

    함수 오버로드: 여러 개의 타입 정의하기

    함수 오버로드(overload)를 사용하면 하나의 함수에 여러 개의 타입 정의 가능

    함수 오버로드를 사용하지 않은 코드

    숫자나 문자 값을 받아서 더한 뒤 매개변수가 모두 숫자면 숫자로, 그렇지 않은 경우에는 문자로 반환하는 함수

    function add(x: number | string, y: number | string): number | string {
        if (typeof x === 'number' && typeof y === 'number'){
            return x + y ;
        } else {
            const result = Number(x) + Number(y);
            return result.toString();
        }
    }
    
    const v1: number = add(1, 2); // 타입 에러
    console.log(1, '2');
    • 모든 매개변수가 숫자이므로 반환값도 숫자이지만 타입 에러 발생
    • 함수의 반환 타입을 구체적으로 정의하지 못했기 때문에 에러가 발생함

    함수 오버로드를 사용한 코드

    위의 함수에 오버로드를 적용한 함수
    함수 오버로드를 적용할 때, 실제로 구현하는 함수를 가장 아래쪽에 작성

    function add(x: number, y: number): number;
    function add(x: string, y: string): string;
    function add(x: number, y: string): string;
    function add(x: string, y: number): string;
    function add(x: number | string, y: number | string): number | string {
        if (typeof x === 'number' && typeof y === 'number'){
            return x + y ;
        } else {
            const result = Number(x) + Number(y);
            return result.toString();
        }
    }
    
    const v1: number = add(1, 2);
    console.log(v1); // 3 -> number
    console.log(add(1, '2')); // 3
    console.log(add('1', 2)); // 3
    console.log(add('1', '2')); // 3
    • 매개변수와 반환 타입의 모든 가능한 조합 정의
    • 실제로 함수를 구현하는 쪽에서 정의한 타입은 함수 오버로드의 타입 목록에서 제외됨
      → 실제로 구현하는 함수 바로 위에 [// @ts-ignore]를 작성한 후 any 타입으로 처리해도 됨
    • 함수 호출 시 어떤 경우에도 타입 에러가 발생하지 않음

    명명된 매개변수

    function getInfoText({
        name,
        age = 15,
        language,
    }: {
        name: string,
        age?: number,
        language: string;
    }): string {
        const nameText = name.substr(0, 10);
        const ageText = age >= 35 ? 'senior' : 'junior';
        return `name: ${nameText}, age: ${ageText}, language: ${language}`;
    }
    
    console.log(getInfoText({ name:'mike', age:23, language:'ko' }));
    // name: mike, age: junior, language: ko
    • 먼저 모든 매개변수의 이름을 객체형으로 정의, 기본값이 있다면 이름과 함께 정의함
    • 앞에 나열된 모든 매개변수에 대한 타입 역시 객체형으로 정의
    • 명명된 매개변수를 사용하면 중간에 있는 매개변수를 선택 매개변수로 사용 가능
    • 비구조화 문법을 이용한 것이기 때문에 함수 호출 시에 인수로 객체를 전달해야 함
    • 명명된 매개변수의 타입을 다른 코드에서도 재사용하려면 인터페이스 사용

    인터페이스로 명명된 매개변수 타입 정의

    interface Param {
        name: string;
        age?: number;
        language?: string;
    }
    function getInfoText({ name, age = 15, language }: Param): string {
        // ...
        return '...';
    }
    • 명명된 매개변수 타입을 인터페이스로 정의
    • 코드가 간소화되며 가독성이 높아지고 Param 인터페이스 재사용 가능

    참고도서: [실전 리액트 프로그래밍 / 저자_ 이재승 / 출판사_ 프로그래밍 인사이트]

    'JavaScript > TypeScript' 카테고리의 다른 글

    TypeScript | 타입 호환성  (0) 2020.05.07
    TypeScript | Interface 인터페이스  (0) 2020.05.07
    TypeScript | Enum 열거형 타입  (0) 2020.05.06
    TypeScript | 개요 & 변수 타입  (0) 2020.05.06

    댓글

Designed by Tistory.