[TypeScript] Interface

dev.galim·2023년 9월 14일

TypeScript

목록 보기
7/10

Interface

→ 타입들의 이름을 짓는 역할을 하고 코드 안의 계약을 정의, 프로젝트 외부에서 사용하는 코드의 계약을 정의하는 것.

  • 일반적으로 변수, 함수, 클래스에 타입 체크를 위해 사용됨.
  • 직접 인스턴스를 생성할 수 없고, 모든 메소드가 추상 메소드임.
  • 추상 클래스의 추싱 메소드와 달리 abstract 키워드는 사용할 수 없음.
📌 ES6는 인터페이스를 지원하지 않지만 타입스크립트는 인터페이스를 지원함.

Interface를 사용하는 이유

  • 타입의 이름을 짓고 코드 안의 계약을 정의하기 위해 사용함.
  • 프로젝트 외부에서 사용하는 코드의 계약을 정의하는 강력한 방법.
    • 다음과 같은 범주에 대해 계약을 정의할 수 있음.
      • 객체의 스팩(속성과 속성의 타입)
      • 함수의 파라미터
      • 함수의 스팩(파라미터, 반환 타입 등)
      • 배열과 객체에 접근하는 방식
      • 클래스

Interface 기본 예제

function sayName(obj: { name: string }) {
	console.log(obj.name);
}

let persone = { name: "june");

sayName(person};
interface Person {
	name: string;
}

function sayName(obj: person) P
	console.log(obj.name);
}

let person = {name: "june"};

sayName(person);

인터페이스를 추가하여 함수 매개변수 프로퍼티를 정의할 수 있다.

정의한 프로퍼티 값을 누락하거나 정의하지 않은 값을 인수로 전달 시 컴파일 에러가 발생한다.


Properties

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

Optional Properties(선택적 프로퍼티)

→ 인터페이스의 모든 프로퍼티가 필요한건 아니다.

어떤 조건에서만 존재하거나 아예 없을 수도 있다.

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

function createSquare(config: SquareConfig): {color: string; area: number} {
    let newSquare = {color: "white", area: 100};
    if (config.color) {
        newSquare.color = config.color;
    }
    if (config.width) {
        newSquare.area = config.width * config.width;
    }
    return newSquare;
}

let mySquare = createSquare({color: "black"});

Readonly properties

→ 객체가 처음 생성될 때만 값 설정이 가능하고, 이후 수정이 불가능함.

프로퍼티 이름 앞에 readonly를 붙여 사용.

interface Point {
	readonly x: number
	readonly y: number
}

let point: Point = { x: 10, y: 20};
point.x = 5; // Error, readonly를 사용했기 때문에 수정할 수 없어 에러가 발생함.
  • readonly vs const
    • readonly와 consyt의 공통점 → 생성 후에 배열을 변경하지 않음.
    • 변수는 const, 프로퍼티는 readonly를 사용함.

Interface types

→ 타입스크립트에서 인터페이스는 함수, 클래스에서 사용할 수 있음.

  • 함수
    • 자바스크립트 객체가 가질 수 있는 넓은 범위의 형태를 기술할 수 있다.
    • 프로퍼티로 객체를 기술하는 것 외에도, 인터페이스는 함수 타입을 설명할 수 있다.
  • 클래스
    • 클래스가 특정 통신 프로토콜을 충족하도록 명시적으로 강제함.
    • C#, Java와 같은 언어에서 일반적으로 인터페이스를 사용하는 방법과 동일함.

function type

→ 함수 인자의 타입과 반환 값의 타입을 정의함.

함수의 타입을 정의할때도 사용.

interface SearchFunc {
    (source: string, subString: string): boolean;
}
  • 인터페이스로 함수 타입을 기술하기 위해, 인터페이스에 호출 서명을 전달한다. 이는 매개변수 목록과 반환 타입만 주어진 함수 선언과 비슷하다. 각 매개변수는 이름과 타입이 모두 필요하다.
let mySearch: SearchFunc; // 함수 타입의 변수 생성
mySearch = function(source: string, subString: string) {
    let result = source.search(subString);
    return result > -1;
} // 같은 타입의 함수 값으로 할당.
  • 한번 정의되면 함수 타입 인터페이스는 다른 인터페이스처람 사용할 수 있다.

class type

→ 클래스가 특정 계약(contract)을 충족하도록 명시적으로 강제한다.

interface Animal {
	makeSound(): void
}

class Dog implements Animal {
	makeSound(): void {
		console.log("멍멍");
	}
}

Interface 확장

→ 클래스와 마찬가지로 인터페이스도 인터페이스 간의 확장이 가능하다.

interface Animal {
	makeSound(): void
}

interface Dog extends Animal {
	speed: number
}

class Bulldog implements Dog {
	makeSound(): void {
		console.log("멍멍");
	}
}

extends → 타입의 확장으로 사용된다.

implements →

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;
  • 이처럼 함수타입이면서 객체 타입을 정의할 수 있는 인터페이스도 구현이 가능하다.

디자인 패턴(Strategy pattern)

→ 객체가 할 수 있는 행위들을 전략(strategy)으로 만들어놓고, 동적으로 행위에 수정이 필요할 경우 전략 객체를 새로 생성하여 변경, 주입하여 다른 행위가 가능하도록 하는 디자인 패턴.

Interface를 활용한 디자인 패턴

  • 디자인 패턴 활용 사례
    class VendingMachine {
    	pay() {
    		console.log("cath pay!");
    	}
    }
    • 자판기 결제 방법을 현금 결제에서 카드 결제로 변경할 때, Pay 메소드 구현 변경이 필요하다.
    • 메소드 수정 방식의 문제점
      • OCP를 위배한다(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
profile
열심히 해볼게요

0개의 댓글