[엘리스 SW트랙 4기] 5주차 - Day 25 : TypeScript Interface / Generic

랸나·2023년 3월 31일
0

1. Interface

Interfaces란?

  • 일반적으로 변수, 함수, 클래스에 타입 체크를 위해 사용
  • 직접 인스턴스 생성 불가, 모든 메소드가 추상 메소드
  • abstract키워드는 사용하지 않음.
  • ES6는 인터페이스 지원 X , TypeScript는 지원함.
  • 타입의 이름을 짓고 코드 안의 계약을 정의
    • 객체의 스펙(속성, 속성의 타입)
    • 함수 파라미터
    • 함수의 스펙(파라미터, 반환타입)
    • 배열과 객체에 접근하는 방식
    • 클래스

Properties

  • 컴파일러는 프로퍼티의 두가지 요소를 검사함.
    • 필수요소 프로퍼티의 유무
    • 프로퍼티 타입
  • 아래 예약어로 프로퍼티를 세밀하게 컨트롤 가능
    • ? (Optional Properties)
    • readonly(Readonly properties)

optional properties

  • 프로퍼티 선언 시 이름 끝에 ?를 붙여 표시
  • 인터페이스에 속하지 않는 프로퍼티의 사용 방지 + 사용 가능한 프로퍼티 기술
  • 객체 안의 몇개의 프로퍼티만 채워 함수에 전달하는 "option bags"같은 패턴에 유용
interface SquareConfig{
  color?: string
  width?: number
}

Readonly properties

  • 객체가 처음 생성될 떄만 설정이 가능. 이후 수정 불가
  • 프로퍼티 이름 앞에 readonly를 붙여 사용.
interface Point{
	readonly x: number
    readonly y: number
}

let point: Point = { x: 10, y:20 };
point.x =5 // Cannot assign to 'x' because it is a read-only property 

readonly vs const

  • 공통점 : 생성 후에 배열을 변경하지 않음을 보장
  • 변수는 const 사용, 프로퍼티는 readonly 사용.

Interface types

  • 인터페이스는 함수, 클래스에서 사용 가능
  • function type
    • 함수의 인자의 타입과 반환 값의 타입을 정의
    • 함수의 타입을 정의할 때에도 사용.
interface SearchFunc{
	(source : string, subString: string): boolean 
}
  • class type
interface Animal{
	makeSound(): void
}

interface 확장

  • 클래스와 마찬가지로 인터페이스도 인터페이스 간의 확장이 가능하다.
interface Animal {
	makeSound(): boid
}

interface Dog extends Animal {
	speed : number
}

hybrid type

  • 함수타입이면서 객체 타입을 정의할 수 있는 인터페이스도 구현 가능
interface Counter {
	(start: number):string
    interval: number
    reset(): void
}

function getCounter(): Counter {
	let counter = function (start: number){} as counter
    counter.interval = 123;
    counter.reset = function(){}
    return counter;
}

let c = getCounter();
c(10);
c.reset();
c.interval = 5.0;

디자인 패턴

  • interface를 활용한 디자인 패턴(Strategy pattern) : 객체가 할 수 잇는 행위들을 전략으로 만들어두고 동적으로 행위의 수정이 필요한 경우 전략을 바꾸는 것 만으로 수정이 가능하도록 만든 패턴

  • 메소드 방식의 문제점 : OCP(Open Closed Principle) 위배, 시스템이 커져서 확장될 경우 연동되는 시스템에도 영향을 줄 수 있음.

  • OOP설계원칙

interface PaymentStrategy {
	pay(): void	
}

class CardPaymentStrategy implements PaymentStrategy{
  pay(): void{
  	console.log("card pay!")
  }
}

class CashPaymentStrategy implements PaymentStrategy{
	pay(): void{
   	  console.log("Cash pay!");
    } 
}

class VendingMachine{
  private paymentStrategy: PaymentStrategy
  
  setPaymentStrategy(paymentStrategy: PaymentStrategy){
    this.paymentStrategy = paymentStrategy;}
}

	pay(){
	this.paymentStrategy.pay();
	}
}
const vendingMachine = new VendingMachine();

vendingMachine.setPaymentStrategy(new CashPaymentStrategy());
vendingMachine.pay(); //cash pay

vendingMachine.setPaymentStrategy(new CardPaymentStrategy());
vendingMachine.pay(); //card pay

2. Generic

2-1. Generic이란?

  • Generic은 코드를 작성할 떄가 아니라 코드가 수행될 떄 타입을 명시한다.
  • 코드를 작성할 때 식별자를 써서 아직 정해지지 않은 타입을 표시한다. (일반적으로 T,U,V...를 사용. 필드 이름의 첫 글자를 사용하기도 함)
  • 재사용성이 높은 함수와 클래스 생성 가능
  • 오류를 쉽게 포착 가능( any처럼 미리 타입을 지정하진 않지만, 타입을 체크해 컴파일러가 오류를 찾을 수 있음)

2-2. Generic을 사용해 function과 class 만들기

//제네릭으로 함수 만들기
function sort<T>(items: T[]): T[]{
	return items.sort();
}

const nums: number[] = [1,2,3,4];
const chars: string[] = ["a","b","c","d"]

sort<number>(nums);
sort<string>(chars);
//제네릭으로 클래스 만들기
class Queue<T>{
	protected data: Array<T> = [];
    push(item:T){
      this.data.push(iem);
      }
    pop(): T | undefined{
      return this.data.shift();
    }  
}
  

2-3. Union type

  • Union type : "|"를 사용해 두개 이상의 타입을 선언하는 방식
  • Union & Generic 모두 여러 타입 다룰 수 잇음.
    • Union은 선언한 공통된 메소드만 사용 가능.
    • 리턴값이 하나의 타입이 아닌 선언된 Union 타입으로 지정됨.

2-4. 제약조건(Constraints / keyof)

  • Constraints : 특정 타입들로만 동작하는 Generic 함수를 만들 때 사용.
const printMessage = <T extends string|number>(message: T): T => {
	return message;
}

printMessage<String>("1");
printMessage<Number>(1);
printMessage<Boolean>(false); //Error
  • Keyof: 두 객체를 비교할 떄 사용
const getProperty = <T extends object, U extends keyof T> (obj: T, key: U) => {
	return obj[key];
}

getProperty({a:1 , b:2 , C:3}, "a");
getProperty({a:1, b:2, c:3}, "z"); //error

2-5. Design pattern(Factory Pattern with Generics)

  • 객체를 생성하는 인터페이스만 미리 정의하고, 인스턴스를 만들 클래스의 결정은 서브클래스가 내리는 패턴.
  • 여러개의 서브 클래스를 가진 슈퍼 클래스가 있을 때, 입력에 따라 하나의 서브 클래스의 인스턴스를 반환한다.
profile
백엔드개발자

0개의 댓글