enum
enum은 열거형 데이터 타입.
상수(const)의 그룹화 시, 사용하기 아주 좋은 타입.
enum 타입은 코드의 가독성을 높이고, 명확한 상수 값을 정의할 수 있다.
컴파일 시, 자동으로 숫자 값으로 매핑되므로 따로 값을 할당할 필요가 없다.
*하지만 특정 숫자 값으로 매핑되어야만 한다면, 그것은 직접 할당해주면 된다.
예시
<script>
enum UserRole {
ADMIN = "ADMIN",
EDITOR = "EDITOR",
USER = "USER",
}
enum UserLevel {
NOT_OPERATOR, // 0
OPERATOR // 1
}
function checkPermission(userRole: UserRole, userLevel: UserLevel): void {
if (userLevel === UserLevel.NOT_OPERATOR) {
console.log('당신은 일반 사용자 레벨이에요');
} else {
console.log('당신은 운영자 레벨이군요');
}
if (userRole === UserRole.ADMIN) {
console.log("당신은 어드민이군요");
} else if (userRole === UserRole.EDITOR) {
console.log("당신은 에디터에요");
} else {
console.log("당신은 사용자군요");
}
}
const userRole: UserRole = UserRole.EDITOR;
const userLevel: UserLevel = UserLevel.NOT_OPERATOR;
checkPermission(userRole, userLevel);
</script>
관리 권한, 사용자 권한에 대한 코드 작성 시 확실하게 적절해 보인다.
object literal
<script>
const obj = {
a: [1,2,3],
b: 'b',
c: 4
}
</script>
예제 코드로 보면 a, b, c 라는 key 에 각각 [1,2,3,], 'b', 4 의 value가 바인딩 되어있음.
enum에 비해서 object literal이 가지는 장점?
enum의 각 멤버는 상수였기 때문에 number, string 타입의 값만 대입이 가능했다.
하지만 object literal에서는 어떤 타입의 값도 대입을 할 수 있다.
즉, 다양한 데이터 타입의 지원으로 유연한 구조를 지닐 수 있다는 말.
또한, 코드 내에서 사용하기 전에 값이 할당되어야 하므로, 런타임 에러 방지할 수 있다.
enum을 사용하면 좋은 경우
- enum은 간단한 상수 값을 그룹화해서 관리할 때.
- 대신, enum은 상수 값이기 때문에 각 멤버의 값이 변하면 안된다는 조건이 달림.
object literal을 사용하면 좋은 경우
- object literal은 멤버의 값이나 데이터 타입을 맘대로 변경할 수 있다.
- 복잡한 구조와 다양한 데이터 타입을 사용해야 할 때.
Partial<T>Partial<T> 타입은 타입 T의 모든 속성을 선택적으로 만든다.
이를 통해서 기존 타입의 일부 속성만 제공하는 객체를 쉽게 생성할 수 있다.
사용 사례
<script>
interface Person {
name: string;
age: number;
}
const updatePerson = (person: Person, fields: Partial<Person>): Person => {
return { ...person, ...fields };
};
const person: Person = { name: "Spartan", age: 30 };
const changedPerson = updatePerson(person, { age: 31 });
</script>
Required<T>Partial<T> 타입과는 반대로 타입 T의 모든 속성을 필수적으로 만듭니다.<script>
interface Person {
name: string;
age: number;
address?: string; // 속성 명 뒤에 붙는 ?가 뭘까요
}
</script>
type RequiredPerson = Required<Person>;Readonly<T>Readonly<T> 는 타입 T의 모든 속성을 읽기 전용으로 만든다.<script>
interface DatabaseConfig {
host: string;
readonly port: number; // 인터페이스에서도 readonly 타입 사용 가능해요!
}
const mutableConfig: DatabaseConfig = {
host: "localhost",
port: 3306,
};
const immutableConfig: Readonly<DatabaseConfig> = {
host: "localhost",
port: 3306,
};
mutableConfig.host = "somewhere";
immutableConfig.host = "somewhere"; // 오류!
</script>
Pick<T,K>Pick<T,K> 유틸리티 타입은 타입 T에서 K 속성들만 선택하여 새로운 타입을 만듦.<script>
interface Person {
name: string;
age: number;
address: string;
}
type SubsetPerson = Pick<Person, "name" | "age">;
const person: SubsetPerson = { name: "Spartan", age: 30 };
</script>
SubsetPerson은 Person이라는 인터페이스에서 name, age 속성만 선택해서 구성된 새로운 타입.Omit<T,K>Omit<T,K> 유틸리티 타입은 타입 T에서 K 속성들만 제외한 새로운 타입을 만듦.Pick<T,K> 유틸리티 타입과는 반대.<script>
interface Person {
name: string;
age: number;
address: string;
}
type SubsetPerson = Omit<Person, "address">;
const person: SubsetPerson = { name: "Alice", age: 30 };
</script>
SubsetPerson 타입은 Person 타입에서 address 속성만 제외한 새로운 타입.물론 이것으로 정리가 되어 언제든 뚝딱뚝딱 손에서 나오진 않겠지만, 차곡차곡 쌓는다는 개념부터 시작하자는 마인드다.