인터페이스란
인터페이스는 객체의 형태를 설명하는 데 사용할 수 있습니다.
클래스와 달리 인터페이스는 청사진으로 사용하지 않고 사용자 정의 타입으로 사용할 뿐입니다.
interface Person {
name: string;
age: number;
// 메서드
greet(phrase: string): void
}
기본값을 할당하려 하면 다음과 같은 에러가 발생합니다.
구체적인 값이 아닌 구조만 있을 뿐입니다.
interface Person {
name: string;
age: number;
greet(phrase: string): void
}
let user1: Person;
user1 = {
name: 'KIM',
age: 29,
greet(phrase: string) {
console.log(phrase + ' ' + this.name)
}
}
이렇게 인터페이스를 이용하여 객체의 구조를 정의할 수 있게 해 줍니다.
사용자 정의 타입과 인터페이스
interface Greetable {
readonly name: string;
greet(phrase: string): void
}
type Greetable = {
readonly name: string;
greet(phrase: string): void
}
위 두 예시 인터페이스와 타입 지정은 사실 똑같이 작동합니다.
종종 두 개를 바꿔가며 써도 대부분 잘 작동하지만 차이가 조금 있습니다.
가장 큰 차이점 하나는 타입 지정과는 다르게 인터페이스는 객체의 구조를 설명하기 위해서만 사용한다는 것입니다.
또, 클래스에서 객체 유형을 정의할 때 타입 지정 대신 인터페이스를 사용하는 것이 좋습니다.
이는 인터페이스를 이행하고 준수해야 하는 약속처럼 사용할 수 있기 때문입니다.
클래스와 인터페이스
인터페이스는 주로 구체적인 구현이 아닌 서로 다른 클래스 간의 기능을 고유하기 위해 사용됩니다.
즉, 인터페이스 내에 구현이나 값을 입력하는 게 아닌 구조와 클래스가 가져야 할 기능을 입력해야 합니다.
인터페이스에는 구현 세부 사항이 전혀 없는 반면, 추상 클래스는 덮어써야 했던 부분과 구체적 구현 부분을 혼합할 수 있습니다.
interface Greetable {
name: string;
greet(phrase: string): void
}
class Person implements Greetable {
name: string;
age= 30;
constructor(n: string) {
this.name = n;
}
greet(phrase: string) {
console.log(phrase + ' ' + this.name)
}
}
let user1: Greetable;
user1 = new Person('KIM');
읽기 전용 인터페이스 속성
인터페이스에 readonly 제어자를 추가할 수 있습니다. 다만 public, private 등은 지정할 수 없습니다.
interface Greetable {
readonly name: string;
greet(phrase: string): void
}
class Person implements Greetable {
name: string;
age= 30;
constructor(n: string) {
this.name = n;
}
greet(phrase: string) {
console.log(phrase + ' ' + this.name)
}
}
let user1: Greetable;
user1 = new Person('KIM');
user1.name = 'PARK'; // 에러
인터페이스에 readonly 속성을 적용하면 클래스에 따로 더 적지 않아도 자동으로 추론합니다.
따라서 위 예시 같이 name에 새로운 값을 할당하고자 할 때 다음과 같은 에러가 발생합니다.
인터페이스 확장하기
interface Named {
readonly name: string;
}
interface Greetable {
greet(phrase: string): void
}
class Person implements Greetable, Named {
...
}
이렇게 두 개의 인터페이스를 클래스에 적용할 수 도 있고
interface Named {
readonly name: string;
}
// , 여기도 여러개 가능
interface Greetable extends Named {
greet(phrase: string): void
}
class Person implements Greetable {
...
}
하나의 인터페이스로 결합할 수 도 있습니다.
클래스의 상속과 가장 큰 차이점은 클래스는 하나의 클래스로부터만 상속할 수 있고 다수의 클래스로부터는 상속할 수 없지만 인터페이스의 경우 여러 인터페이스로부터 상속받을 수 있습니다.
함수 타입으로서의 인터페이스
함수도 결국 객체이기 때문에 타입 지정 대신 인터페이스를 사용할 수 있습니다.
// type AddFn = (a: number, b: number) => number;
interface AddFn {
(a: number, b:number): number;
}
let add: AddFn;
add = (n1: number, n2:number) => {
return n1 + n2;
}
선택적 매개변수 & 속성
속성 이름 다음에 물음표를 추가하여 선택적 속성을 지정할 수 있습니다.
그러면 타입스크립트는 이 속성이 인터페이스를 구현하는 클래스 내에 있을 수 있지만 반드시 그렇지는 않다고 인식하게 됩니다.
필수 사항을 선택 사항으로 바꾸게 하는 것입니다.
interface Named {
readonly name?: string;
outputName?: string;
}
interface Greetable extends Named {
greet(phrase: string): void
}
class Person implements Greetable {
// 선택적 속성
name?: string;
age= 30;
// 인자가 선택사항이 됨
constructor(n?: string) {
if(n) {
this.name = n;
}
}
greet(phrase: string) {
if(this.name) {
console.log(phrase + ' ' + this.name);
} else {
console.log('No Name!');
}
}
}
let user1: Greetable;
user1 = new Person(); // 인자 없이 오류 X
위의 코드와 같이 속성 마지막에 ?를 적어 선택적 속성을 부여할 수 있습니다.
인터페이스와 클래스에서 name 속성을 선택적으로 만들었고 생성자 함수 매개 변수를 선택적으로 만들어 새 인스턴스를 생성할 때 인자가 없어도 가능하게 하였습니다.
인자 없이 인스턴스 생성을 가능하게 하기 위해선 매개 변수에 기본값을 넣어주거나 선택적 매개변수로 만들어줘야 합니다.
++
인터페이스는 자바스크립트로 컴파일 도중 코드를 검사하는 데만 사용된 다음에 무시됩니다.
즉 컴파일된 자바스크립트 코드를 보면 인터페이스의 흔적을 찾아볼 수 없습니다.
'TYPESCRIPT' 카테고리의 다른 글
제네릭 (6) | 2023.03.27 |
---|---|
고급 타입 (6) | 2023.03.24 |
클래스 2 (6) | 2023.03.21 |
클래스 1 (6) | 2023.03.20 |
타입스크립트 컴파일러 (7) | 2023.03.17 |