[TypeScript] 인터페이스: 속성

이영우·2023년 5월 30일
0

타입스크립트

목록 보기
3/5
post-thumbnail

인터페이스

인터페이스는 타입스크립트에서 객체 유형의 타입을 정의하는 도구이다.
데이터의 구조와 동작을 정의하는데 사용되며, 속성의 이름, 타입을 지정해 객체의 형태를 정의한다.

interface UserInfo {
  name: string;
  age: number;
  preferences: {
    theme: string;
    language: string;
  };
}

위 예제와 같이, 일종의 타입 설계도를 만든다고 이해하면 될 것 같다.

인터페이스는 두개의 글로 나눠서 정리할 것인데, 이 글에서는 인터페이스의 속성과 관련된 내용을 다뤄볼 것이다.


속성 수정자 (Property Modifiers)

속성 수정자는 타입스크립트에서 객체의 속성에 적용할 수 있는 키워드 or 문법이다.
다음과 같은 키워드로, 속성의 동작과 접근 방식을 제어한다.

readonly : 읽기 전용 속성, 값을 변경할 수 없는 속성을 정의
optional/ ?: 선택적 속성, 값을 생략할 수 있는 속성을 정의
public, private, protected: 접근 제어자, 속성에 대한 접근 수준을 제한
static: 정적 속성, 클래스 수준의 속성을 정의

오늘 내용에서 정리할 개념은 readonly와 optional이다.


읽기 전용 프로퍼티

interface UserInfo {
  name: string;
  readonly age: number;  // 읽기 전용 속성
  preferences?: {
    theme: string;
    language: string;
  };
}

const user = { name: 'hanni', age: 18 };

const logUserInfo = (user: UserInfo) => {
  console.log(user.name);
  user.age = 0;  // error: 읽기 전용 속성이므로 'age'에 할당할 수 없습니다.
};

logUserInfo(user);

위와 같이, interface 내에서 속성 이름(age) 앞에 readonly 키워드를 붙여주면, age 속성을 변경할 수 없게 된다.

하지만, 이는 값을 완전히 변경하지 못한다는게 아니다. 내부의 값은 변경할 수 있지만, 속성 자체를 다시 쓸 수 없다는 것을 뜻한다.
또한, readonly 키워드는 런타임 시 동작에 영향을 주지 않는다.


선택적 프로퍼티

interface UserInfo {
  name: string;
  age: number;
  preferences?: {  // 옵션 속성
    theme: string;
    language: string;
  };
}

const user = { name: 'hanni', age: 18 };
const logUserInfo = (user: UserInfo) => {
  console.log(user.name);
};

logUserInfo(user);

위 코드를 실행해보면, interface 내에 정의된 preferences가 인자로 넘어오지 않았는데도, 오류가 나지 않는다.

이렇게, 속성 이름 끝에 ?를 추가하여, 해당 속성을 선택 사항으로 지정할 수 있다.

옵션 속성을 사용하면 속성이 필수가 아니게 되지만,
인터페이스 내부에 없는 속성의 사용을 방지할 수 있어 적절한 상황에 사용하면 장점이 있다.



인덱스 시그니처 (Index Signatures)

인덱스 시그니처란?
타입스크립트에서 동적으로 속성에 접근하기 위해 사용되는 기능이다.
또한, 미리 모든 속성의 이름을 알 수 없지만 값의 형태는 알고 있을 때,
인덱스 시그니처를 통해 가능한 유형의 값을 정의할 수 있다.

interface MyDictionary {
  [index: string]: number;
}

인덱스 시그니처는 위와 같은 형태로 작성한다.
index는 인덱스에 타입, value 자리에 있는 number는 해당 인덱스에 접근했을 때, 반환되는 타입을 나타낸다.

const dictionary: MyDictionary = {
  one: 1,
  two: 2,
  three: 3,
};

console.log(dictionary['two']); // 2
console.log(dictionary['four']); // undefined

위 예제와 같이 정의한 인터페이스를 타입으로 갖는 객체에 동적으로 접근할 수 있다.
인덱스 시그니처를 활용하면, 간편하게 객체의 동적인 속성을 처리할 수 있다.


초과 속성 검사 (Excess Property Checks)

초과 속성 검사란?
타입스크립트에서 객체 리터럴이 다른 변수에 할당, 혹은 함수의 매개변수로 전달될 때, 정의되지 않은 추가적인 속성이 있는지 검사하는 동작이다.

interface IdolGroup {
  group?: string;
  member?: string;
}

const logIdol = (idol: IdolGroup) => {
  console.log(idol.group, idol.member);
};

logIdol({ group: '뉴진스', member: '강해린', strange: '강해린 이상하다' });
/* error : 개체 리터럴은 알려진 속성만 지정할 수 있으며 
'IdolGroup' 형식에 'strange'이(가) 없습니다 */

함수 logIdol은 매개변수로 IdolGroup인터페이스 형식의 idol을 받는데,
strange라는 추가 속성이 존재해서, 초과 속성 검사가 발생하고 오류를 표시해준다.

위 예제는 함수로 예를 들었지만, 객체 리터럴이 변수에 할당되는 경우에도 해당 동작이 발생한다고 한다. 타입스크립트는 여러모로 안정성 측면에서 이점이 있는 것 같다.


마치며

인덱스 시그니처 / 초과 속성 검사가 익숙한 개념이 아니라서 조금 헤맸다.
공식 문서가 읽기에는 조금 딱딱해도 필요한 내용이 잘 정리되어있는 것 같다. 다음 글에서는 인터페이스의 확장과 교차 유형에 대해 알아보자. 👍


참고 문서

profile
학습한 기술 지식들을 기록합니다.

0개의 댓글