능히 해낼 수 있다
230815 TypeScript: 함수 본문
✍️✍️✍️ 위 글은 작성자의 지식습득에 따라 추후 퇴고 될 수 있음을 알려드립니다(피드백 환영).
더하기 함수를 만들어보자
// 더하기 함수 만들기: return하는 경우
//매개변수 타입선언 //반환 타입선언
function add (num1: number, num2: number): number {
return num1 + num2
}
더하기 기능을 만들 함수의 매개변수에 number라는 타입을 선언해주고, 반환할 타입도 number라고 선언해 준다. 그러면 의도한 대로 더하는 기능을 하는 함수가 만들어졌다.
return하는 경우가 아니라면, void를 선언해 주면 된다.
// 더하기 함수 만들기: return하지 "않는" 경우
//매개변수 타입선언 //반환 타입선언
function add (num1: number, num2: number): void {
console.log(num1 + num2)
}
1. optional parameter
interface처럼 함수도 optional을 설정할 수 있다. 유저 로그인 시, 인사하는 기능을 구현한다고 가정해보자.
function greeting(name: string) {
return `Hello, ${name || "world!"}`
}
아래 함수처럼 greeting이라는 함수는 name를 매개변수로 받고 있고, 템플릿 리터럴을 사용해 name을 반환한다. 이 상태에서 result라는 변수에 담아 greeting을 불러오면 에러가 난다. 이유는 불러와야하는 매개변수가 없기 때문.
function greeting(name: string) {
return `Hello, ${name || "world!"}`
}
const result = greeting(); // error!!!
물론 코드에 name이 없을 경우 "world"라는 단어를 불러오도록 작성했지만, TypeScript에서는 좀 더 명시적으로 작성하는 것을 요하기 때문에 에러가 발생하는 것이다. 때문에 매개변수를 선택적으로 올 수 있도록 작성해보면 아래와 같다.
// parameter optional
function greeting(name?: string) {
return `Hello, ${name || "world!"}`
}
const result = greeting(); // solved!
이를 선택적 매개변수 또는 옵셔널이라고 부른다. 하지만 타입은 항상 지켜져야하고, undefined이거나 타입이 있어야하는것이다. 아니면 매개변수 자체에 기본값을 줄 수도 있다. grettingDefault에 마우스를 올려보면 기존 greeting과 같은 형태의 매개변수 타입선언 상태를 보여줄 것이다.
// parameter optional
function greeting(name?: string) {
return `Hello, ${name || "world!"}`
}
// parameter default
function greetingDefault(name = "world!") {
return `Hello, ${name}`
}
const result = greeting(); // solved!
이 상태에서 나이도 추가해보자
function greeting(name : string, age?: number):string {
if(age !== undefined) { // 나이가 있을 때
return `Hello, ${name}! You are ${age}.`
} else { // 나이가 없을 때
return `Hello, ${name}!`
}
}
console.log(gretting('mimi'));
console.log(gretting('mimi', 28));
아 참고로 필수로 입력 해야하는 매개변수 앞에 선택 매개변수가 올 수 없고 에러가 발생한다. 선택적 매개변수는 할 수도 있고 안해도 되기 때문에 필수로 받을 필요가 없기 때문이다. 만약에 옵셔널 매개변수를 앞에 두고 받고 싶다면 undefined를 같이 선언해 주어야 한다.
// error!!
function greeting(age?: number, name : string):string {
if(age !== undefined) { // 나이가 있을 때
return `Hello, ${name}! You are ${age}.`
} else { // 나이가 없을 때
return `Hello, ${name}!`
}
}
// undefined선언해 해결
function greeting(age: number | undefined, name : string):string {
if(age !== undefined) { // 나이가 있을 때
return `Hello, ${name}! You are ${age}.`
} else { // 나이가 없을 때
return `Hello, ${name}!`
}
}
console.log(gretting(28,'mimi'));
console.log(gretting(undefined,'mimi'));
2. 나머지 매개변수(Rest parameters) 타입작성
function add(...nums) {
return nums.reduce((res, num) => res + num, 0))
}
add(1,2,3) //6
add(1,2,3,4,5,6,7,8,9,10) //55
숫자를 모두 전달 받아 더하는 함수를 만들었다. ...nums가 rest parameters이고, 나머지 매개변수는 add함수를 호출한 부분을 보면 2개 이상이 될 수 있고 그에 따라 다른 결과값을 받을 수 있다. 점 세개 전달받은 매개변수를 '배열'로 나타낼 수 있게 한다.
3. this
위 코드는 this 때문에 에러가 발생하고 있다. 이유는 함수 내에서 사용된 this의 타입 추론이 되고 있지 않기 때문.
TypeScript는 this의 타입을 함수가 어떻게 호출되었는지에 따라 추론하는데, 현재 코드에서는 showName 함수를 bind 메서드로 Ben 객체와 바인딩한 이후에 호출하고 있다. 하지만 TypeScript는 bind 메서드로 함수를 바인딩하더라도 this의 타입을 올바르게 추론하지 못하므로 해당 오류가 발생하는 것이다.
그래서 showName에 this의 타입을 User로 선언해 주면 에러가 해결된다.
만약 매개변수가 있다면 어떻게 될까 그리고 여기서 this는 어떻게 User타입을 명시할 수 있을까
아까와 마찬가지로 this를 User타입으로 설정해주면 된다. 그리고 res에 매개변수들을 불러올 때는 마찬가지로 this, age, gender 순서대로 불러와 사용하면 된다.
위 이미지에서는 res에 this를 제외한 나머지 매개변수가 들어가 있는 상태이다. 매개변수가 3개가 있다고 헷갈리면 안된다.
4. overload
join함수에선 나이의 타입이 숫자라면 User를 반환해주고 아니라면 문장을 반환하는 기능을 가지고있다. 함수에선 에러가 발생하지 않았지만 사용해보니 mimi와 rosi에 TypeError가 발생했다. 이유가 몇개 있는데, 첫번째는 mimi가 User객체를 반환하는게 확신이 없기 때문이고, 두번째는 string반환할 수도 있다고 함수 반환타입에 선언을 했기 때문이다. rosi 또한 같은 이유이다.
join함수는 전달받은 매개변수(age) 타입에 따라서 결과값이 객체나 문자열로 달라지고 있다. 이럴 땐 오버로드를 사용한다. 함수오버로드는 매개변수와 타입에 따라 결과값을 다르게 하는 것을 나타내는데, 아래처럼 바꿔 볼 수 있다.
이렇게 함수오버로드 처리를 해주면 string인상태도 인지할 수 있고, User객체도 인지 할 수 있어 타입에러가 발생하지 않는다.
'개발🌐 > TypeScript' 카테고리의 다른 글
230817 TypeScript: class (0) | 2023.08.15 |
---|---|
230815 TypeScript: 리터럴, 유니온, 교차 Type (0) | 2023.08.15 |
230811 TypeScript: Interface (0) | 2023.08.11 |
230804 TypeScript: 기본 타입 (0) | 2023.08.04 |
230803 TypeScript: 사용하는 이유 (0) | 2023.08.03 |