본문 바로가기

javascript

[Typescript] 형식화된 함수 개발

 

타입스크립트에는 표준 자바스크립트 함수에는 없는 몇 가지 새로운 기능이 있어 쉽게 함수를 작성할 수 있다.

 
 

타입스크립트에서 함수 만들기

왜 타입스크립트로 함수를 만드나

  • 자바스크립트 함수에서는 매개변수에 데이터 형식을 지정하거나, 전달된 인수의 형식 검사를 시행하거나, 수신된 인수의 수를 확인하지 않는다 ⇒ 사용자가 매개변수를 확인하는 논리를 함수에 추가해야 한다
  • 타입스크립트는 함수 개발을 간소화하며 사용자가 매개변수를 입력하고 값을 반환할 수 있어 문제를 쉽게 해결한다
  • 매개변수에 새로운 옵션을 추가할 수 있다. → 매개변수를 필수 또는 선택 사항으로 지정 가능 (자바스크립트에서 모든 매개변수는 선택사항)
  • 함수에 형식을 추가하면 ⇒ 함수에 전달하는 값과 반환되는 값을 검사할 수 있다
  • 함수 논리를 만들 때 매개변수의 데이터 형식을 편집기에서 감지하기 때문에 자동 완성 지원을 사용할 수 있다. (자동 완성 기능은 다른 사용자가 개발한 함수를 사용할 때 필요한 입력 및 출력 형식을 명확하게 표시한다)

 

명명된 함수

  • 이름이 있는 함수는 function 키워드를 이용해 작성.
  • 명명된 함수 선언은 코드가 실행되기 전에 실행 컨텍스트에 로그됨 → 호이스팅
  • 타입스크립트에서 명명된 함수를 선언하는 것은 자바스크립트와 같다. 유일한 차이점은 함수의 매개 변수와 반환 값에 형식 주석을 추가하는 것
function addNumbers (x: number, y: number): number {
    return x + y;
}

addNumbers(1, 2);
 
"use strict";
function addNumbers(x, y) {
    return x + y;
}
addNumbers(1, 2);

 

함수 식(익명 함수)

  • 함수 식(익명 함)은 실행 컨텍스트에 미리 로드되지 않으며 코드를 발견하면 실행
  • 함수 식은 런타임에 생성되며 함수 식을 실행하려면 먼저 선언해야 한다.
  • 함수 식은 호이스팅되지 않는다.
  • 함수 식은 값을 나타내므로 대부분 변수에 할당되거나 다른 함수로 전달되며 익명일 수 있다.
let addNumbers = function(x: number, y:number):number {
    return x + y;
}

addNumbers(1, 2);
  • 아래 예제에서 sum 변수는 형식화되지 않았지만, 타입스크립트의 형식 추론 양식인 ‘상황별 입력’을 통해 형식을 확인할 수 있다. (여기에서 sum은 function 타입일까?)
  • 상황에 맞는 형식화는 프로그램을 보다 쉽게 형식화할 수 있다.
let sum = function (input: number[]): number {
    let total: number = 0;
    for (let i = 0; i < input.length; i++) {
        if(isNaN(input[i])) {
            continue;
        } 
        total += input[i];
    }
    return total;
}

console.log(sum([1, 2, 3]));
 
"use strict";
let sum = function (input) {
    let total = 0;
    for (let i = 0; i < input.length; i++) {
        if (isNaN(input[i])) {
            continue;
        }
        total += input[i];
    }
    return total;
};
console.log(sum([1, 2, 3]));

 

화살표 함수

  • function 키워드를 생략하고 매개변수와 함수 본문 사이에 ⇒ 연산자 사용
// 익명 함수
let addNumbers1 = function(x: number, y: number): number {
    return x + y;
}

// 화살표 함수
let addNumbers2 = (x: number, y: number): number => x + y;

 

연습 - 자바스크립트 함수를 형식화하기

문제1)

function displayAlert(message) {
    alert('The message is ' + message);
}
function displayAlert(message:string) {
    alert('The message is ' + message)
}

 

문제2)

 
function sum(input) {
    let total =  0;
    for(let count = 0; count < input.length; count++) {
        if(isNaN(input[count])){
            continue;
        }
        total += Number(input[count]);
    }
    return total;
}
function sum(input:number[]): number {
    let total =  0;
    for(let count = 0; count < input.length; count++) {
        if(isNaN(input[count])){
            continue;
        }
        total += Number(input[count]);
    }
    return total;
}

 

매개변수

  • 타입스크립트에서는 함수에 정의된 모든 매개변수가 필수 매개변수라고 가정한다.
  • 함수를 호출하면 컴파일러가
    • 각 매개변수에 제공된 값을 확인
    • 함수에 필요한 매개변수만 전달
    • 매개변수는 함수에 정의된 순서대로 전달
  • 자바스크립트에서는 모든 매개변수가 선택 사항이며, 함수에서 정의한 것보다 많거나 적은 인수를 전달할 수 있다고 가정한다.

 

필수 매개변수

  • 별도로 지정하지 않는 한 모든 함수 매개변수는 필수
  • 함수에 전달되는 인수의 개수가 함수에 필요한 매개변수의 개수와 일치해야 한다
function addNumbers(x: number, y: number): number {
    return x + y;
}

addNumbers(1, 2);
addNumbers(1);   // Error. Expected 2 arguments, but got 1.

 

선택적 매개변수

  • 매개변수 이름 끝에 ?를 붙이면 옵션으로 만들 수 있다
  • 선택적 매개변수는 필수 매개변수 뒤에 와야 한다.
  • 아래 함수의 경우 x는 필수, y는 옵션.
  • 이 함수가 올바른 값을 반환하려면 y가 undefined로 전달될 가능을 처리해야 한다.
function addNumbers(x: number, y?: number): number {
    if (y === undefined) {
        return x;
    } else {
        return x + y;
    }
}

addNumbers(1, 2);
addNumbers(1);

 

기본 매개변수

  • 선택적 매개변수에 기본값 할당
  • 선택적 매개변수에 값이 전달되면 그 값을 사용, 값이 전달되지 않는다면 기본 값 사용
  • 기본 매개변수는 필수 매개변수 다음에 와야 한다.
  • 아래 예제에서 x는 필수, y는 옵션. y에 값이 전달되지 않으면 기본값은 25
function addNumbers(x: number, y = 25): number {
    return x + y;
    
}

addNumbers(1, 2);  // 3
addNumbers(1);  // 26

 

Rest 매개변수

  • 여러 매개변수를 그룹으로 사용할 경우 (예, 배열)
  • 얼마나 많은 매개변수를 사용할지 모를 경우
  • 개수가 무한대인 선택적 매개변수로 취급한다.
let addNumbers = (firstNumber: number, ...restOfNumbers: number[]): number =>{
    let total: number = firstNumber;
    for (let counter = 0; counter < restOfNumbers.length; counter++) {
        if (isNaN(restOfNumbers[counter])) {
            continue;
        }
        total += restOfNumbers[counter];
    }
    return total;
}

addNumbers(1, 2, 3, 4, 5, 6, 7);  // 28
addNumbers(2);  // 2
addNumbers(2, 3, "three");  // Error. Argument of type 'string' is not assignable to parameter of type 'number'.

 

 

분해 개체 매개변수

  • 함수 매개변수는 함수에서 정의된 순서대로 전달되어야 한다.
  • 위치 매개변수는 선택적이거나 데이터 형식이 동일한 여러 매개변수를 사용하여 함수를 호출할 때 코드를 읽기 어렵다.
  • 분해 개체 매개변수 : 함수에서 인터페이스를 사용하여 위치 매개변수 대신 명명된 매개변수를 정의할 수 있다.
  • 다음 예제에서 Message 인터페이스를 정의하고, displayMessage 함수에서 Message 객체가 매개변수로 전달됨
interface Message {
    text: string;
    sender: string;
}

function displayMessage({text, sender}: Message) {
    console.log(`Message from ${sender}: ${text}`);
}

displayMessage( { sender: 'Christopher', text: 'Hello, world!!'});

 

연습

필수 매개변수

3개의 숫자를 더하는 addThreeNumbers 함수를 정의해 보자. 화살표 함수 사용.

let addThreeNumbers = (x: number, y: number, z: number):number => x + y + z;

 

위 함수에 인수가 2개일 때, 4개일 때 적용 → 2개일 때는 NaN 반환. 4개일 때는 3개만 사용해서 결과 보여줌.

addThreeNumbers(10, 20);  // NaN 반환. Erro. Expected 3 arguments, but got 2.
addThreeNumbers(10, 20, 30, 40);  // 60 반환. Error. Expected 3 arguments, but got 4.

 

선택적 매개변수

  • 위의 addThreeNumbers 함수에서 y를 선택적 매개변수로 만들고 위에서와 똑같이 실행해 보자

→ 선택적 매개변수는 필수 매개변수 뒤에 와야 하므로 오류 발생

 

  • 제대로 동작하려면 z를 선택적 매개변수로 놓아야 함
  • 단, 이 경우 z가 undefined일 경우를 고려해야 함
let addThreeNumbers = (x: number, y: number, z?: number):number =>{
    if (z === undefined) {
        return x + y;
    } else {
        return x + y + z;
    }
} 


addThreeNumbers(10, 20, 30);
addThreeNumbers(10, 20);

 

기본 매개변수

  • 필수 매개변수 3개가 필요한 화살표 함수 만들기
let subtractThreeNumbers = (x: number, y: number, z: number) => x - y - z;
  • z의 기본 값을 10으로 설정
let subtractThreeNumbers = (x: number, y: number, z = 10) => x - y - z;

subtractThreeNumbers(10, 20);  // -20 
subtractThreeNumbers(10, 20, 15);  // -25

 

 

연습 - 함수 형식 정의

형식 별칭을 사용해 calculator 함수 형식 정의

  • calculator를 사용해 다른 함수 선언 가능
type calculator = (x: number, y: number) => number;

let addNumbers: calculator = (x: number, y: number): number => x + y;
let subtractNumbers: calculator = (x: number, y: number): number => x - y;

console.log(addNumbers(1, 2));
console.log(subtractNumbers(1, 2));

 

  • calculator 함수 형식을 사용해서 다른 함수로 전달할 수도 있음
type calculator = (x: number, y: number) => number;

let addNumbers: calculator = (x: number, y: number): number => x + y;
let subtractNumbers: calculator = (x: number, y: number): number => x - y;

let doCalculation = (operation: 'add' | 'subtract' ): calculator => {
    if (operation = 'add') {
        return addNumbers;
    } else {
        return subtractNumbers;
    }
}

console.log(doCalculation('add')(1, 2));

 

인터페이스를 통해 정의

interface Calculator {
    (x: number, y: number): number;
}

let addNumbers: Calculator = (x: number, y: number): number => x + y;
let subtractNumbers: Calculator = (x: number, y: number): number => x - y;

console.log(addNumbers(1, 2));
console.log(subtractNumbers(1, 2));

 

함수 형식 유추

  • 함수를 정의할 때 함수 매개 변수의 이름은 함수 형식의 이름과 일치하지 않아도 됨. (함수 형식에서는 x, y를 사용했지만 함수를 정의할 때는 number1, number2 사용)
  • 두 함수 모두에서 형식 시그니처의 매개 변수 이름을 입력해야 하지만, 두 함수 형식의 호환 여부를 확인할 때는 이름이 무시된다.
  • 매개 변수 형식과 반환 형식을 생략해도 된다. TypeScript는 함수 형식 정의에서 이러한 형식을 추론하기 때문.
  • TypeScript를 이용할 때는 언제나 세 가지 문이 동일합니다.
let addNumbers: Calculator = (x: number, y: number): number => x + y;
let addNumbers: Calculator = (number1: number, number2: number): number => number1 + number2;
let addNumbers: Calculator = (num1, num2) => num1 + num2;  // 형식 유추

 

(이 글의 원문 보기 : Develop typed functions by using Typescript)

 

Develop typed functions by using TypeScript - Training

Learn how to develop typed functions by using TypeScript.

learn.microsoft.com