원티드 타입스크립트 챌린지를 듣고, 추천 받은 공부 방법 중에 exercise를 통해서 1부터 10까지 풀 수 있어야 된다고 해서, exercises를 풀면서 타입스크립트를 학습해보기로 했다.
사이트 : TypeScript Exercises
문제 8: PowerUser는 User와 Admin의 모든 필드(type 제외)를 가져와야 하고, 코드에서 모든 필드를 중복 없이 type 'powerUser'를 가지도록 정의해야 된다.
interface User {
type: 'user';
name: string;
age: number;
occupation: string;
}
interface Admin {
type: 'admin';
name: string;
age: number;
role: string;
}
type PowerUser = unknown;
export type Person = User | Admin | PowerUser;
export const persons: Person[] = [
{ type: 'user', name: 'Max Mustermann', age: 25, occupation: 'Chimney sweep' },
{ type: 'admin', name: 'Jane Doe', age: 32, role: 'Administrator' },
{ type: 'user', name: 'Kate Müller', age: 23, occupation: 'Astronaut' },
{ type: 'admin', name: 'Bruce Willis', age: 64, role: 'World saver' },
{
type: 'powerUser',
name: 'Nikki Stone',
age: 45,
role: 'Moderator',
occupation: 'Cat groomer'
}
];
function isAdmin(person: Person): person is Admin {
return person.type === 'admin';
}
function isUser(person: Person): person is User {
return person.type === 'user';
}
function isPowerUser(person: Person): person is PowerUser {
return person.type === 'powerUser';
}
export function logPerson(person: Person) {
let additionalInformation: string = '';
if (isAdmin(person)) {
additionalInformation = person.role;
}
if (isUser(person)) {
additionalInformation = person.occupation;
}
if (isPowerUser(person)) {
additionalInformation = `${person.role}, ${person.occupation}`;
}
console.log(`${person.name}, ${person.age}, ${additionalInformation}`);
}
console.log('Admins:');
persons.filter(isAdmin).forEach(logPerson);
console.log();
console.log('Users:');
persons.filter(isUser).forEach(logPerson);
console.log();
console.log('Power users:');
persons.filter(isPowerUser).forEach(logPerson);
User와 Admin의 속성을 다 가져야 되는 PowerUser를 만들기 위해서 extending 하고, type: 'powerUser' 속성을 추가해줘야 함
interface와 type alias의 extending 방법은 다르다.
문제에서는 type alias를 이용해 PowerUser를 선언했기 때문에 type alias를 확장해보았다.
type alias는 &
intersections를 통해서 확장시킬 수 있다.
처음에는 이런식으로 작성을 해줬으나, type PowerUser = never
타입이 나오는 것을 확인하였다.
type PowerUser = User & Admin & {
type: 'powerUser'
}
type 속성이 겹치면서 생기는 문제라고 생각하여 Omit<Type, Keys>
을 이용해서 User와 Admin에 type 속성을 제외하고 type을 생성하도록 하였다.
type PowerUser = Omit<User, 'type'> & Omit<Admin, 'type'> & {
type: 'powerUser'
}
interface는 확장시킬 때 extends
키워드를 사용하여 확장한다. interface NewInterface extends BaseInterface { ... }
interface를 이용해서도 확장해보았다.
interface PowerUser extends Omit<User, 'type'>, Omit<Admin, 'type'> {
type: 'powerUser'
}
이 문제 풀려고... 정말 머리싸맸다...
extends 확장 개념은 알고 있었지만, 언제 사용해야 되는지를 잘 모르니... 이렇게 오래 걸리지...ㅠ_ㅠ