function sing(song: string) { //any에서 string로 타입이 바뀜
console.log(`Sing: ${song}!`);
}
→ 자바스크립트는 인수의 수와 상관없이 함수를 호출할 수 있으나 타입스크립트는 함수에 선언된 모든 매개변수가 필수라고 가정함
→ 함수가 잘못된 수의 인수로 호출되면, 타입스크립트는 타입 오류의 형태로 이의를 제기함
//singTwo 함수는 매개변수가 2개가 아닌 경우 오류남
function singTwo(first: string, second: string) {
console.log(`${first} and ${second}`);
}
// singTwo('hi'); -> 오류남
singTwo('hi', 'hello'); //ok
매개변수 : 인수로 받을 것으로 예상되는 함수의 선언
선택적 매개변수
→ 자바스크립트는 함수의 매개변수가 제공되지 않으면 함수의 내부 인숫값은 undefined로 기본값이 설정됨
→ 타입스크립트에서는 매개변수가 선택적이라는 뜻에 ?:
를 표시
→ [함수 호출]에 선택적 매개변수를 제공할 필요는 없음, | undefined가 유니언 타입으로 추가됨
→ 선택적 매개변수는 마지막 매개변수여야 함
(아래의 announcedSong
매개변수의 위치가 (singer?: string, song: string)
이면 오류남)
function announcedSong(song: string, singer?: string) {
console.log(`Song : ${song}`);
if(singer) {
console.log(`Singer: ${singer}`);
}
}
//모두 다 오류나지 않음
announcedSong('Greenleeves');
announcedSong('Greenleeves', undefined);
announcedSong('Chandelier', 'Sia');
→ 자바스크립트에서 선택적 매개변수를 선언할 때 =와 같이 포함된 기본값 제공
→ 선택적 매개변수는 기본적으로 값이 제공되기 때문에 해당 타입스크립트 타입에서는 암묵적으로 함수 내부에 | undefined
유니언 타입이 추가됨
function rateSong(song: string, rating = 0) {
console.log(`${song} gets ${rating}/5 stars!`);
}
rateSong('Photograph');
rateSong('Set fire to the Rain', 5);
rateSong('Set fire to the Rain', undefined);
//오류
//rateSong('At Last!', '100'); //number아닌 string값
→ 자바스크립트 일부 함수는 임의의 수의 인수로 호출할 수 있도록 만들어짐
→ … 연산자
는 함수 선언의 마지막 매개변수에 위치, 해당 매개변수에서 시작해 함수에 전달된 나머지 인수가 모두 단일 배열에 저장되어야 함
→ 다만 타입스크립트는 인수 배열을 나타내기 위해 []
이 추가됨
function singAllTheSongs(singer: string, ...songs: string[]) {
for(const song of songs) {
console.log(`${song}, by ${singer}`);
}
}
singAllTheSongs('Alicia Keys');
singAllTheSongs('Lady Gaga', 'Bad Romance', 'Just Dance', 'Poker Face');
// singAllTheSongs('Ella Fitzgerald', 2000);
// Argument of type 'number' is not assignable to parameter of type 'string'
//타입 : (songs: string[]) => number
function singSongs(songs: string[]) {
for(const song of songs) {
console.log(`${song}`);
}
return songs.length;
}
// (songs: string[], index: number): string | undefined
function getSongAt(songs: string[], index: number) {
return index < songs.length
? songs[index]
: undefined
}
→ 가능한 반환값이 많은 함수가 항상 동일한 타입의 값을 반환하도록 강제함
→ 타입스크립트는 재귀 함수의 반환 타입을 통해 타입을 유추하는 것을 거부함
→ 수백 개 이상의 타입스크립트 파일이 있는 매우 큰 프로젝트에서 타입스크립트 타입 검사 속도를 높일 수 있음
//(songs: string[], count?: number): number
function singSongsRecurisve(songs: string[], count = 0): number {
return songs.length ? singSongsRecurisve(songs.slice(1), count + 1) : count;
}
// (songs: string[], count?: number) => number
const singSongsRecurisve2 = (songs: string[], count = 0): number =>
songs.length ? singSongsRecurisve(songs.slice(1), count +1) : count;
let nothingInGivesString: () => string; //매개변수가 없고 string 타입 반환
let inputAndOutput: (songs: string[], count?: number) => number;
//string 매개변수와 count 선택적 매개변수 및 number값 반환
→ runOnSongs 함수는 getSongAt 매개변수 타입을 index: number로 받고 string을 반환하는 함수로 선언
→ getSongAt을 전달하면 타입 일치
→ logSong은 매개변수로 number 대신 string을 사용하므로 반환값 가져오지 못함
const songs = ['Juice', 'Shake it off', 'What is up'];
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);
//Argument of type '(song: string) => string' is not assignable to parameter of type '(index: number) => string'.
//Types of parameters 'song' and 'index' are incompatible.
// Type 'number' is not assignable to type 'string'
→ 함수 타입은 다른 타입이 사용되는 모든 곳에 배치할 수 있음(유니언 타입 포함)
→ 유니언 타입의 애너테이션에서 함수 반환 위치를 나타내거나 유니언 타입을 감싸는 부분을 표시할 때 괄호 사용
//타입은 string | undefined 유니언을 반환하는 함수
let returnStringOrUndefined: () => string | undefined;
//타입은 undefined나 string을 반환하는 함수
let maybeReturnString: (() => string) | undefined;
let singer: (song: string) => string;
singer = function(song) {
//song: string 타입
return `Singing: ${song.toUpperCase()}`
}
const songs = ['Call me', 'Jolene', 'The Chain'];
songs.forEach((song, index) => {
console.log(`${song} is at index ${index}`);
})
→ 반복적으로 작성하는 매개변수와 반환 타입을 갖는 코드 공간을 많이 절약 가능
type StringToNumber = (input: string) => number;
let stringToNumber: StringToNumber;
stringToNumber = (input) => input.length;
//오류
// stringToNumber = (input) => input.toUpperCase();
type NumberToString = (input: number) => string;
function useNumberToString(numberToString: NumberToString) {
console.log(`The string is ${numberToString(1234)}`);
}
useNumberToString((input) => `${input}: Hooray!`);
//오류
// useNumberToString((input) => input * 2);
→ 어떤 값도 반환하지 않음
→ 반환 값이 없는 함수의 반환 타입을 확인할 수 있음
function logSong(song: string | undefined): void {
if(!song) {
return;
}
console.log(`${song}`);
return true;
//Type 'boolean' is not assignable to type 'void'
}
let songLogger: (song: string) => void;
songLogger = (song) => {
console.og(`${songs}`);
};
songLogger("Heart of Glass");
→ 자바스크립트는 실제값이 반환되지 않으면 기본으로 모두 undefined를 반환하나 void는 undefined와는 다름
→ 함수 반환 타입이 무시된다는 것을 의미, undefined는 반환되는 리터럴 값
→ undefined를 포함하는 대신 void 타입의 값을 할당하려고 하면 타입 오류
function returnsVoid() {
return;
}
let lazyValue: string | undefined;
//오류
lazyValue = returnsVoid();
//Type 'void' is not assignable to type 'string | undefined
→ 자바스크립트가 아닌 함수의 반환 타입을 선언하는데 유용
→ 함수의 반환값이 자체적으로 반환될 수 있는 값이 아니고 사용하기 위한 것도 아니라는 표시 기억해야 함
const records: string[] = [];
function saveRecords(newRecords: string[]) {
newRecords.forEach((record => records.push(record));
}
saveRecords(['21', 'Come on Over', 'The BodyGuard']);
→ 값을 반환하지 않을 뿐만 아니라 반환할 생각도 없음
→ 의도적으로 항상 오류 발생시키거나 무한루프 생성
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 ${typeof param}`);
}
//param 타입 : string
param.toUpperCase();
}
→ 하나의 최종 구현 시그니처와 그 함수의 본문 앞에 서로 다른 버전의 함수 이름, 매개변수, 반환 타입을 여러 번 선언
→ 오버로드된 함수 호출에 대해 구문오류 생성할 지 여부 결정하는 경우
⇒ 타입스크립트는 함수의 오버로드 시그니처만 확인
⇒ 구현 시그니처는 함수의 내부 로직에서만 사용
→ 허용된 수의 인수를 사용해 호출할 수 있으나 2개의 인수를 사용해 호출하면 2개의 인수를 허용하는 오버로드 시그니처가 없기에 타입오류 발생
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(55436000);
createDate(7, 27, 1987);
//오류
createDate(4, 1);
// No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
→ 오버로드된 함수의 구현에 사용되는 구현 시그니처는 매개변수 타입과 반환 타입에 사용하는 것과 동일함
→ 함수 오버로드 시그니처에 있는 반환 타입과 각 매개변수는 구현 시그니처에 있는 동일한 인덱스의 매개변수에 할당할 수 있어야 함
→ 구현 시그니처는 모든 오버로드 시그니처와 호환되어야 함
function format(data: string): string;
function format(data: string, needle: string, haystack: string): string;
// 오류
function format(getData: () => string): string;
//This overload signature is not compatible with its implementation signature
function format(data: string, needle?: string, haystack?: string) {
return needle && haystack ? data.replace(needle, haystack : data);
}