프로젝트 실습 파일:
실습자료
-learn-typescript
-quiz
-2_address-book
$ npm i
을 이용해서 package.json
에 정의해놓은 라이브러리들을 설치하자.✔️ tsconfig.json
"compilerOptions"
에서 "noImplicitAny"
를 true
로 바꿔주자."compilerOptions"
에 "strict": true
, "strictFunctionTypes": true
도 추가 해주자. ✔️ .eslintrc.js
'@typescript-eslint/no-explicit-any': 'off'
,"@typescript-eslint/explicit-function-return-type": 'off'
를 주석처리 해주자.실제 애플리케이션 개발시 API를 호출해 와서 API의 응답에 규칙, 규격을 정의할 때 제네릭을 가장 많이 사용하게 된다.
function fetchItems(): string[] {
var items = ['a', 'b', 'c'];
return items;
}
var result = fetchItems();
console.log(result);
fetchItems()
함수의 반환값이 string
으로 이루어진 배열이라는 것을 타입스크립트가 추론할 수 있다.
function fetchItems() {
var items = ['a', 'b', 'c'];
return new Promise(function(resolve) {
resolve(items);
})
}
fetchItems(): Promise<unknown>
이라는 메세지가 뜨게 된다.new Promise()
를 반환하게 되면 함수에서 기본적으로 추론하는게 Promise
가 오는데 그 안의 타입은 잘 모르겠다라고 보는 것이다.fetchItem()
함수를 실행하는 시점에서 타입스크립트가 Promise
안에 들어오는 비동기 코드들에 대해 알 수 없는 것이다.
Promise
에 어떤 타입이 올것인지 즉, 비동기 처리를 통해 돌려받을 반환 값이 무엇인지 명시를 해줘야Promise
를 제대로 사용할 수 있다.
function fetchItems(): Promise<string[]> {
var items = ['a', 'b', 'c'];
return new Promise(function(resolve) {
resolve(items);
})
}
fetchItems();
전화번호부 클래스 선언부 타입 정의
전화번호부 검색 메서드의 타입 정의
이넘을 이용한 타입 정의
주요 메서드(조회) 타입 정의 및 실습 마무리✔️ 아래 코드완성본의 주석 참고하자.
코드에 작성한 주석 잘 읽어보자
실습자료
-learn-typescript
-quiz
-2_address-book
-src
-index.ts
interface PhoneNumberDictionary {
[phone: string]: {
num: number;
};
}
interface Contact {
name: string;
address: string;
phones: PhoneNumberDictionary;
}
// 실제로 코드 작성시 오타로 인한 에러가 나는 경우가 발생할 수 있다.
// 따라서, 오타 등으로 인한 에러를 막기 위해 '변수화' 하는 것이 좋다.
// => 타입 관점에서 안전한 코딩
enum PhoneType {
Home = 'home',
Office = 'office',
Studio = 'studio'
}
// api
// TODO: 아래 함수의 반환 타입을 지정해보세요.
function fetchContacts(): Promise<Contact[]> {
// TODO: 아래 변수의 타입을 지정해보세요.
const contacts: Contact[] = [
{
name: 'Tony',
address: 'Malibu',
phones: {
home: {
num: 11122223333,
},
office: {
num: 44455556666,
},
},
},
{
name: 'Banner',
address: 'New York',
phones: {
home: {
num: 77788889999,
},
},
},
{
name: '마동석',
address: '서울시 강남구',
phones: {
home: {
num: 213423452,
},
studio: {
num: 314882045,
},
},
},
];
return new Promise(resolve => {
setTimeout(() => resolve(contacts), 2000);
});
}
// main
class AddressBook {
// TODO: 아래 변수의 타입을 지정해보세요.
contacts: Contact[] = []; // 메인 변수의 타입 정의
constructor() {
this.fetchData();
}
fetchData(): void {
fetchContacts().then(response => {
// response는 Contact[]라고 나온다.
// 위에서 fetchContacts()함수의 반환값이 Promise<Contact[]>이라고 정의했기 때문이다.
// (=> fetchContacts()함수가 Promise를 반환하고, 이 Promise의 타입이 Contact[]라고 정의된 것이다.)
// 따라서, fetchContacts()함수 실행 후 then으로 받았을 때 타입이 Contact[]가 되는 것이다.
this.contacts = response;
});
}
/* TODO: 아래 함수들의 파라미터 타입과 반환 타입을 지정해보세요 */
// return이 filter를 사용하기 때문에 그냥 Contact가 아닌 Contact[] 배열이라는 것을 적어줘야 한다.
// ( filter는 배열에 사용할 수 있다. )
findContactByName(name: string): Contact[] {
return this.contacts.filter(contact => contact.name === name);
}
findContactByAddress(address: string): Contact[] {
return this.contacts.filter(contact => contact.address === address);
}
// home, office, studio를 phoneType으로 받으려고 한다.
// 1개 이상이며 home, office, studio만 사용한단 것을 알기 때문에 '이넘'을 사용하면 좋다.
findContactByPhone(phoneNumber: number, phoneType: PhoneType): Contact[] { // 이넘을 이용한 타입 정의
return this.contacts.filter(
contact => contact.phones[phoneType].num === phoneNumber
);
}
addContact(contact: Contact): void { // 반환값이 없기때문에 void로 타입 설정한 것.
this.contacts.push(contact);
}
displayListByName(): string[] {
return this.contacts.map(contact => contact.name);
}
displayListByAddress(): string[] {
return this.contacts.map(contact => contact.address);
}
/* ------------------------------------------------ */
}
new AddressBook();
💡참고