개발 알다가도 모르겠네요

타입스크립트의 함수 본문

웹/Typescript

타입스크립트의 함수

이재빵 2022. 6. 18. 15:15
728x90

 

function add(x: number, y: number): number {
    return x + y;
}

let myAdd = function(x: number, y: number): number { return x + y };

각 파라미터와 함수 자신의 반환될 타입을 정해줄 수 있습니다.
TypeScript는 반환 문을 보고 반환 타입을 파악할 수 있으므로 반환 타입을 생략할 수 있습니다.

 

함수 타입 작성

let myAdd: (x: number, y: number) => number =
    function(x: number, y: number): number { return x + y; };

함수의 타입은 매개변수, 반환 타입이 있습니다. 전체 함수 타입을 작성하고자 한다면 이 두 가지 타입이 필요합니다.

let myAdd: (baseValue: number, increment: number) => number =
    function(x: number, y: number): number { return x + y; };

매개변수의 타입들이 올바르게 나열되어 있다면 함수 타입에 이름을 붙이더라도 유효한 타입으로 간주합니다.

두 번째로 반환 타입입니다. 매개변수 타입들과 반환 타입 사이에 '화살표 표기'( => )를 써서 반환 타입을 분명히 할 수 있습니다.

만약 함수가 값을 반환하지 않는다면 비워두는 대신 void를 써서 표시합니다.

 

타입의 추론

// myAdd는 전체 함수 타입을 가집니다
let myAdd = function(x: number, y: number): number { return  x + y; };

// 매개변수 x 와 y는 number 타입을 가집니다
let myAdd: (baseValue: number, increment: number) => number =
    function(x, y) { return x + y; };

이러한 타입 추론 형태를 "contextual typing" 이라 부릅니다. 

 

선택적 매개변수와 기본 매개변수

TypeScript에서는 모든 매개변수가 함수에 필요하다고 가정합니다.

함수에 주어진 인자의 수는 함수가 기대하는 매개변수의 수와 일치해야 합니다.

function buildName(firstName: string, lastName: string) {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // 오류, 너무 적은 매개변수
let result2 = buildName("Bob", "Adams", "Sr.");  // 오류, 너무 많은 매개변수
let result3 = buildName("Bob", "Adams");         // 정확함

 

JavaScript에서는 모든 매개변수가 선택적이고, 사용자는 적합하다고 생각하면 그대로 둘 수 있습니다.

그렇게 둔다면 그 값은 undefined가 됩니다.

TypeScript에서도 선택적 매개변수를 원한다면 매개변수 이름 끝에 ? 를 붙임으로써 해결할 수 있습니다.

function buildName(firstName: string, lastName?: string) {
    if (lastName)
        return firstName + " " + lastName;
    else
        return firstName;
}

let result1 = buildName("Bob");                  // 지금은 바르게 동작
let result2 = buildName("Bob", "Adams", "Sr.");  // 오류, 너무 많은 매개변수
let result3 = buildName("Bob", "Adams");         // 정확함

 

 

TypeScript에서는 유저가 값을 제공하지 않거나 undefined로 했을 때에 할당될 매개변수의 값을 정해 놓을 수도 있습니다.

이것을 기본-초기화 매개변수라고 합니다.

function buildName(firstName: string, lastName = "Smith") {
    return firstName + " " + lastName;
}

let result1 = buildName("Bob");                  // 올바르게 동작, "Bob Smith" 반환
let result2 = buildName("Bob", undefined);       // 여전히 동작, 역시 "Bob Smith" 반환
let result3 = buildName("Bob", "Adams", "Sr.");  // 오류, 너무 많은 매개변수
let result4 = buildName("Bob", "Adams");         // 정확함

 

나머지 매개변수 (Rest Parameters)

function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}

// employeeName 은 "Joseph Samuel Lucas MacKinzie" 가 될것입니다.
let employeeName = buildName("Joseph", "Samuel", "Lucas", "MacKinzie");

나머지 매개변수는 선택적 매개변수들의 수를 무한으로 취급합니다. 나머지 매개변수로 인자들을 넘겨줄 때는 당신이 원하는 만큼 넘기거나 아무것도 넘겨주지 않을 수도 있습니다. 컴파일러는 생략 부호 (...) 뒤의 이름으로 전달된 인자 배열을 빌드하여 함수에서 사용할 수 있도록 합니다.

 

function buildName(firstName: string, ...restOfName: string[]) {
    return firstName + " " + restOfName.join(" ");
}

let buildNameFun: (fname: string, ...rest: string[]) => string = buildName;

 

this와 화살표 함수 

let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        return function() {
            let pickedCard = Math.floor(Math.random() * 52);
            let pickedSuit = Math.floor(pickedCard / 13);

            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}

let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);

이 예제를 작동시키면 오류가 발생합니다.

createCardPicker에 의해 생성된 함수에서 사용 중인 this가 deck 객체가 아닌 window에 설정되었기 때문입니다. 

cardPicker()의 자체적인 호출 때문에 생긴 일입니다.

최상위 레벨에서의 비-메서드 문법의 호출은 this를 window로 합니다.

(Note: strict mode에서는 this가 window 대신 undefined 가 됩니다. )

 

let deck = {
    suits: ["hearts", "spades", "clubs", "diamonds"],
    cards: Array(52),
    createCardPicker: function() {
        // NOTE: 아랫줄은 화살표 함수로써, 'this'를 이곳에서 캡처할 수 있도록 합니다
        return () => {
            let pickedCard = Math.floor(Math.random() * 52);
            let pickedSuit = Math.floor(pickedCard / 13);

            return {suit: this.suits[pickedSuit], card: pickedCard % 13};
        }
    }
}

let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();

alert("card: " + pickedCard.card + " of " + pickedCard.suit);

 

오버로드

let suits = ["hearts", "spades", "clubs", "diamonds"];

function pickCard(x: {suit: string; card: number; }[]): number;
function pickCard(x: number): {suit: string; card: number; };
function pickCard(x): any {
    // 인자가 배열 또는 객체인지 확인
    // 만약 그렇다면, deck이 주어지고 card를 선택합니다.
    if (typeof x == "object") {
        let pickedCard = Math.floor(Math.random() * x.length);
        return pickedCard;
    }
    // 그렇지 않다면 그냥 card를 선택합니다.
    else if (typeof x == "number") {
        let pickedSuit = Math.floor(x / 13);
        return { suit: suits[pickedSuit], card: x % 13 };
    }
}

let myDeck = [{ suit: "diamonds", card: 2 }, { suit: "spades", card: 10 }, { suit: "hearts", card: 4 }];
let pickedCard1 = myDeck[pickCard(myDeck)];
alert("card: " + pickedCard1.card + " of " + pickedCard1.suit);

let pickedCard2 = pickCard(15);
alert("card: " + pickedCard2.card + " of " + pickedCard2.suit);

오버로드는 pickCard 함수에 대해 타입 검사 호출을 제공합니다.

위 예제에서 function pickCard(x): any는 오버로드 목록에 해당되지 않습니다.

' > Typescript' 카테고리의 다른 글

타입스크립트의 타입 추론  (0) 2022.06.19
타입스크립트의 Enum  (0) 2022.06.19
타입스크립트의 인터페이스  (0) 2022.06.18
타입스크립트의 제네릭  (0) 2022.06.18
타입스크립트의 Class  (0) 2022.06.17