TypeScript
의 열거형(Enum)
JavaScript
에서는 기본적으로 열거형을 지원하지 않지만, TypeScript
에서는 문자형 열거형과 숫자형 열거형을 지원한다.
enum Color {
Red,
Green,
Blue,
}
Color
라는 열거형을 정의Red
, Green
, Blue
(Enum)
열거형은 숫자형과 문자열형, 혹은 이 둘의 조합으로 정의될 수 있다.
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
Red
가 1, Green
이 2, Blue
가 4로 정의열거형의 값에 대해 산술 연산을 수행할 수도 있다.
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
let c: Color = Color.Green;
let greenValue: number = Color.Green;
let blueValue: number = Color.Blue;
console.log(c); // 출력: 2
console.log(greenValue); // 출력: 2
console.log(blueValue); // 출력: 4
열거형은 일반적으로 상수값을 대신하여 사용되므로, 타입스크립트에서는 열거형이 많이 사용.
열거형은 코드를 더욱 가독성 높게 만들어주고, 오타와 같은 실수를 방지.
(Enum)
문자형 열거형은 열거형의 값을 전부 다 특정 문자 또는 다른 열거형 값으로 초기화해야 한다.
숫자형 열거형과 개념적으로는 거의 비슷.
enum Direction {
Up = "UP",
Down = "DOWN",
Left = "LEFT",
Right = "RIGHT",
}
let myDirection: Direction = Direction.Up;
console.log(myDirection); // 출력: "UP"
Direction
이라는 문자열 기반의 열거형(Enum)을 정의
Up
, Down
, Left
, Right
각각에는 문자열 값이 할당되어 있다.
myDirection
변수를 Direction.Up
으로 초기화하고 있다.
출력 결과로는 "UP"
auto-incrementing
이 없다.문자열 기반의 열거형은 주로 외부에서 가져온 값을 TypeScript에서 다루기 위해서 사용.
예를 들어, HTTP 요청 방식을 나타내는 열거형을 정의할 수 있다.
enum HttpMethod {
Get = "GET",
Post = "POST",
Put = "PUT",
Delete = "DELETE",
}
function makeRequest(url: string, method: HttpMethod) {
// ...
}
makeRequest("/api/data", HttpMethod.Post);
HTTP 요청 방식을 나타내는 HttpMethod
열거형을 정의.
makeRequest
함수는 URL과 HTTP 요청 방식을 인자로 받는다.
HTTP 요청 방식을 지정할 때는 HttpMethod.Post
와 같이 열거형 값을 사용.
이렇게 열거형을 사용하면 오타와 같은 실수를 방지할 수 있으며, 코드의 가독성과 안정성을 높일 수 있다.
(Reverse mappings)
키(key)
로 값(value)
을 얻을 수 있고 값(value)
으로 키(key)
를 얻을 수도 있다.enum Enum {
A
}
let a = Enum.A;
let nameOfA = Enum[a]; // "A"
TypeScript
의 인터페이스(Interface)
interface
를 사용하여 TypeScript 인터페이스를 생성할 수 있습니다.예약어
(reserved word)
컴퓨터 프로그래밍 언어에서 이미 문법적인 용도로 사용되고 있기 때문에 식별자로 사용할 수 없는 단어를 의미.
예를 들어return
,import
,const
,let
등이 있으며, 이런 단어들은 함수의 이름이나 변수의 이름으로 사용할 수 없다.
TypeScript에서 인터페이스는 객체(Object)의 구조를 정의하기 위해 주로 사용되는 예약어
interface User {
name: string;
age: number;
}
// 정상적으로 선언됩니다.
const user: User = {
name: "anna",
age: 20
}
// 프로퍼티의 순서를 지키지 않아도 정상적으로 선언됩니다.
const user: User = {
age: 20,
name: "anna"
}
// 정의된 프로퍼티보다 적게 작성했기 때문에 에러가 납니다.
const user: User = {
name: "anna"
}
// 정의된 프로퍼티보다 많이 작성했기 때문에 에러가 납니다.
const user: User = {
name: "anna",
age: 20,
job: "developer"
}
사용자 정보를 정의하기 위해 interface
예약어를 사용하여 User
인터페이스를 만들었다.
인터페이스를 만들 때 예약어를 작성하고, 인터페이스의 이름을 대문자로 작성.
이렇게 인터페이스의 이름을 대문자로 시작하는 것은 *네이밍 컨벤션.
네이밍 컨벤션
(Naming Convention)
이름을 짓는 일종의 관례.
TypeScript로 개발할 때 대부분의 개발자는 인터페이스의 이름을 대문자로 시작하도록 작성.
인터페이스는 객체의 타입을 정의하고, 객체가 대문자로 시작하는 것과 유사하기 때문에 일관성 있는 코드 작성을 위해 이러한 관례를 따르는 것.
인터페이스 내에는 name
과 age
가 정의되어 있기 때문에, User
인터페이스를 사용하여 변수를 선언할 때는 반드시 정의된 프로퍼티를 전부 작성해야 한다.
interface
로 정의된 속성만 지정할 수 있으며, 그 외 프로퍼티를 추가로 작성하고자 해도 인터페이스 내에 정의되어 있지 않기 때문에 추가로 프로퍼티를 더 작성하여 선언할 수 없다.
그러나 인터페이스 안의 모든 프로퍼티가 필요한 것은 아니며, 어떤 조건에서만 존재하거나 아예 없을 수도 있기 때문에 ?
연산자를 사용하여 선택적 프로퍼티를 작성할 수도 있다.
interface User {
name: string;
age?: number;
}
// 정상적으로 선언됩니다.
const user: User = {
name: "anna"
}
인터페이스를 사용하여 객체의 프로퍼티 이름과 타입을 정의하고, 함수의 매개변수 타입과 반환 타입도 정의할 수 있다.
interface User {
name: string;
age: number;
job: string;
}
interface Greeting {
(user: User, greeting: string): string;
}
const greet: Greeting = (user, greeting) => {
return `${greeting}, ${user.name}! Your job : ${user.job}.`;
}
const user: User = {
name: "anna",
age: 30,
job: "developer"
};
const message = greet(user, "Hi");
console.log(message);
User
인터페이스 외에도 Greeting
인터페이스를 추가로 작성하여 함수 타입을 정의.
Greeting
인터페이스는 User
타입과 문자열 타입을 매개변수로 받아 문자열 타입을 반환.
greet
함수는 Greeting
을 사용하여 구현되었으며, user
객체와 문자열 "hi"
를 전달인자로 전달받아 문자열을 반환.
Greeting
인터페이스에서 이미 greet
의 매개 변수인 user
와 greeting
의 타입과 반환 타입이 작성되어 있기 때문에, greet
함수는 string
타입을 반환한다고 명시하지 않아도 되며, 매개 변수의 타입 또한 작성하지 않아도 된다.
클래스에서도 인터페이스를 사용할 수 있다.
interface Calculator {
add(x: number, y: number): number;
substract(x: number, y: number): number;
}
class SimpleCalculator implements Calculator {
add(x: number, y:number) {
return x + y;
}
substract(x: number, y: number) {
return x - y;
}
}
const caculator = new SimpleCalculator();
console.log(caculator.add(4, 9)); //13
console.log(caculator.substract(10, 5)); //5
Calculator
인터페이스는 add
와 substract
메서드를 정의.
SimpleCaculator
클래스는 Calculator
인터페이스를 사용하여 작성되었다.
Caculator
인터페이스를 사용하고 있기 때문에 SimpleCaculator
클래스 내에는 Calculator
인터페이스 내에 정의된 두 메서드를 반드시 작성해야 한다.
extends
라는 키워드를 사용해 기존에 존재하던 클래스를 상속해 새로운 클래스를 정의할 수 있다.class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
}
}
//Person 클래스를 extends 키워드를 사용해 상속하여 새로운 클래스인 Student를 정의했습니다.
class Student extends Person {
constructor(name, age, grade) {
super(name, age);
this.grade = grade;
}
study() {
console.log(`${this.name} is studying hard for the grade ${this.grade}.`);
}
}
이같이 인터페이스도 extends
라는 키워드를 사용하여 기존에 존재하던 인터페이스를 상속해 확장이 가능.
이렇게 하면 기존에 존재하던 인터페이스의 프로퍼티를 다른 인터페이스에 복사하는 것을 가능하게 해 주며, 인터페이스의 재사용성을 높여준다.
interface Person {
name: string;
age: number;
}
interface Developer extends Person {
language: string;
}
const person: Developer = {
language: "TypeScript",
age: 20,
name: "Anna",
}
Person
인터페이스를 extends
키워드로 상속해 새로운 인터페이스인 Developer
를 만들고,Developer
인터페이스를 사용하여 person
이라는 객체를 구현.Developer
인터페이스는 Person
인터페이스를 상속하고 있으므로, Person
내부의 프로퍼티를 그대로 받아올 수 있다.마찬가지로 여러 인터페이스를 상속받아 확장할 수도 있다.
interface FoodStuff {
name: string;
}
interface FoodAmount {
amount: number;
}
interface FoodFreshness extends FoodStuff, FoodAmount {
isFreshed: boolean;
}
const food = {} as FoodFreshness;
food.name = "egg";
food.amount = 2;
food.isFreshed = true;
food
변수의 값으로 빈 객체를 할당하는 부분as
라는 키워드를 이용하여 해당 값에 FoodFeshness
라는 타입으로 정의타입 단언(type assertion)
타입 단언
(type assertion)
컴파일러에게 특정 타입 정보의 사용을 강제하게 함으로써, 컴파일러가 가진 정보를 무시하고 프로그래머가 원하는 임의의 타입을 값에 할당할 수 있다.