function sing(song) {
// paramter 'song': any
console.log(`Singing: ${song}!`);
}
function sing(song: string) {
// paramter 'song': string
console.log(`Singing: ${song}!`);
}
function singTwo(first: string, second: string) {
console.log(`${first} / ${second}`);
}
// Error: Expected 2 arguments, but got 1
singTwo('Ball and Chain');
// Ok
singTwo('I will Survive', 'Higher Love');
// Error: Expected 2 arguments, but got 3
singTwo('Go Your Own Way', 'The Chain', 'Dream');
| undefined
가 union 타입으로 추가되어 있습니다.function announceSong(song: string, singer?: string) {
console.log(`Song: ${song}`);
if (singer) {
console.log(`Singer: ${singer}`);
}
}
// Ok
announceSong('Greensleeves');
// Ok
announceSong('Greensleeves', undefined);
// Ok
announceSong('Chandelier', 'Sia');
| undefined
를 포함하는 union 타입 매개변수와 다릅니다.function announceSongBy(song: string, singer: string | undefined) { /* ... */}
// Error: Expected 2 arguments, but got 1
announceSongBy('Greensleeves');
// Ok
announceSongBy('Greensleeves', undefined);
// Ok
announceSongBy('Chandelier', 'Sia');
// Error: A required parameter cannot follow an optional parameter
function announceSinger(singer?: string, song: string) {/* ... */}
function rateSong(song: string, rating = 0) {
console.log(`${song} gets ${rating}/5 stars!`);
}
// Ok
rateSong('Photograph');
// Ok
rateSong('Set Fire to the Rain', 5);
// Ok
rateSong('Set Fire to the Rain', undefined);
// Error: Argument of type '100' is not assignable to paratmeter of type 'number | undefined'
rateSong('At Last', '100');
[]
구문이 추가된다는 점만 다릅니다.function singAllTheSongs(singer: string, ...songs: string[]) {
for (const song of songs) {
console.log(`${song}, by ${singer}`);
}
}
// Ok
singAllTheSongs('Alicia Keys');
// Ok
singAllTheSongs('Lady Gaga', 'Bad Romance', 'Just Dance', 'Poker Face');
// Error: Argument of type 'number' is not assignable to parameter of type 'string'
singAllTheSongs('Ella Fitzgerald', 2000);
// function singSongs(songs: string[]) => number
function singSongs(songs: string[]) {
for (const song of songs) {
console.log(`${song}`);
}
return songs.length;
}
// function getSongAt(songs: string[], index: number) => string | undefined
function getSongAt(songs: string[], index: number) {
return index < songs.length ? songs[index] : undefined;
}
아래와 같은 경우, 함수에서 반환 타입을 명시적으로 선언하는 것이 유용합니다.
함수의 반환 타입 type annotation은 매개변수 목록이 끝나는 )와 {의 사이에 배치됩니다.
function singSongsRecursive(songs: string[], count = 0): number {
return song.length
? singSongsRecursive(songs.slice(1), count + 1)
: count;
}
const singSongsRecursive = (songs: string[], count = 0): number => {
return song.length
? singSongsRecursive(songs.slice(1), count + 1)
: count;
}
function getSongRecordingDate(song: string):
Date | undefined {
switch(song) {
case 'Strange Fruit':
// Ok
return new Date('April 20, 1939');
case 'Greensleeves':
// Error: Type 'string' is not assignable to type 'Date'
return 'unknown';
}
}
JavaScript에서 함수는 값으로 전달할 수 있습니다.
함수 타입(function type) 구문은 화살표 함수와 유사하지만 함수 본문 대신 타입이 있습니다.
let nothingInGivesString: () => string;
let inputAndOutput: (songs: string[], count?: number) => number;
함수 타입은 콜백 매개변수를 설명하는데 자주 사용됩니다.
TypeScript는 두 함수를 서로 할당할 수 없다는 오류를 출력할 때 일반적으로 3가지 단계를 제공합니다.
const songs = ["Juice", "Shake It Off", "What's up"];
function runOnSongs(getSongAt: (index: number) => string) {
for (let i = 0; i < songs.length; i++) {
console.log(getSongAt(i));
}
}
function getSongAt(index: number) {
return `${songs[index]}`;
}
function logSong(song: string) {
return `${song}`;
}
// Ok
runOnSongs(getSongAt);
// Error: Argument of type '(song: string) =? string' is not assignable to parameter type '(index: number) => string'
// Type of parameters 'song' and 'index' are incompatible
// Type 'number' is not assignable to type 'string'
runOnSongs(logSong):
let maybeReturnsString: (() => string) | undefined;
let singer: (song: string) => string;
singer = function (song) {
// parameter 'song': string
return `Singing: ${song.toUpperCase()}`;
}
const songs = ['Call Me', 'Jolene', 'The Chain'];
songs.forEach((song, index) => {
// parameter 'song': string
// parameter 'index': number
console.log(`${song} is at index ${index}`);
})
type StringToNumber = (input: string) => number;
let stringToNumber: StringToNumber;
// Ok
stringToNumber = (input) => input.length;
// Error: Type '(input: string) => string' is not assignable to type 'StringToNumber'
// Type 'number' is not assignable to 'string'
stringToNumber = (input) => input.toUpperCase();
function logSong(song: string | undefined): void {
if (!song) {
return;
}
console.log(`${song}`);
// Error: Type 'boolean' is not assignable to type 'void'
return true;
}
function returnsVoid() {
return;
}
let lazyValue: string | undefined;
// Error: Type 'void' is not assignable to type 'string | undefined'
lazyValue = returnsVoid();
const records: string[] = [];
function saveRecords(newRecords: string[]) {
newRecords.forEach(record => records.push(record));
}
saveRecord(['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 ${param}`);
}
// parameter 'param': string
param.toUpperCase();
}
Note
- void : 아무것도 반환하지 않는 함수의 반환 타입
- never : 절대 반환하지 않는 함수의 반환 타입
// overload signature
function createDate(timestamp: number): Date;
function createDate(month: number, day: number, year: number): Date;
// implementation signature
function createDate(monthOrTimestamp: number, day?: number, year?: number) {
return day === undefined || year === undefined
? new Date(monthOrTimestamp)
: new Date(year, monthOrTimestamp, day);
}
// Ok
createDate(554356800);
// Ok
createDate(7, 27, 1987);
// Error: No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
createDate(4, 1):
function createDate(monthOrTimestamp, day, year) {
return day === undefined || year === undefined
? new Date(monthOrTimestamp)
: new Date(year, monthOrTimestamp, day);
}
// Ok
function format(data: string): string;
// Ok
function format(data: string, needle: string, haystack: string): string;
// Error: This overload siganature is not competible with its implementation signature
function format(getData: () => string): string;
function format(data: string, needle?: string, haystack?: string) {
return needle & haystack ? data.replace(needle, haystack) : data;
}