Learning TypeScript 5장

hyena_lee·2023년 3월 15일
0

TypeScript

목록 보기
5/7
post-thumbnail

함수 매개 변수

  • 함슈으의 매개변수도 타입을 지정할 수 있다.
  • 타입의 정보가 선언되지 않는다면 any타입으로 간주하며 매개변수의 타입은 무엇이든 될 수 있다.
function play(football) {
  	console.log('Playing: ${football}!'};
}

필수 매개변수

  • 함수에 선언되 모든 매개변수가 필수라고 가정하자.
  • 함수가 잘못된 수의 인수로 호출되면, 타입스크립는 타입 오류의 형태롷 이의 제기를 할 수 있다.
  • 타입스크립트에서는 매개변수의 타입과 개수를 정확하게 일치하는지 확인합니다.
function palayOne(first: string, second: string) {
  	conssole.log('${first} / ${second});
palyOne("sport and soccer");
  // Error: Exptected 2 arguments, but got 1.

playOne("team", "player");  // ok
playOne("team", "palyer", "ball");
  // Error: Expected 2 arguments, but got 3.
}

선택적 매개변수

  • 함수 메개변수가 제공되지 않으면 함수 내부의 인숫값은 undefined 기본값으로 설정된다.
  • 선택적 객체 타입 속성과 유사하게 타입 에너네이션의 : 앞에 ? 를 추가해 매개변수가 선택적이라고 표시한다.
  • 함수 호출에 선택적 매개변수를 제공할 필요는 없습니다.
  • 선택적 매개변수에는 항상 | undefined 가 유니언 타입으로 추가되어 있습니다.
function Play(football: string, palyer?: string) {
  conosle.log('Play: ${football)');
  
  if(palyer) {
    console.log('Player ${player}');
  }
}

Play("a"); // ok
Play("a", undefined);  // ok
Play("a", "b"); // ok
  • 선택적 매개변수는 항상 암묵적으로 undefined가 될 수 있다.
  • 선택적 매개변수는 값이 명시적으로 undefined 일지라도 항상 제공되어야 한다.
function Play(football: string, player: string | undefined) {
 	Play("a");
  // Error: Expected 2 arguments but got 1.
  
  Play("a", undefined);   // ok
  Play("a", "b");  // ok
  • 모든 선택적 매개변수는 마지막 매개변수여야 한다.
  • 필수 매개변수 전에 선택적 매개변가 먼저 오면 오류가 발생한다.
function Play(player?: string, football: string) {}
// Error: A required parmeter cannot follow an optional parameter.

기본 매개 변수

  • 선택적 매개변수에는 기본적을 값이 제공되기 때문에 해당 타입스크립트 타입에는 암묵적으로 함수 내부에 | undefined 유니언 타입이 추가된다.
  • 함수의 매개변수에 대해 인수를 누락하거나 undefined 인수를 사용해서 호출하는 것을 하용한다.
function Play(football:string, score = 0) {
  console.log('${football} gets ${score} / star!);
}
              
Play("a");   //ok
Play("a", 2);  // ok
Play("a", undefined);  // ok
Play("a", "7").   
// Error : Argument of type "7" is not assignable to 
// Parameter of type 'number | undefined'.

나머지 매개변수

  • 자바스크립트이 일부 함수는 임의의 수의 인수로 호출할 수있도록 만들어진다.
  • spread operator는 함수 선언의 마지막 매개변수에 위치하고, 해당 매개변수에서 시작해 함수에 전달된 '나머지' 인수가 모두 단일 배열에 저장되어야 한다.
  • 인수 배열을 나나태내기 위해 끝에 [] 구문이 추가된다는 점만 다르다.
function allSongs(singer: string, ...songs: string[]) {
  for (const song of songs) {
    console.log('${song}, by ${singer}');
  }
}

allSongs("a"); //ok
allSongs("a", "b", "c");  //ok
allSongs("a", 3000);  
// Error : Argument of type 'number' is not assignable to parameter of type 'string'

반환 타입

  • 함수가 반환할 수 있는 가능한 모든 값을 이해하면 함수가 반환하는 타입을 알 수 있다.
  • 함수에 다른 값을 가진 여러 개의 반환문을 포함하고 있다면, 타입스크립트는 반환 타입을 가능한 모든 반환 타입의 조합으로 유추할 수 있다.
function getSongs(s: string[], n: number) {
  return n < s.length ? s[n]: undefined
}

명시적 반환 타입

  • 변수와 마찬가지로 타입 애너테이션을 사용해 함수의 반환 타입을 명시적으로 선언하지 않는 것이 좋다.

  • 함수에서 반환 타입을 명시적으로 선언하는 방식이 매우 유용할 때가 종종 있다.

    		- 가능한 반환값이 많은 함수가 항상 동일한 타입의 값을 반환하도록 강제한다.
      - 타입스크립트는 재귀 함수의 반환 타입을 통해 타입을 유추하는 것을 거부한다.
      - 수백 개의 이상의 타입스크립트 파일이 있는 매우 큰 프로젝트에서 타입스크립트 타입검사 속도를 높일 수 있다.
      
  • 함수 선언 반환 타입 애너테이션은 매개변수 목록이 끝나는 ) 다음에 배치되고, 함수 선언의 경우는 { 앞에 위치한다.

function btsSong(songs: string[], count=0): number{
  return songs.length ? btsSong(songs.slice(1), count+1) : count;
}

function btsSong = (songs: string[], count = 0): number => 
	songs.length ? btsSong(songs.slice(1), count+1) : count;
  
  • 함수의 반환 타입으로 할당할 수 없는 값을 반환하는 경우는 타입스크립트는 할당가능성 오류를 표시한다.
function btsDebutDate(song: string):
Date | undefined {
  swich (song) {
    case "2cool4skool";
    	return new Date("June 13, 2013");  //ok
    
    case "save me";
    	return "unkonwn";
    // Error: Type 'string' is not assignable to type 'Date'
    default:
    	return undefined;  // ok
  }
}

함수 타입

  • 함수를 값으로 전달 할 수 있고, 함수를 가지기 위한 매개변수 또는 변수의 타입을 선언하는 방법이 필요하다.
  • 함수타입구문은 함수와 유사하지만 함수 본문 대신 타입이 있다.
const nothing: () => string;  // 매개변수가 없고 string 타입을 반환

const input:(songs: string[], count?: number) => number;
// string[]매개변수와 count 선택적 매개변수 및 number 값을 반환하는 함수를 설명
  • 함수 타입은 콜백 매개변수(함수로 호출되는 매개변수)를 설명하는데 자주 사용!!
const songs = ['Juice", "Sake It Off", "what's up"];
function runSongs(getSongAt: (index: number) => string) {
  for(let i = 0; i < songs.length; i += 1){
    console.log(getSongsAt(i));
  }
}

function getSongAt(index: number) {
  return '${songs[index]}';
}
runOnSongs(getSongAt);  // ok

function logSong(song: string) {
  return '${song}';
} 
runOnSongs(logSong);
//Error: Argument of type '(song: string) => string' is not
//  assignable to parameter of type '(index: number) => string'.
// Type of parameters 'song' and 'index' are incompatible.
// Type 'number' is not assignable to type 'string'
    
  • runOnSong 에 대한 오류 메시지
    - 첫번째 들여쓰기 단께는 두 함수 타입을 출력한다.
    - 다음 들여쓰기 단계는 일치하지 않는 부분을 지정한다.
    - 마지막 들여쓰기 단계는 일치하지 않는 부분에 대한 정확한 할당 가능성 오류를 출력한다.
  • 단계별로 제공하는 내용 정리하자면
    - logSongs: (song: string) => string은 getSongAt: (index: number) => string에 할당되도록 제공되는 타입이다.
    - logSongs의 song 매개변수는 getSongAt의 index 매개변수로 할당된다.
    - song의 string 타입은 index의 number 타입에 할당할 수 없다.

함수 타입 괄호

  • 함수 타입은 다른 타입이 사용되는 모든 곳에 배치할 수 있다.
  • 유니언 타입도 포함되며 애너테이션에서 함수 반환 위치를 나타내거나 유니언 타입을 감싸는 부분을 표시할때 괄호를 사용한다.
// 타입은  string | undefined 유니언을 변환하는 함수
let returnString:() => string | undefined;

// 타입은 undefined 나 string 을 반환하는 함수
let myReturn: (() => string) | undefined;

매개 변수 타입 추론

  • 타입스크립트는 선언된 타입의 위치에 제공된 함수의 매개변수 타입을 유추 할 수있다
let singer: (songs: string) => string;
singer = function (song) {
  // song: string 타입
  return 'Singing: ${song.toUpperCase()}!'} // ok
  • 함수를 매개변수로 갖는 함수에 인자로 전달 된 함수는 해당 매개변수 타입도 잘 유추 할 수 있다.
const songs = ["a", "b", "c];
               
// song: string
// index: number
songs.forEach((song, index) => {
 	console.log('${song} is at index ${index}') 	
});

함수 타입 별칭

  • 함수 타입에서도 동일하게 타입 별칭을 사용할 수 있다.
  • 함수 리터럴로 사용하면 코드 가독성이 안 좋다.
type StringNumber = (input: string) => number;

let stringNumber: StringNumber;

stringNumebr = (input) => input.length;  //ok

stringNumber = (input) => input.toUpperCase();
//Error: Type 'string' is not assignable to type 'number'
type NumberString = (input: number) => string;

function useSNumberString(numberString: NumberString) {
	console.log('The string is: ${numberString(1234)}');
}

usesMunberString((input) => '${input}! Hooray!');  // ok

usesNumberString((input) => input * 2);

// Error: Type 'number' is not assignable to type 'string'

그 외 반환 타입

0️⃣ void 반환 타입

  • void 는 어떤 값도 반환하지 않는다는 의미를 갖는 타입이다.
  • return 문이 없는 함수이거나 값을 반환하지 않는 return 문을 가진 함수일 가진 함수는 어떤 값도 반환하지 않는다.
funtion logSong (song: string | undefined): void {
  if (!song) {
    return;   // ok
  }
	console.log('${song});
  
  return true;
  // Error : Type 'boolean' is not assignable to type 'void'
  • 함수 타입 선언 시 void 반환 타입은 매우 유용하다.
  • 함수 타입을 선언할 때 void를 사용하면 함수에서 반환되는 모든 값은 무시된다.
let songLogger: (song: string) => void;

songLogger = (song) => {
  console.log('${songs}');
};

songLogger("Fake Love");   // ok
  • 자바스크립트 함수는 실젯값이 반환되지 않으면 기본으로 모두 undefined를 반환하지만 void는 undifined와 동일하지 않다.
  • void는 함수의 반환 타입이 무시된다.
function returnVoid() {
  return;
}
let lazyValue: string | undefined;
lazyValue = returnVoid();
// Error : Type 'void' is not assignable to type 'string| undefined'.
  • undefined와 void를 구분해서 사용하면 매우 유용하다.
  • void 를 반환하도록 선언된 타입 위치에 전달된 함수가 반환된 모든 값을 무시하도록 설정할 때 유용하다.
  • forEach 메서드는 void를 반환하는 콜백을 받아 forEach에 제공되는 함수는 원하는 모든 값을 반환할 수 있다.
  • void 타입은 함수의 반환값이 자체적으로 반환될 수 있는 값도 아니고, 사용하기 위한 것도 아니라는 표시위한 것.
const records: string[] = [];

function saveRecords(newRecords: string[]) {
  newRecords.forEach(record => records.push(record));
}

saveRecords(['22', 'yet to come', 'permission to Dance'])

never 반환 타입

  • 일부 함수는 값을 반환하지 않고 never 반환 함수는 항상 오류를 발생시키거나 무한루프를 실행하는 함수이다.
  • 함수가 절대 반환하지 않도록 의도하려면 명시적 : never 타입 애너테이션을 추가해 해당 함수를 호출한 뒤 모든 코드가 실행되지 않음을 나타낸다.
function fail(message: string): never {
	throw new Error ('Invariant failure: ${message}.');
}
function workWithUnsafeParam(param:unknown) {
  if(typeof param !== 'string') {
    fail('param should be a string, not ${typof param}');
  }
  
  param.toUpperCase();   // ok
}

🌧️ 함수 오버로드

  • 선택적 매개변수나 나머지 매개변수만으로 표현할 수 없는 매우 댜른 매개변수들로 호출 될 수 있다.
  • 하나의 최종 구현 시그니처와 그 함수와 본문 앞에 서로 다른 버전의 함수 이름, 매개변수, 변환 타입을 여러 번선언한다.
  • 함수 오버로드는 복잡하고 설명하기 어려운 함수 타입에 사용하는 최후의 수단이기 때문에 가능하면 함수 오버로드를 사용하지 않는 것이 좋다.
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(1231);  // ok
createDate(2, 22, 2222);  // ok

createDate(4, 1);
// Error : No overload expects 2 arguments, but overloads
// do exist that expect eithor 1 or 3 arguments.
  • createDate 함수 1개는 timestamp 매개변수 또는 3개의 매개변수 (month, day, year)를 사용해 호출한다.
  • 2개의 인수를 사용해 호출하면 2개의 인수를 허용하는 오버로드 시그니처가 없기 때문에 타입 오류가 발생한다.

호출 시그니처 호환성

  • 함수의 오버로드 시그니처에 있는 반환 타입과 각 매개변수는 구현 시그니처에 있는 동일한 인덱스이 매개변수에 할당할 수 있어야 한다. (구현 시그니처는 모든 오버로드 시그니처와 호환되어야 함)

    1. 처번째 매개변수를 string으로 선언
    1. 두개의 오버로드 시그니처는 string 타입과 호환
    1. 세번째 오버로드 시그니처의 () => string 타입과는 호환되지 않는다.
function format(data: string): string; // ok
function format(data: string, needle: string, haystack: string): string; // ok
function format(getData: () => string): string;
// Error: This overload signature is not compatible with its implementation signature

function format (data: string, neele? string, haystack? string) {
  return needle && haystack ? data. replace(needle, haystack) : data;
}

[Reference]
1. Learning typeScript(조시 골드버그/고승원/한빛미디어_2023)

profile
실수를 두려워 말고 계속 도전 하는 개발자의 여정!

0개의 댓글