![[Typescript] 함수(2)](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLbdo0%2FbtsFyfcR4ZX%2FQtTkFXGlnNi6t9GNv9XON1%2Fimg.png)
3️⃣ 함수 타입
함수타입 구문은 화살표 함수와 유사하지만 함수 본문 대신 타입이 있다.
💥기본적인 사용법
let nothingInGivesString : () => string;
이 변수 타입은 매개변수가 없고 string을 반환하는 함수이다.
함수 타입은 콜백 매개변수(함수로 호출되는 매개변수)를 설명하는 데 자주 사용된다.
const songs = ["Butter", "As Time Goes by", "Hey Jude"];
/* getSongAt 매개변수의 타입을 index:number 로 받고 string을 반환하는 함수 */
function runOnSongs(getSongAt: (index: number) => string) {
for (let i = 0; i < songs.length; i += 1) {
console.log(getSongAt(i));
}
}
function getSongAt(index: number) {
return `${songs[index]}`;
}
runOnSongs(getSongAt); /* OK */
function logSong(song: string) {
return `${song}`;
}
runOnSongs(logSong); /* Error */
/* logSong은 매개변수로 number 대신 string을 사용하므로 반환값을 가져오는데 실패*/
🚩 함수 타입 괄호
/* 타입은 string | undefined 유니언을 반환하는 함수 */
let case1: () => string | undefined;
/* 타입은 undefined나 string을 반환하는 함수 */
let case2: (() => string) | undefined;
함수 타입은 다른 타입이 사용되는 모든 곳에 배치할 수 있다.
🚩 매개변수 타입 추론
⭐️ 작성한 모든 함수에 대해 매개변수의 타입을 선언해야한다면 굉장히 번거롭다.
⭐️ TypeScript는 선언된 타입의 위치에 제공된 함수의 매개변수 타입을 유추할 수 있는 기능이 있다.
let singer : (song: string) => string;
singer = function (song) {
/*song : string*/
return `Singing : ${song.toUpperCase()}!`;
};
singer 변수는 string 타입의 매개변수를 갖는 함수로 알려져 있으므로 나중에 singer가 할당되는 함수내의 song 매개변수는 string으로 예측됨.
🚩 함수 타입 별칭
[Typescript] 유니언과 리터럴(2)
리터럴 타입 const philosopher = "Hypatia"; 위의 코드를 보면 philosopher 이라는 변수에 "Hypatia"라는 string을 담았다. 즉, philosopher은 string타입이면서도 구체적으로는 "Hypatia"라는 구체적인 특별한 값을 가
indigochi1d.tistory.com
유니언과 리터럴에서 다뤘던 타입 별칭과 같이 함수 타입에서도 동일하게 타입 별칭을 사용할 수 있다.
/*StringToNumber 타입은 string 타입을 받고 number 타입을 반환하는 함수의 별칭*/
type StringToNumber = (input:string) => number;
let case1 : StringToNumber;
case1 = (input) => input.length; /*OK*/
case2 = (input) => input.toUpperCase(); /*Error*/
4️⃣ 그 외 반환 타입
🚩 void 반환타입
void 타입으로 선언하면 함수에서 반환되는 모든 값은 무시된다.
- return 문이 없는 함수
- 값을 반환하지 않는 함수
function Sing(song: string | undefined): void {
if (!song) {
return;
}
console.log(`${song}`);
}
💡undefined와 void를 구분해서 사용하면 매우 유용하다.
특히 void를 반환하도록 선언된 타입 위치에 전달된 함수가 반환된 모든 값을 무시하도록 설정할 때 유용하다.
Javascript 함수는 실제값이 반환되지 않으면 undefined를 반환하는데 void는 이와 동일하지 않다.
void : 반환값 무시
undefined : 반환되는 리터럴 값
💡void 타입은 함수의 반환 타입을 선언하는 데 사용하는 Typescript 키워드이다.
🚩 never 반환 타입
💡never 반환 함수는 의도적으로 항상 오류를 발생시키거나 무한 루프를 실행하는 함수이다.
함수가 절대 반환하지 않도록 의도하려면 명시적 : never 타입 에너테이션을 추가해 해당 함수를 호출한 후 모든 코드가 실행되지 않음을 나타낸다.
function fail(message : string) : never{
throw new Error(`Invariant failure : ${message}`);
}
function detectUnsafeParams(param : unknown){
if (typeof param !== "string"){
fail(`Param should be a string type, not ${param}`);
}
/* 위의 조건문을 거치면 param의 type이 string이라는게 논리상 확실시됨.*/
param.toUpperCase();
}
위의 코드는 never 반환 타입이 타입 내로잉을 통해 Typescript의 제어 흐름 분석을 도와주고 있다.
never 와 void는 다르다.
never는 절대 반환하지 않는 함수를 위한다.
void는 아무것도 반환하지 않는 함수를 위한다.
5️⃣함수 오버로드
함수 오버로드는 JavaScript에서의 다양한 함수 호출 방식에 대해 선택적 매개변수와 나머지 매개변수만으로 표현할 수 없는 상황에 대해서 다룬다.
👨🏻💻 아래의 코드로 간단하게 보여주자면..
function example1(a, b = 2, ...rest) {
console.log(a);
console.log(b);
console.log(rest);
}
example1(1); /* a = 1, b = 2 (기본값), rest = []*/
example1(1, 3); /* a = 1, b = 3, rest = []*/
example1(1, 3, 4, 5); /* a = 1, b = 3, rest = [4, 5]*/
이 함수는 a를 필수 매개변수, b를 선택적 매개변수 , ...rest로 나머지 매개변수로 인자를 받아 사용하고 있다.
이러한 경우 문제가 없는데 아래의 함수의 경우에는 문제가 생긴다.
function example2(a, b) {
if (typeof a === 'function') {
a();
} else if (typeof a === 'string' && typeof b === 'function') {
b(a);
} else {
console.log('Invalid input');
}
}
example2(() => console.log('Function called!')); /* a가 함수일 때 호출 */
example2('Hello', (msg) => console.log(msg)); /* a가 문자열이고 b가 함수일 때 호출*/
example2(1, 2); /* Invalid input */
여기서 example2 함수는 첫 번째 매개변수가 함수인지, 문자열인지에 따라 다르게 작동하며, 이 함수는 선택적 매개변수나 나머지 매개변수로 표현하기 어렵다.
🚫 왜냐하면 호출 방식이 너무 다르기 때문이다🚫
- 첫 번째 경우, a가 함수일 때는 그것을 실행함.
- 두 번째 경우, a가 문자열이고, b가 함수일 때 b(a)를 호출함.
- 세 번째 경우는 함수가 예상하지 못한 입력이 들어왔을 때 에러를 처리함.
이 함수는 매개변수의 타입과 순서에 따라 다른 동작을 하기 때문에 모든 함수를 선택적 매개변수와 나머지 매개변수만으로 표현할 수 없다.
하지만 TypeScript에선 이 문제를 함수 오버로드를 통해 해결한다.
오버로드 함수는 오버로드 시그니처와 구현 시그니처로 나눌 수 있다.
이 코드를 간단하게 말하면
함수가 매개변수 1개를 받을때 : timestamp
함수가 매개변수 3개를 받을때 : month, day, year
로 인식하고 동작한다.
📙Code
function createDate(timestamp:number) : Date; /* 오버로드 시그니처*/
function createDate(month:number,day:number,year:number) : Date; /*오버로드 시그니처*/
function createDate(monthOrTimestamp:number,day?:number,year?:number){ /*구현 시그니처 */
return day === undefined || year === undefined
? new Date(monthOrTimestamp)
: new Date(year,monthOrTimestamp,day)
}
createDate(59557); /* OK!! */
createDate(4,23,2000); /* OK!! my birthday lolzz */
createDate(4,1); /*Error*/
'FrontEnd > Typescript' 카테고리의 다른 글
[Typescript] 배열(2) (0) | 2024.08.11 |
---|---|
[Typescript] 배열(1) (0) | 2024.08.05 |
[Typescript] 함수(1) (1) | 2024.03.05 |
[Typescript] 객체(2) (1) | 2024.02.10 |
[Typescript] 객체(1) (1) | 2024.02.09 |
안녕하세요? 개발자입니다.