반응형

# TypeScript 

## 실습_전화번호부 애플리케이션

  • 내려받은 소스 바탕으로 진행.
  • address-book 터미널로 열어서 npm i 진행.

tsconfig.json

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true,
    "target": "es5",
    "lib": ["es2015", "dom", "dom.iterable"],
    "noImplicitAny": true,
    "strict": true,
    "strictFunctionTypes": true
  },
  "include": ["./src/**/*"]
}

동기 / 비동기 코드

  • promise : 비 동기 처리 시 사용.
// 동기 코드.
// function fetchItems() {
//     let items = ['a', 'b', 'c'];
//     return items;
// }

// let result = fetchItems();
// console.log(result);


// 비동기 코드
function fetchItems(): Promise<string[]> {
    let items: string[] = ['a', 'b', 'c'];
    return new Promise(function(resolve) {
        resolve(items);
    });
}

Map

// map
let heroes= [
    { name: 'Kim', age: 30 },
    { name: 'Jin', age: 130 },
];

heroes.map(function(hero) {
    return hero.name;   // ['Kim', 'Jin']
});

index.ts

interface PhoneNumberDictionary {
  [phone: string]: {
    num: number;
  };
}

interface Contact {
  name: string;
  address: string;
  phones: PhoneNumberDictionary;
}

enum PhoneType {
  Home = 'home',
  Ofiice = 'office',
  Studio = 'studio',
}

// api
// TODO: 아래 함수의 반환 타입을 지정해보세요.
// promise
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);  // 2초
  });
}

// main
class AddressBook {
  // TODO: 아래 변수의 타입을 지정해보세요.
  contacts: Contact[] = [];

  constructor() { // 초기화 코드
    this.fetchData();
  }

  fetchData(): void {
    fetchContacts().then(response => {
      this.contacts = response;
    });
  }

  /* TODO: 아래 함수들의 파라미터 타입과 반환 타입을 지정해보세요 */
  findContactByName(name: string): Contact[] {
    return this.contacts.filter(contact => contact.name === name);
  }

  findContactByAddress(address: string): Contact[] {
    return this.contacts.filter(contact => contact.address === address);
  }

  // phoneNumber : hone,  office, studio -> enum으로 제한.
  findContactByPhone(phoneNumber: number, phoneType: PhoneType): Contact[] {
    return this.contacts.filter(
      contact => contact.phones[phoneType].num === phoneNumber
    );
  }

  addContact(contact: Contact): void {
    this.contacts.push(contact);
  }

  // map api
  displayListByName(): string[] {
    return this.contacts.map(contact => contact.name);
  }

  displayListByAddress(): string[] {
    return this.contacts.map(contact => contact.address);
  }
  /* ------------------------------------------------ */
}

new AddressBook();
반응형
반응형

# TypeScript 

## 제네릭

  • 제네릭 : Java 등의 언어에서 재사용성이높은 컴포넌트를 만들 때 자주 활용되는 특징. 한가지 타입 보다 여러 가지 타입에서 작동하는 컴포넌트를 생성하는데 사용된다.

기본 문법

function logText<T>(text: T): T {
    console.log(text);
    return text;
}

logText<string>('hi');

아래와 같이 인터페이스에 제네릭 선언 가능.

// 인터페이스에 제네릭 선언 방법
// interface Dropdown {
//     value: string;
//     selected: boolean;
// }

// const obj: Dropdown = { value: 'abc', selected: false };


interface Dropdown<T> {
    value: T;
    selected: boolean;
}

const obj: Dropdown<string> = { value: 'abc', selected: false };

기존 타입 정의 방식과 제네릭의 차이점 - 함수 중복 선언의 단점

  • 아래와 같이 타입을 다르게 받기위해 중복되는 코드 사용하는것은 유지보수 측면에서 좋지 않음.
function logText(text: string) {
    console.log(text);
    //text.split('').reverse().join('');
    return text;
}

function logNumber(num: number) {
    console.log(num);
    return num;
}

logText('hi');
logNumber(10);

기존 문법과 제네릭의 차이점 - 유니온 타입을 이용한 선언 방식의 문제점

  • 아래와 같은 경우 string과 number의 교집합인 공통으로 접근할 수 있는 속성, API 내에서만 자동완성 제공하는 문제점 존재.
function logText(text: string | number) {
    console.log(text);
    return text;
}

logText('hi');
logText(10);
  • 아래와 같이 변수로 받았을 경우 반환값에 대한 문제 발생.
const a = logText('hi');
a.split('');    // string과 number 타입이기 때문에 불가.

 

제네릭의 장점과 타입 추론에서의 이점

  • 제네릭 사용 시 아래와 같이 사용 가능.
function logText<T>(text: T): T {
    console.log(text);
    return text;
}

const str = logText<string>('abc');
str.split('');

const login = logText<boolean>(true);

제네릭 실전 예제. (이메일, 상품 수량 선택 드롭박스)

  • 방법1) 인터페이스와 유니온 사용하여 아래와 같이 가능.
interface Email {
  value: string;
  selected: boolean;
}

interface ProductNumber {
  value: number;
  selected: boolean
}

interface TrueFalse {
  value: boolean;
  selected: boolean
}

const emails: Email[] = [
  { value: 'naver.com', selected: true },
  { value: 'gmail.com', selected: false },
  { value: 'hanmail.net', selected: false },
];

const numberOfProducts: ProductNumber[] = [
  { value: 1, selected: true },
  { value: 2, selected: false },
  { value: 3, selected: false },
];

function createDropdownItem(item: Email | ProductNumber) {
  const option = document.createElement('option');
  option.value = item.value.toString();
  option.innerText = item.value.toString();
  option.selected = item.selected;
  return option;
}

// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
  const item = createDropdownItem(email);
  const selectTag = document.querySelector('#email-dropdown');
  selectTag.appendChild(item);
});

numberOfProducts.forEach(function (product) {
  const item = createDropdownItem(product);
  const selectTag = document.querySelector('#product-dropdown');
  selectTag.appendChild(item);
});

 

  • 방법2) 인터페이스에 제네릭을 사용하여 아래와 같이 가능.
interface DropdownItems<T> {
  value: T;
  selected: boolean;
}

// interface Email {
//   value: string;
//   selected: boolean;
// }

// interface ProductNumber {
//   value: number;
//   selected: boolean
// }

// interface TrueFalse {
//   value: boolean;
//   selected: boolean
// }

const emails: DropdownItems<string>[] = [
  { value: 'naver.com', selected: true },
  { value: 'gmail.com', selected: false },
  { value: 'hanmail.net', selected: false },
];

const numberOfProducts: DropdownItems<number>[] = [
  { value: 1, selected: true },
  { value: 2, selected: false },
  { value: 3, selected: false },
];

function createDropdownItem(item: DropdownItems<string> | DropdownItems<number>) {
  const option = document.createElement('option');
  option.value = item.value.toString();
  option.innerText = item.value.toString();
  option.selected = item.selected;
  return option;
}

// NOTE: 이메일 드롭 다운 아이템 추가
emails.forEach(function (email) {
  const item = createDropdownItem(email);
  const selectTag = document.querySelector('#email-dropdown');
  selectTag.appendChild(item);
});

numberOfProducts.forEach(function (product) {
  const item = createDropdownItem(product);
  const selectTag = document.querySelector('#product-dropdown');
  selectTag.appendChild(item);
});

제네릭의 타입 제한_1_.

// 제네릭의 타입 제한.
function logTextLength<T>(text: T[]): T[] {
    console.log(text.length);
    text.forEach(function (text) {
        console.log(text);
    });
    return text;
}

logTextLength<string>(['hi', 'abc']);

제네릭의 타입 제한_2_정의된 타입으로 타입 제한.

// 제네릭 타입 제한 _ 정의된 타입 이용.
interface LengthType {
    length: number;
}

function logTextLength<T extends LengthType>(text: T): T {
    console.log(text.length);
    return text;
}

logTextLength('a');
logTextLength(10);  // 불가.
logTextLength({ length: 10 });

제네릭의 타입제한_3_keyof로 제네릭의 타입 제한하기

// 제네릭 타입 제한 _ keyof
interface ShoppingItem {
    name: string;
    price: number;
    stock: number;
}

function getShoppingItemOption<T extends keyof ShoppingItem>(itemOption: T): T {
    return itemOption;
}

getShoppingItemOption('name');  // ctrl + space 로 자동완성 확인.
반응형
반응형

# TypeScript 

## 클래스

class.js

// ES2015 (ES6)
class Person {
    //클래스 로직
    constructor(name, age) {  // 초기화.
        console.log('생성 되었습니다.');
        this.name = name;
        this.age = age;
    }
}

var seho = new Person('세호', 35);
console.log(seho);

자바스크립트 프로토타입.

  • 자바스크립트는 프로토타입 기반의 언어.
var user = { name: 'capt', age: 100 };
var admin = {};
admin._proto_ = user;   // admin은 user를 상속받아 사용.
admin.name;
admin.age;
admin.role = 'admin';

자바스크립트 프로토타입 활용 사례.

 

Object - JavaScript | MDN

Object 클래스는 JavaScript의 데이터 유형 중 하나를 나타냅니다. 다양한 키 모음 및 더 복잡한 엔티티들을 저장하는 데 사용됩니다. 객체는 Object() 생성자 또는 객체 초기자 / 리터럴 구문를 통해 생

developer.mozilla.org

  • Built-in JavascriptAPI 또는 Javascript Native API

프로토타입과 클래스와의 관계.

  • 아래 코드는 동일한 코드임. (생성자 함수 사용한 것과, 클래스 사용한 것)
function Person(name, age) {
    this.name = name;
    this.age = age;
}

var capt = new Person('kim', 150);  // 아래와 동일 코드임.

// ES2015 (ES6)
class Person {
    //클래스 로직
    constructor(name, age) {  // 초기화.
        console.log('생성 되었습니다.');
        this.name = name;
        this.age = age;
    }
}

var seho = new Person('세호', 35);
console.log(seho);

타입스크립트의 클래스 문법.

class.ts

  • 타입 스크립트 에서의 클래스 문법
class Person {
    private name: string;   // 클래스에서 사용할 멤버변수 정의 필요.
    public age: number;     // 변수의 접근 범위 지정 가능. (private, public, readonly..)
    readonly log: string;   // readonly : 값에 접근만 할 수 있고 변경은 불가능.(읽기만)

    constructor(name: string, age: number) {
        this.name = name;
        this.age = age;
    }
}


// 리액트 예전 문법 - 클래스 기반 코드
class App extends React.Component {

}
// 리액트 최신 문법 - 훅 기반의 함수형 코드
function App() {
    return <div>Hello World</div>
}
반응형
반응형

# TypeScript 

## 이넘(Enum)

  • Enum : 특정 값들의 집합을 의미하는 자료형. (집합의 데이터 타입)

숫자형 이넘

별도의 값을 지정해주지 않으면숫자형 이넘으로 취급, 숫자 값 지정 시 다음 값은 해당 값부터 1씩 증가.

enum Shoes {
    Nike,
    Adidas,
    Sth,
}

var myShoes1 = Shoes.Nike;
var myShoes2 = Shoes.Adidas;
var myShoes3 = Shoes.Sth;

console.log(myShoes1);  // 0 출력. -> 별도의 값 지정하지 않으면 숫자형 이넘으로 취급.
console.log(myShoes2);  // 1 출력.
console.log(myShoes3);  // 2 출력.

문자형 이넘

enum Shoes {
    Nike = '나이키',
    Adidas = '아디다스',
}

var myShoes1 = Shoes.Nike;
var myShoes2 = Shoes.Adidas;

console.log(myShoes1);  // 나이키 출력.
console.log(myShoes2);  // 아디다스 출력.

이넘 활용

enum Answer {
    Yes= 'Y',
    No = 'N',
}
// 예제
function askQuestion(answer: Answer) {
    if(answer == Answer.Yes) {
        console.log('정답');
    }

    if (answer == Answer.No) {
        console.log('오답');
    }
}

// askQuestion('예스');
// askQuestion('y');
// askQuestion('Yes');
askQuestion(Answer.Yes);
askQuestion(Answer.No);
반응형

+ Recent posts