[TypeScript] 인터페이스(Interface)
타입스크립트에는 객체의 타입을 정의하는 방법이 크게 두 가지가 있다. 하나는 앞서 배운 타입 별칭(Type Alias) 이고, 다른 하나는 이번에 다룰 인터페이스(Interface) 이다. 인터페이스는 타입에 이름을 지어주는 또 다른 문법으로, 특히 객체의 구조를 정의하는 데 특화되어 있다. 1. 기본 문법 인터페이스는 interface 키워드를 사용하여 정의한다. 타입 별칭과 문법만 조금 다를 뿐, 기본적인 기능은 거의 같다. TypeScript // 인터페이스 정의 interface Person { name: string; age: number; } // 변수에 타입 주석으로 사용 const person: Person = { name: "조태민", age: 25, }; --- 2. 프로퍼티 설정 객체 리터럴 타입에서 배웠던 선택적 프로퍼티나 읽기 전용 프로퍼티도 동일하게 사용할 수 있다. 2-1. 선택적 프로퍼티 (Optional Property) 프로퍼티 이름 뒤에 ?를 붙여서, 해당 속성이 없어도 에러가 나지 않게 설정할 수 있다. TypeScript interface Person { name: string; age?: number; // 있어도 되고 없어도 됨 } const person: Person = { name: "조태민", // age는 생략 가능 }; 2-2. 읽기 전용 프로퍼티 (Readonly Property) 프로퍼티 이름 앞에 readonly를 붙여서, 초기화 이후 값을 수정할 수 없게 만든다. TypeScript interface Person { readonly name: string; // 읽기 전용 age?: number; } const person: Person = { name: "조태민", age: 25, }; // person.name = "홍길동"; // ❌ 에러 발생 (수정 불가) --- 3. 메서드 타입 정의와 오버로딩 인터페이스 내부에서 메서드의 타입을 정의하는 방법은 두 가지가 있다. 어떤 방식을 쓰느냐에 따라 오버로딩 가능 여부가 달라지므로 주의해야 한다. 3-1. 함수 타입 표현식 (화살표 함수 형태) 가장 일반적인 형태지만, 메서드 오버로딩을 구현할 수 없다는 단점이 있다. TypeScript interface Person { sayHi: () => void; // sayHi: (a: number) => void; // ❌ 오버로딩 불가능 (에러 발생) } 3-2. 호출 시그니처 (Call Signature) 메서드 이름 뒤에 괄호를 여는 방식이다. 이 방식을 사용하면 메서드 오버로딩을 구현할 수 있다. TypeScript interface Person { sayHi(): void; sayHi(a: number): void; // ✅ 오버로딩 가능 sayHi(a: number, b: number): void; // ✅ 오버로딩 가능 } --- 4. 하이브리드 타입 (Hybrid Type) 자바스크립트에서는 함수도 객체이므로, 함수이면서 동시에 객체(프로퍼티를 가짐) 인 형태를 만들 수 있다. 인터페이스로도 이를 정의할 수 있다. TypeScript interface Func2 { (a: number): string; // 호출 시그니처 (함수로서의 역할) b: boolean; // 프로퍼티 (객체로서의 역할) } const func: Func2 = (a) => "hello"; func.b = true; --- 5. 주의할 점 (타입 별칭과의 차이) 인터페이스는 타입 별칭(type)과 거의 비슷하게 동작하지만, Union(|)이나 Intersection(&) 타입을 직접 정의할 수는 없다. TypeScript // 타입 별칭은 가능 type Type1 = number | string; // 인터페이스는 불가능 (문법 오류) // interface Person { ... } | number // ❌ 만약 인터페이스와 유니온/인터섹션을 함께 사용하고 싶다면, 타입 별칭을 이용해 합치거나 타입 주석에서 직접 사용해야 한다. TypeScript interface Person { name: string; age: number; } // 타입 별칭을 이용해 결합 type Type1 = number | string | Person; // 변수 선언 시 결합 const person: Person & string = { name: "조태민", age: 25, // ... string 메서드 등 }; --- 요약 1. 인터페이스: 객체의 구조를 정의하는 문법이다 (interface Name { ... }). 2. 프로퍼티: 선택적(?), 읽기 전용(readonly) 설정이 가능하다. 3. 메서드: - func: () => void (함수 타입 표현식) -> 오버로딩 불가 ❌ - func(): void (호출 시그니처) -> 오버로딩 가능 ✅ 4. 한계: 인터페이스 자체적으로 Union이나 Intersection을 생성할 수 없다 (타입 별칭과 조합하여 해결).