TypeScript 스터디 자료

roberto·2022년 7월 11일
0

1주차

캡슐화

관련된 아이들 끼리 묶기

추상화

내부 복잡한 기능을 다이해하지않고 외부의 인터페이스를 통해 이해하는것
ex) 자동차내부 원리 몰라도 핸들만 돌리면 됨

상속 (재사용)

브라우저 돔요소도 모두 상속!

다형성

절차지향

객체지향 실습

  • 클래스 안에있는 멤버 변수 접근 시에는 this

예제 커피머신

 class CoffeeMaker {
 	-
//👉 멤버변수 메모리낭비 -> static 키워드를 가지고 class 레벨로 지정 
     static BEANS_GRAMM_PER_SHOT: number=7;
     coffeeBeans: number = 0 ;
    -
    //인스턴스 만들떄 호출 
     constructor(coffeeBeans: number){
         this.coffeeBeans = coffeeBeans;
     }
	-
     makeCoffee(shots: number): CoffeeCup { 
         if(this.coffeeBeans < shots * CoffeeMaker.BEANS_GRAMM_PER_SHOT){
             throw new Error('NOT ENOUGH COFFEE BEANS');
         }
         this.coffeeBeans -= shots * CoffeeMaker.BEANS_GRAMM_PER_SHOT;
         return {
             shots,
             hasMilk: false,
         };
     }
    const maker = new CoffeeMaker(32);
 }

커피 머신 캡슐화 예제

 class CoffeeMaker {
-
//👉 멤버변수 메모리낭비 -> static 키워드를 가지고 class 레벨로 지정 
    private static BEANS_GRAMM_PER_SHOT: number=7;
    private coffeeBeans: number = 0 ;
-
    //👉 private 설정함으로서 사용자에게 클래스 내부 static 메소드가 있다고 알림
    private constructor(coffeeBeans: number){
         this.coffeeBeans = coffeeBeans;
 	}
    -
    //👉 클래스 만들지 않고 밖에서 접근 가능 
    static makeMachine(coffeeBeans: number): CoffeeMaker {
        return new CoffeeMaker(coffeeBeans)
    }
	-
    //👉 내부의 상태를 변경 하는 함수 
    fillCoffeeBeans(beans: number){
        if(beans < 0){
            throw new Error('--- 0 x ')
        }
        this.coffeeBeans += beans;
    }
	-
     makeCoffee(shots: number): CoffeeCup { 
         if(this.coffeeBeans < shots * CoffeeMaker.BEANS_GRAMM_PER_SHOT){
             throw new Error('NOT ENOUGH COFFEE BEANS');
         }
         this.coffeeBeans -= shots * CoffeeMaker.BEANS_GRAMM_PER_SHOT;
         return {
             shots,
             hasMilk: false,
         };
     }
	-
    const maker = new CoffeeMaker(32);
	-
    //외부 접근 가능 
    //maker.coffeeBeans = 3 
 }

getter & setter

     class User { 
        firstName: string;
        lastName: string;
        fullName: string;
        constructor(firstName: string, lastName: string){
            this.firstName = firstName;
            this.lastName = lastName;
            this.fullName = `${firstName} ${lastName}`;
        }
-
        const user = new User('steve','Jobs');
        console.log(user.fullName); //steve Jobs
        user.firstName = 'Ellie';
        console.log(user.fullName); //👻 steve Jobs "!!동일한 값이나온다"   
    }

동일한 값이 나오지않기위해

추상화 예제

  • 추상화 - 인터페이스 다른사용자가 사용할수 있도록 "깔끔하게"
  • 추상화 방법
    1. 접근제어자(private..)통해 캡슐화를 함으로
    2. 인터페이스를 통해

2.인터페이스를 통한 예제

📌public 함수들 접근가능
const maker: 👉CoffeeMachine = CoffeeMachine.makeMachine(32);
maker.fillCoffeeBeans(32);
maker.makeCoffee(2);
maker.clean();
-
📌인터페이스로 타입을 제한에서 받게되면 인터페이스 안에있는것들만 가능하다
const maker2: 👉ICoffeeMker = CoffeeMachine.makeMachine(32);
maker2.fillCoffeeBeans(32);
maker2.makeCoffee(2);
maker2.clean();

STACK 구현해보기 (객체지향활용)

조건

📌언어자체 제공하는 배열 이용 x => 연결리스트 사용

//👉 Head -> Node1 ->Node2
//👉 인터페이스만을 이용해서 사용 
-
interface Stack{
//👉값변경 불가 내부적으로
    readonly size: number;
    push(value:string): void;
    pop(): string;
}
-
type StackNode = {
    //👉readonly => 값이 변경 되지 않도록 하기 위함 
    readonly value : string;
    //👉다른 노드를 가리키거나 가르키지 않거나(마지막)
    readonly next?: StackNode
    // next: StackNode |  undefined;
}
-
class StackImpl implements Stack {
    //👉읽기만 가능
    private _size: number=0;
    private head?: StackNode;
    get size(){
        return this._size;
    }
    push(value:string){
        this._size++;
        //👉새로운 value 가 들어오면 value를 감싸는 노드를 만든다
        const node: StackNode = {value, next: this.head}
        //👉head 는 새로들어온 노드를 가르키도록
        this.head = node;
        this._size++;
    }
    pop(): string {
        //👉노드는 있을수도 없을수도 있다 (null == undefined)
        if(this.head == null){
            throw new Error('스택이 비어있어 확인해')
        }
        //👉제거하고자 하는노드
        const node = this.head;
        //👉head 다음 것을 가르키도록
        this.head = node.next;
        this._size--;
        return node.value;
    }
}

2주차

1. 제네릭


📌왜쓰지 제네릭 ? => 재사용! up!

함수를 제네릭하게 예제

{     
    //1️⃣숫자만 체크  
    .
    function checkNotNUll(arg: number | null): number {
        if(arg == null) {
            throw new Error('not valid number!');
        }
        return arg;
    }
    .
    //2️⃣모든 타입체크를 위해 any 의 사용은 타입이 안전하지않음
    .
    function checkNotNUllAny(arg: any | null): any{
           if(arg == null) {
            throw new Error('not valid number!');
        }
        return arg;
    }
    const result = checkNotNUllAny(123);
	.
    //✨3️⃣제네릭을 이용해 타입을 보장 GENERIC 타입을 받아서 리턴 
    .
    //null 이 아닐때만 똑같은 타입으 반환하는 함수
    function checkNotNullGeneric<TYPE>(arg: TYPE | null):TYPE{
            if(arg == null) {
            throw new Error('not valid number!');
        }
        return arg;
    }
    const number = checkNotNullGeneric(123)
    const boal: boolean = checkNotNullGeneric(true)
}

클래스를 제네릭하게 예제

//👉쓰는 사람이 LEFT,RIGHT 타입을 결정
interface Either <LEFT, RIGHT>{
    left: () => LEFT;
    right: () => RIGHT;
}
.
class SimpleEither<LEFT, RIGHT> implements Either<LEFT, RIGHT> {
    constructor (private leftValue: LEFT, private rightValue: RIGHT) {}
    left(): LEFT {
        return this.leftValue;
    }
    right(): RIGHT{
        return this.rightValue
    }
}
.
const either: Either<number, number> =new SimpleEither(4,5);

제네릭 조건

세부 적인 타입을 인자로 받아서
추상적인 타입으로 다시 리턴하는 함수는 => 좋지않다
타입은 추상적으로 만들어야함

2. API 읽어보기

타입스크립트는 오픈소스 프로젝트이다 !
https://github.com/microsoft/TypeScript/blob/master/lib/lib.es5.d.ts

3. 에러처리 하기

에러처리를 위해
Java 에는 => Exception 이라는 클래스가 있다
Js 에는 => Error 라는 클래스가 있다

예상치 못한 이슈가 위처럼 발생한다

어디서 ??? try catch 를 사용해야할까?

👉 application 레벨에서 사용하자!

세부적인 에러 => Error state 사용!

예제)

{
  type NetworkErrorState = {
    result: 'fail';
    //👉왜실패했는지 세부적인 이유 (유니온타입)
    reason: 'offline' | 'down' | 'timeout';
  };
.
  type SuccessState = {
    result: 'success';
  };
.
  type ResultState = SuccessState | NetworkErrorState;
.
  //👉성공 실패 ResultState
  class NetworkClient {
    tryConnect(): 👉ResultState {
      return {
        result: 'success',
      };
    }
  }
.
  class UserService {
    constructor(private client: NetworkClient) {}
.
    login() {
      this.client.tryConnect();
    }
  }
.
  class App {
    constructor(private userService: UserService) {}
    run() {
      try {
        this.userService.login();
      } catch (error) {
        // show dialog to use
      }
    }
  }
  const client = new NetworkClient();
  const service = new UserService(client);
  const app = new App(service);
  app.run();
}

3. 막강한타입

Type Alias vs Interface

  • 차이점과 공통점들
type PositionType ={
    x:number;
    y:number;
}
.
interface PostionInterface{
    x: number;
    y: number;
}
.
//✨오브젝트형태로 둘다 구현 가능 
const obj1: PositionType = { 
    x: 1,
    y: 1,
}
.
const obj2: PositionType ={
    x: 1,
    y: 1,
}
.
//클래스에서 둘다 구현 가능 
class Pos1 implements PositionType{
    x:number;
    y:number;
}
.
class Pos2 implements PostionInterface{
    x:number;
    y:number;
}
.
// 🎆 오직 인터페이스에서만 여러 곳에서 선언가능
interface coffee{
    x: number
}
interface coffee{
    y: number
}
.
// 🎇 오직 타입만 computed properties 가능 , 유니온 타입가능 
type Person = {
    name : string,
    age: number,
}
.
type Name = Person['name']; //string 
.
type Direction = 'left'|'right'

type 은 데이터를 담을 목적일떄쓴다!!

interface 는 규격을 정할떄 쓴다 !!

유틸리티 타입

1. Index Type

📌 다른타입의 키의 벨류 선언 가능

type Animal = {
    name : string;
    age: number;
    gender: 'maele'|'female';
};
.
type Name = Animal['name']; //string
const text: Name = 'helllo'
.
type Gender = Animal['gender']; //'male' | 'female'
.
type Keys = keyof Animal; //'name' | 'age' | 'gender'
const key: Keys = 'gender';

2. Mapped Type

📌 기존의 타입들을 이용하면서 다른형태로 변환해서 사용

type Video = {
    title: string;
    author: string;
}
.
// 👉 T 오브젝트 타입의 모든 키들을 돌면서 그키에해당하는 value의 타입을 정의 
type Optional<T> ={
    [P in keyof T]?: T[P] //for...in 키를돌며 타입 할당
}
type VideoOptional =Optional<Video>;
//사용
const videoOp: VideoOptional ={
    animal //에러
}
.
//👉 성질 변화 => 타입변경 불가! 
type ReadOnly<T> = {
    readonly [P in keyof T]: T[P];
};
.
//👉 주어진 T타입과 null 이가능하도록 타입을 설정 
type Nullable<T> = { [P in keyof T]: T[P] | null}
.
//👉 타입스크립트 타입 예제 - 전달된 오브젝트를 돌면서 Proxy 라는 타입으로 한단계 감싸는 역할을 한다
type Proxify<T> = {
    [P in keyof T]: Proxy<T[P]>;
}

3. Conditional Type

📌

//👉 문자열을 상속 한다면 ? boolean
type Check<T> = T extends string ? boolean : number ;
type Type = Check<String>;
.
//👉 타입스크립트 예제 
type TypeName<T> = T extends string
?'string'
: T extends number
?'number'
: T extends boolean
? 'boolean'
: T extends undefined
? 'undefined'
:object;
.
type T0 = TypeName<string>; 'string'
type T1 = TypeName<'a'>; 'string'

3. ReadOnly Type

📌 읽을수만 있는 타입

4. partial Type

📌 기존의 타입중에서 부분적인것만 허용하고 싶을때 사용

type ToDo = {
    title : string;
    description: string;
    label: string;
    priority: 'high' | 'low'
};
.
function updateTodo(todo: ToDo, fieldsToUpdate: Partial<ToDo){
    return {...todo, ...fieldsToUpdate};
}
.
const todo: ToDo ={
       title : 'a',
    description: 'a',
    label: 'a',
    priority: 'high',
}
.
const updated = updateTodo(todo, {priority:'low'});
console.log(updated);

5. pick Type

📌 기존의 타입중에서 원하는 타입만

6. Omit Type

📌 기존의 타입중에서 빼고싶은 타입만

7. Record Type

📌 하나를 키로쓰고 나버지른 다른타입으로 묵고싶을때(맵과비슷)

type PageInfo = {
    title: string;
}
.
type Page = 'home' | 'about' | 'contact';
.
const nav: Record<Page, PageInfo> = { 
    home: {title:'Home'},
    about: {title: 'About'},
    contact: {title: 'Contact'}
}

4주차

프로토 타입 :

📌 상속을 위해 쓰임 - 반복적으로 쓰일수 있게 속성, 행동정의



프로토 타입 데모

자바스크립트 모든 오브젝트는 __propto 를 상속(가지고)있다

Object.create()

Object.create(proto[, propertiesObject])

  1. proto
    새로 만든 객체의 프로토타입이어야 할 객체.
  2. propertiesObject
    선택사항. 지정되고 undefined가 아니면,
    자신의 속성(즉, 자체에 정의되어 그 프로토타입 체인에서 열거가능하지 않은 속성)이
    열거 가능한 객체는 해당 속성명으로 새로 만든 객체에 추가될 속성 설명자(descriptor)를
    지정합니다.
    이러한 속성은Object.defineProperties()의 두 번째 인수에 해당합니다
// Shape - 상위클래스
function Shape() {
  this.x = 0;
  this.y = 0;
};
.
// 상위클래스 메서드
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};
.
// Rectangle - 하위클래스
function Rectangle() {
  Shape.call(this);
};

참고

this 봉인하기 bind && () =>

  1. bind ( ) 호출하여 묶어둠
  2. () => 선언될 당시 문맥,스코프의 this 컨텍스유지

모듈

한 파일안에 작성된 코드를 말하는것

모듈화

파일내 한정시키기 (접근통제)

profile
medium 으로 이전했습니다

0개의 댓글