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])
- proto
새로 만든 객체의 프로토타입이어야 할 객체.- 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 && () =>
- bind ( ) 호출하여 묶어둠
- () => 선언될 당시 문맥,스코프의 this 컨텍스유지
모듈
한 파일안에 작성된 코드를 말하는것
모듈화
파일내 한정시키기 (접근통제)