본문 바로가기

TypeScript

TypeScript 인터페이스

Interface

 

인터페이스는 상호간에 정의 한 약속 , 규칙을 의미하며 TS에서 인터페이스는 보통 다음과 같이 정의 한다.

  • 객체의 스펙(속성과 속성의 타입)
  • 함수의 파라미터
  • 함수의 스펙
  • 배열과 객체를 접근하는 방식
  • 클래스

 

예제 코드를 보여드리자면

// TS 파일
let user: object;

user = {
	name : "Mr.Park"
	age: 31
}

console.log(user.name) // 어떤 값이 나올까?


네 에러가 발생합니다

 

object에는 특성 속성값이 없기 때문이죠? name에 마우스를 올려보면 object에 name 없다는 표시가 나옵니다.

이렇게 proporty를 정의해서 객체를 표현하고자 할때는 Interface를 사용합니다.

interface User {
  name: string;
  age: number;
  gender?: string;
}

let user: User = {
  name: "Mr.Park",
  age: 31,
};

user.gender = "male";

console.log(user.age); // 30
console.log(user.gender); // "male"

 

User 중괄호 안에 속성값을 정의하고 그 다음 let user는 User타입으로 명시를 합니다. User타입으로 명시하게 되면 오로지 User안에 요소와 속성들을 사용해야합니다.

let user 객체안에 gender값이 정의 되어 있지 않다는걸 확인 할 수 있을겁니다. 그런 성별은 optional로 처리를 할 수가 있는데 그것을 (?)물음표로 처리를 할 수가 있습니다.

 

옵션 속성은 단순히 인터페이스를 사용할때 속성을 선택적으로 적용할 수 있다는 것 뿐만 아니라

인터페이스에 정의 되어 있지 않은 속성에 대해서 인지 시켜줄 수 있다는 장점이 있습니다.

 

interface CraftBeer {
  name: string;
  hop?: number;
}

function brewBeer(beer: CraftBeer) {
  console.log(beer.from); // Error: Property 'from' does not exist on type 'Beer'
}

속성을 선택적으로 적용하기 위해서는 (?) 키워드를 쓰기 때문에 원래 같으면 정의된 속성 외에도 다른 속성에 대한 추가가 자유로웠지만, 더욱 엄격하게 제어할 수 있다.

 

readonly 읽기 전용 속성

 

readonly는 해당 속성이 읽기 전용임을 나타내며, 값을 한 번 설정하고 나면 변경할 수 없음을 의미합니다.

interface User {
  name: string;
  age: number;
  gender?: string;
  readonly birthYear: number;
}

let user: User = {
  name: "Mr.Park",
  age: 30,
  birthYear: 2000,
};
// user.birthYear = 1990; readonly로 인해 에러
console.log(user.birthYear) // 2000

여기서 readonly birthYear: number;User 인터페이스의 속성으로서, birthYear가 읽기 전용임을 정의합니다. 이 속성은 객체가 생성될 때 한 번만 값을 설정할 수 있으며, 이후에는 값을 변경할 수 없습니다.

 

읽기 전용 배열

배열을 선언할 때 ReadonlyArray<T> 타입을 사용하면 읽기 전용 배열을 생성할 수 있다.

let arr: ReadonlyArray<number> = [1,2,3];

arr.splice(0,1); // error
arr.push(4); // error
arr[0] = 100; // error
arr = [10, 20, 30]; // error

 

문자열 리터럴 타입(String Literal Types)

interface User {
  [grade: number]: string;
}

let user: User = {
  1: "A",
  2: "B",
};

나중에 추가해야할 속성이 생길수가 있죠? 이렇게 학년별로 점수를 기입 해야할때 배열안에도 정의 할 수 있습니다.

number를 key라고 하고 string을 value로 받는 proporty 여러개 받을 수 가 있습니다. 하지만 성적을 string으로 받기에는 범위가 넓죠? 그래서 사용할수 있는게 문자열 Literal 입니다. 

 

type Score = "A" | "B" | "C" | "F";

interface User {
  [grade: number]: Score;
}
let user: User = {
  1: "A",
  2: "B",
};

Score이라는 타입을 만들어서 실제로 문자열 리터럴 타입은 유니언 타입, 타입 가드 그리고 타입 별칭과 잘 결합됩니다. 이런 기능을 함께 사용하여 문자열로 enum과 비슷한 형태를 갖출 수 있습니다. 허용된 개의 문자열이 아닌 다른 문자열을 사용하게 되면 오류가 발생합니다.\

 

함수 타입 

interface는 함수 타입을 정의 할때에도 사용가능하다

ex1)

interface Add {
	(num1:number, num2:number): number;
}

const add : Add = function(x, y){
	return x + y
}

add(10, 20)

 

ex2) boolean값을 return 해봅시다.

interface Login {
  (username: string, password: string): boolean;
}
// Login 인터페이스는 string 타입의 매개 변수를 받고 boolean 타입을 return 하는 함수만 정의가 가능!

let loginUser: Login = function(id: string, pw: string) {
    console.log('로그인 했습니다.');
    return true;
}

let logoutUser: Login = function(id: string, pw: string) {
    console.log('로그아웃 했습니다.');
    return true;
}

 

interface 대신 type으로도 사용하여 정의할 수 있습니다.

// 함수 타입 정의
type AddFunction = (x: number, y: number) => number;

// 함수 타입을 사용하여 함수 구현
const add: AddFunction = (x, y) => {
  return x + y;
};

console.log(add(3, 5)); // 출력: 8

위의 코드에서 AddFunction이라는 타입을 정의했습니다. 이 타입은 (x: number, y: number) => number 형식으로, 두 개의 숫자 매개변수를 받아들이고 숫자를 반환하는 함수의 타입을 나타냅니다.

 

클래스 타입(implements)

 

TypeScript에서 클래스 타입을 인터페이스로 정의할 수 있습니다. 이를 통해 클래스가 특정한 인터페이스를 구현해야 함을 명시할 수 있습니다.

 

ex1)

// 인터페이스 정의
interface Printable {
  print(): void;
}

// Printable 인터페이스를 구현하는 클래스
class Printer implements Printable {
  print() {
    console.log("Printing...");
  }
}

// 인터페이스를 구현하지 않은 클래스
class NotPrinter {
  // print 메서드가 없기 때문에 컴파일 오류 발생
}

// Printable 타입의 변수에 Printer 클래스 인스턴스 할당
const printer: Printable = new Printer();
printer.print(); // 출력: Printing...

// Printable 타입의 변수에 NotPrinter 클래스 인스턴스 할당 - 컴파일 오류 발생
// const notPrinter: Printable = new NotPrinter();
// notPrinter.print();

위의 코드에서 Printable 인터페이스를 정의했습니다. 이 인터페이스에는 print() 메서드가 있으며 반환값이 없는 타입(void)입니다.

그리고 Printer 클래스를 Printable 인터페이스를 구현하는 형태로 정의했습니다. 이 클래스는 print() 메서드를 구현해야 하며, 이는 인터페이스에서 정의된 메서드와 시그니처가 일치해야 합니다.

NotPrinter 클래스는 Printable 인터페이스를 구현하지 않으므로, 컴파일 시에 오류가 발생합니다.

마지막으로 Printable 인터페이스를 타입으로 사용하여 printer 변수에 Printer 클래스의 인스턴스를 할당했습니다. 이를 통해 클래스의 인스턴스가 인터페이스의 요구사항을 충족하는지 확인할 수 있습니다.

 

ex2)

// implements
interface Car {
  color: string;
  wheels: number;
  start(): void;
}

class Bmw implements Car {
  color: string;
  wheels: 4;
  constructor(c: string) {
    this.color = c;
  }
  start() {
    console.log("go..");
  }
}

const b = new Bmw("green");
console.log(b); 
// Bmw: {
//	"wheels": 4,
//	"color": "green"
// }

b.start() // "go.."

'TypeScript' 카테고리의 다른 글

TypeScript 제네릭(Generics)  (0) 2024.02.07
Typescript 기초  (1) 2024.02.07