ts는 js의 슈퍼셋으로, 정적 타입을 지원하는 프로그래밍 언어이다. 그리고 이 기능을 직관적으로 도와주는 문법이 바로 타이핑이다. 타이핑의 방법은 type Aliasing과 interface방법이 있다.
type Aliasing과 함께 interface는 코드 작성 시에 타입을 명시하여 개발자가 더 안정적이고 예측 가능한 코드를 작성할 수 있도록 도와준다. 또한 interface는 js에 아예 없는 문법이기에 컴파일 후 결과는 인터페이스에 관한 부분이 사라진다. 인터페이스는 컴파일 타임에만 필요하고, 관계를 규명해서 체크해주는 역할만 하기 때문이다. 이번 포스트에서는 interface에 대해 중점적으로 다룬다.
interface Person {
firstName: string;
lastName: string;
age: number;
printHello(): void;
}
const person: Person = {
firstName: "John",
lastName: "Doe",
age: 30,
printHello() {
console.log(`안녕하세요! ${person.firstName} ${person.lastName} 입니다!`);
}
};
console.log(person.printHello()); // 출력: "John Doe"
위의 예시에서 Person
인터페이스는 firstName
, lastName
, age
, printHello
라는 속성과 함수를 가져야 함을 가져야 함을 정의한다. person
객체는 이 인터페이스를 따르기 때문에 해당 인터페이스의 구조를 준수하면서 사용된다.
타입 체크와 문서화
인터페이스를 사용하여 객체의 예상되는 구조를 명시하므로, 컴파일러가 해당 구조를 검사하고 오류를 감지할 수 있다. 또한 코드 내에서 인터페이스 이름으로 해당 구조에 대한 문서화 역할도 수행할 수 있다.
확장성
인터페이스를 확장하여 새로운 속성이나 메서드를 추가할 수 있다. 이렇게 하면 기존의 인터페이스를 수정하지 않고도 코드를 확장할 수 있다.
객체의 일관성 유지
동일한 인터페이스를 따르는 다양한 객체가 있을 때, 이들이 인터페이스의 정의에 따라 일관성 있는 구조를 유지하게 된다.
위의 기본 기능이외에도 코딩 중에는 여러가지 상황이 발생한다. 이때 도움이 될 수 있는 여러 기능이 추가적으로 있다.
interface의 속성 중에 상황에 따라 꼭 필요하지 않는 경우가 생길 수 있다. 하지만 이럴 때 지정된 타입에 따라 적용시키지 않으면 오류가 발생한다. 이때, 속성의 이름 옆에 ?
를 붙여주면 생략이 가능하다
interface Person {
name: string;
age?: number;
}
객체의 속성에 동적으로 접근하기 위한 방법이다. 이를 통해 객체의 속성을 배열처럼 인덱스로 접근할 수 있다. 주로 객체 내부의 데이터를 동적으로 조회하거나 조작할 때 사용된다. optional type은 프로퍼티의 이름이 명시되어있고 이것이 있는지 없는지만 구분한다면, indexable type은 어떤 프로퍼티도 추가로 typing이 가능하다는 차이점이 있다. 하지만 이를 남용하면 타입의 안정성이 떨어지기 때문에 최소한으로 사용해야한다.
interface Person {
name: string;
[index: string]: string;
}
const person1: Person = { name: 'Minho' };
per son1['grade'] = 'middle school';
interface Person {
name: string;
printHello(): void;
}
interface Person {
name: string;
printHello: () => void;
}
// 두 방법 다 가능하다.
인터페이스는 다른 인터페이스의 확장을 받을 수 있다. 이를 통해 기존의 인터페이스를 확장하여 새로운 속성이나 메서드를 추가할 수 있다.
interface Shape {
color: string;
}
interface Square extends Shape {
sideLength: number;
}
&
키워드를 통해 여러 개의 인터페이스를 결합하여 하나의 타입으로 만들 수 있다. 이를 활용하면 다양한 인터페이스의 속성을 하나의 객체에서 모두 사용할 수 있다.
interface Login {
print(): void;
}
interface SignUp {
log(): void;
}
type Logger = Login & SignUp;
readonly
키워드를 사용하여 속성을 읽기 전용으로 만들 수 있다. 이 속성은 초기화 후에는 변경할 수 없으며 오로지 get만 가능하다.
interface Person {
readonly name: string;
readonly ID: string;
}
const person: Person = {
name: 'Grax',
ID: 'AD123',
};
person.name = 'Draven'; // 불가능
ts에서 함수는 contructor
를 제외하고 첫번째 매개변수를 this
를 넣더라도 자동적으로 해석을 해준다. this
를 넣고 타입을 지정해주면 해당 this
를 인식해준다. 물론 없어도 가능하다.
하지만 arrow function은 일반 function과 달리 this
의 스코프 위치가 다르기 때문에 불가능한 점을 유의해야한다.
const p42: Person4 = {
name: 'Eric',
age: 35,
hello(this: Person4): void {
console.log(`안녕하세요!! ${this.age}살 입니다`);
},
};