-
TypeScript | 함수형 타입JavaScript/TypeScript 2020. 5. 6. 15:43
함수 타입
함수의 타입을 정의하기 위해서는 매개변수 타입과 반환 타입이 필요
:(콜론)을 이용해서 매개변수 타입 및 반환 타입 정의함수 타입 정의
function getInfoText(name: string, age: number): string { const nameText = name.substr(0, 10); const ageText = age >= 35 ? 'senior' : 'junior'; return `name: ${nameText}, age: ${ageText}`; } const v1: string = getInfoText('mike', 23); const v2: string = getInfoText('mike', '23'); // 타입 에러 const v3: number = getInfoText('mike', 23); // 타입 에러 console.log(v1); // name: mike, age: junior
- 매개변수 name은 문자열 타입이기 때문에 substr 메서드 사용 가능
- 매개변수 age는 숫자이기 때문에 다른 숫자와 크기 비교 가능
- 매개변수 또는 반환 타입이 맞지 않는 경우 타입 에러 발생
변수를 함수 타입으로 정의
const getInfoText: (name: string, age: number) => string = function(name, age){ // ... return `...`; };
- 함수를 구현하는 코드에서는 매개변수 타입과 반환 타입을 지정하지 않음
- 타입스크립트는 function() 매개변수의 name과 age가 각각 문자열과 숫자라는 것을 알고 있음
선택 매개변수
반드시 입력하지 않아도 되는 매개벼수
매개변수 이름 오른쪽에 ?(물음표) 기호를 입력하면 선택 매개변수가 됨function getInfoText(name: string, age: number, language?: string): string { const nameText = name.substr(0, 10); const ageText = age >= 35 ? 'senior' : 'junior'; const languageText = language ? language.substr(0, 10) : ''; return `name: ${nameText}, age: ${ageText}, language: ${languageText}`; } const v1 = getInfoText('mike', 23, 'ko'); const v2 = getInfoText('mike', 23); const v3 = getInfoText('mike', 23, 123); // 타입 에러 console.log(v1); // name: mike, age: junior, language: ko console.log(v2); // name: mike, age: junior, language:
- language를 선택 매개변수로 정의
- 함수 호출 시 선택 매개변수의 인수를 입력하지 않아도 에러는 발생하지 않음
- 함수 내부에서 language 인수의 존재 여부를 검사하지 않고 substr 메서드를 호출하면 타입 에러 발생
- 선택 매개변수 오른쪽에 필수 매개변수가 오면 컴파일 에러 발생
// 컴파일 에러 발생 function getInfoText(name: string, language?: string, age: number): string { // ... return `...`; }
undefined를 이용해서 중간에 선택 매개변수 정의하기
function getInfoText( name: string, language: string | undefined, age: number, ): string { // ... return `...`; } getInfoText('mike', undefined, 23);
- |(유니온 타입)을 이용해서 undefined도 입력할 수 있도록 함
- 함수 호출 시 중간에 undefined 입력
- 컴파일 에러가 발생하지는 않지만 사용성과 가독성이 좋지 않음
→ 매개변수의 개수가 많은 경우에는 비구조화 문법을 이용해서 명명된 매개변수로 작성하는 게 좋음
매개변수 기본값 정의하기
function getInfoText( name: string, age: number = 15, language = 'korean', ): string { const nameText = name.substr(0, 10); const ageText = age >= 35 ? 'senior' : 'junior'; const languageText = language ? language.substr(0, 10) : ''; return `name: ${nameText}, age: ${ageText}, language: ${languageText}`; } console.log(getInfoText('mike')); // name: mike, age: junior, language: korean console.log(getInfoText('mike', 23)); // name: mike, age: junior, language: korean console.log(getInfoText('jone', 36, 'english')); // name: jone, age: senior, language: english const f1: ( name: string, age?: number, language?: string, ) => string = getInfoText;
- 타입 오른쪽에 = 기호를 사용해서 매개변수 기본값 정의 가능
- age의 인수를 입력하지 않으면 15가 기본값으로 사용됨
- 타입을 입력하지 않아도 매개변수 기본값 정의 가능
기본값이 문자열이기 때문에 매개변수 language의 타입도 문자열이 됨 - 기본값이 있는 매개변수는 선택 매개변수임
나머지 매개변수
나머지 매개변수의 타입은 배열로 정의 가능
function getInfoText(name: string, ...rest: string[]): string { // ... return `...`; }
this 타입
함수의 this 타입을 정의하지 않으면 기본적으로 any 타입이 사용됨
any 타입은 가급적 쓰지 않는 게 좋으므로 타입을 정의해 두는 것이 좋음this 타입을 정의하지 않은 경우
function getParam(index: number): string { const params = this.splt(','); if(index < 0 || params.length <= index){ return ''; } return this.split(',')[index]; }
- this의 타입이 암묵적으로 any로 사용된다는 경고를 볼 수 있음
- 2번째 줄에서 split을 splt로 오타를 냈지만 any 타입이기 때문에 컴파일 에러가 발생하지 않음
this 타입 정의하기
함수의 this 타입은 첫 번째 매개변수 위치에서 정의 가능
function getParam(this: string, index: number): string { const params = this.splt(','); // 타입 에러 발생 // ... return ''; }
- 매개변수 index는 두 번째 자리에 정의
- 하지만 this 타입은 매개변수가 아니므로 index가 첫 번째 매개변수가 됨
- this의 타입을 정의했기 때문에 splt 오타에서 타입 에러 발생
원시 타입에 메서드 추가하기
원시(primitive) 타입에 메서드를 등록할 때는 인터페이스 이용
interface String { getParam(this: string, index: number): string; } function getParam(this: string, index: number): string { const params = this.split(','); if(index < 0 || params.length <= index){ return ''; } return this.split(',')[index]; } String.prototype.getParam = getParam; console.log('asdf, 1234, ok'.getParam(1)); // 1234
- 인터페이스를 이용해서 이미 존재하는 문자열 타입에 getParam 메서드 추가
- 문자열의 프로토타입에 직접 작성한 getParam 함수 등록
- 문자열에 등록된 getParam 메서드 호출 가능
함수 오버로드: 여러 개의 타입 정의하기
함수 오버로드(overload)를 사용하면 하나의 함수에 여러 개의 타입 정의 가능
함수 오버로드를 사용하지 않은 코드
숫자나 문자 값을 받아서 더한 뒤 매개변수가 모두 숫자면 숫자로, 그렇지 않은 경우에는 문자로 반환하는 함수
function add(x: number | string, y: number | string): number | string { if (typeof x === 'number' && typeof y === 'number'){ return x + y ; } else { const result = Number(x) + Number(y); return result.toString(); } } const v1: number = add(1, 2); // 타입 에러 console.log(1, '2');
- 모든 매개변수가 숫자이므로 반환값도 숫자이지만 타입 에러 발생
- 함수의 반환 타입을 구체적으로 정의하지 못했기 때문에 에러가 발생함
함수 오버로드를 사용한 코드
위의 함수에 오버로드를 적용한 함수
함수 오버로드를 적용할 때, 실제로 구현하는 함수를 가장 아래쪽에 작성function add(x: number, y: number): number; function add(x: string, y: string): string; function add(x: number, y: string): string; function add(x: string, y: number): string; function add(x: number | string, y: number | string): number | string { if (typeof x === 'number' && typeof y === 'number'){ return x + y ; } else { const result = Number(x) + Number(y); return result.toString(); } } const v1: number = add(1, 2); console.log(v1); // 3 -> number console.log(add(1, '2')); // 3 console.log(add('1', 2)); // 3 console.log(add('1', '2')); // 3
- 매개변수와 반환 타입의 모든 가능한 조합 정의
- 실제로 함수를 구현하는 쪽에서 정의한 타입은 함수 오버로드의 타입 목록에서 제외됨
→ 실제로 구현하는 함수 바로 위에 [// @ts-ignore]를 작성한 후 any 타입으로 처리해도 됨 - 함수 호출 시 어떤 경우에도 타입 에러가 발생하지 않음
명명된 매개변수
function getInfoText({ name, age = 15, language, }: { name: string, age?: number, language: string; }): string { const nameText = name.substr(0, 10); const ageText = age >= 35 ? 'senior' : 'junior'; return `name: ${nameText}, age: ${ageText}, language: ${language}`; } console.log(getInfoText({ name:'mike', age:23, language:'ko' })); // name: mike, age: junior, language: ko
- 먼저 모든 매개변수의 이름을 객체형으로 정의, 기본값이 있다면 이름과 함께 정의함
- 앞에 나열된 모든 매개변수에 대한 타입 역시 객체형으로 정의
- 명명된 매개변수를 사용하면 중간에 있는 매개변수를 선택 매개변수로 사용 가능
- 비구조화 문법을 이용한 것이기 때문에 함수 호출 시에 인수로 객체를 전달해야 함
- 명명된 매개변수의 타입을 다른 코드에서도 재사용하려면 인터페이스 사용
인터페이스로 명명된 매개변수 타입 정의
interface Param { name: string; age?: number; language?: string; } function getInfoText({ name, age = 15, language }: Param): string { // ... return '...'; }
- 명명된 매개변수 타입을 인터페이스로 정의
- 코드가 간소화되며 가독성이 높아지고 Param 인터페이스 재사용 가능
참고도서: [실전 리액트 프로그래밍 / 저자_ 이재승 / 출판사_ 프로그래밍 인사이트]
'JavaScript > TypeScript' 카테고리의 다른 글
TypeScript | 타입 호환성 (0) 2020.05.07 TypeScript | Interface 인터페이스 (0) 2020.05.07 TypeScript | Enum 열거형 타입 (0) 2020.05.06 TypeScript | 개요 & 변수 타입 (0) 2020.05.06