[TS] 인터페이스

Im-possible·2025년 4월 28일

인터페이스

- 객체의 속성명과 속성값의 타입을 지정
- 변수, 함수의 매개변수, 함수의 리턴 타입에 사용
- 속성은 `;` 또는 `,`로 구문
- interface 키워드로 선언하는 사용자 정의 타입
- 인터페이스를 타입으로 지정한 객체는 해당 인터페이스에 정의된 속성명과 타입을 준수해야함
- JS로 컴파일하면 제거됨

인터페이스를 객체의 타입으로 지정

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

const u1: User = {
  name: 'kim',
  age: 5,
};

함수의 리턴 타입으로 인터페이스 지정

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

const createUser = function(name: string, age: number): User {
  return { name, age }
}

const u3: User = createUser('lee', 20);

함수의 매개변수 타입으로 인터페이스 지정

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

const u1: User = {
  name: 'kim',
  age: 5,
};

function getAge(user: User): number{
  return user.age;
}

console.log(getAge(u1)); 

클래스에서 인터페이스 사용

-클래스의 타입 지정
- 클래스명 뒤에 `implements` 추가
- 인터페이스를 타입으로 지정한 클래스의 멤버 변수와 메서드는 인터페이스에 정의된 속성과 속성의 타입을 준수해야 함
- 인터페이스에 타입을 선언하면 타입 규칙을 지정해주는 것
- class 선언 시 인터페이스에 지정한 규칙을 따르지 않으면 타입 에러 발생
// 인터페이스 선언
interface Score {
  kor: number;
  eng: number;
  sum(): number;
  avg(): number;
}

// 클래스를 선언하며 인터페이스 지정
class HighSchool implements Score {
  kor: number;
  eng: number;
  constructor(kor: number, eng: number) {
    this.kor = kor;
    this.eng = eng;
  }
  sum(): number {
    return this.kor + this.engl
  }
  // 타입을 생략할 경우 타입 추론에 의해 리턴값을 파악하여 적절한 타입 추론
  avg() {
    return this.sum() / 2;
  }
}

// 총점과 평균 출력하는 함수
function printScore(score: Score) {
  console.log(score.sum(), score.avg());
}

const myScore = new HighSchool(100, 80);
printScore(myScore);

선택적 프로퍼티 (optional property)

- 객체의 속성을 선택적으로 부여하고 싶을 때 인터페이스 속셩명 뒤에 `?` 추가
interface Todo {
  id: number;
  title: string;
  content: string;
  done?: boolean
}

const todo1: Todo = {
  id: 1,
  title: '할일1',
  content: '내용1',
  done: false,
}

const todo2: Todo = {
  id: 2,
  title: '할일2',
  content: '내용2',
}

readonly

- 	객체 생성시에 값을 할당하면 생성한 후에는 수정이 불가능한 속성을 만들 때 사용
- 인터페이스의 속성명 앞에 `readonly` 추가
interface Todo {
  readonly id: number;
  title: string;
  content: string;
  done?: boolean
}

const todo1: Todo = {
  id: 1,
  title: '할일1',
  content: '내용1',
  done: false,
}

todo1.id = 2 // 컴파일 에러 => readonly 이므로 수정 불가

인터페이스 상속

- 부모 인터페이스의 속성과 메서드 정의를 자식 인터페이스가 물려 받고 확장
- 기존에 쓰던 타입 별칭에서, 기존의 타입 별칭을 유지하며 또 다른 속성을 추가하고 싶을 때 사용
- interface 선언부의 `extends` 를 추가하고 뒤에 상속 받을 부모 인터페이스 지정
// 인터페이스 선언
interface TodoRegist {
  title: string;
  content: string;
}

// TodoInfo는 title, content, id, done 속성을 가짐
interface TodoInfo extends TodoRegist {
  id: number;
  done: boolean;
}

const todo1: TodoRegist = {
  title: '할일1',
  content: '내용1',
}

const todo2: TodoInfo = {
  id: 1,
  title: '할일1',
  content: '내용1',
  done: false,
}

계층 구조로 상속

- 인터페이스 상속은 여러 단계의 게층 구조로 상속 가능
interface TodoRegist {
  title: string;
  content: string;
}

// TodoInfo는 title, content, id, done 속성을 가짐
intergace TodoInfo extends TodoRegist {
  id: number;
  done: boolean;
}

// TodInfoWithDate는 title, content, id, done, createdAt, updatedAt 속성을 가짐
interface TodoInfoWithDate extends TodoInfo {
  createdAt : Date;
  updatedAt : Date;
}

다중 상속

- 둘 이상의 인터페이스를 상속 받을 수 있음
- 부모 인터페이스에서 속셩이 겹칠 경우 타입이 동일해야한다.
  interface TodoRegist {
    title: string;
    content: string;	-  
  }

  interface TodoList {
    id: number;
    title: string;
    done: boolean;
  }
  
  // 다중 상속
  // TodoInfo는 title, content, id, done, createdAt, updatedAt 속성을 가짐
  interface TodoInfo extends TodoRegist, TodoList{
    createAt: Date;
	updatedAt: Date;
}

인터페이스 재선언(선언 병합)

- 동일한 이름의 인터페이스를 중복으로 선언
- 기존 인터페이스에 없는 속성을 추가
- 같은 이름의 속성을 재선언 할 경우 타입이 동일해야하며, 다른 경우 never 타입이 되기때문에 값을 넣을 때 에러 발생
- 기존의 인터페이스를 변경할 수 없는 경우(외부 라이브러리)에 사용
interface Todo {
  id: string;
  title: string;
  content: string;
}

// 재선언
interface Todo {
  // id: number; // 동일한 속성을 지정하려면 type이 같아야함
  title: string; // type이 같다면 동잃한 속성도 상관 없음
  done: boolean;
  createdAt: Date;
}

타입별칭과 인터페이스의 차이점

- 타입 별칭은 거의 모든 것을 정의 할 수 있다
- 인터페이스는 객체, 클래스의 타입을 정의할 수 있다
- 따라서 객체와 클래스를 정의할 때는 인터페이스를 사용하는 것을 추천

0개의 댓글