[typescript] exercises 1 ~ 5

KoEunseo·2023년 2월 10일
0

typescript

목록 보기
11/23

타입스크립트 연습하기

https://typescript-exercises.github.io/#exercise=1&file=%2Findex.ts

exercises 1

1단계 exercise이다.
users라는 배열이 있고 이에 맞는 User라는 인터페이스 타입을 만들어 지정해주었다.

export interface User {
    name: string;
    age: number;
    occupation: string;
};

export const users: User[] = [
    {
        name: 'Max Mustermann',
        age: 25,
        occupation: 'Chimney sweep'
    },
    {
        name: 'Kate Müller',
        age: 23,
        occupation: 'Astronaut'
    }
];

export function logPerson(user: User) {
    console.log(` - ${user.name}, ${user.age}`);
}

console.log('Users:');
users.forEach(logPerson);

exercises 2

처음에 지정해주었던 User 외에도 배열의 타입을 타입을 확장해야 할 필요가 생겼다. 직업이 아니라 역할을 데이터로 갖는 person 객체가 생겼기 때문. 이때 User 인터페이스를 수정할 수도 있겠지만 다른 형태에 대한 인터페이스를 만들고 aliase를 통해 타입을 확장하면서도 엄격하게 지킬 수 있도록 할 수 있다.

interface User {
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    name: string;
    age: number;
    role: string;
}

export type Person = User | Admin;

export const persons: Person[] /* <- Person[] */ = [
    {
        name: 'Max Mustermann',
        age: 25,
        occupation: 'Chimney sweep'
    },
    {
        name: 'Jane Doe',
        age: 32,
        role: 'Administrator'
    },
    {
        name: 'Kate Müller',
        age: 23,
        occupation: 'Astronaut'
    },
    {
        name: 'Bruce Willis',
        age: 64,
        role: 'World saver'
    }
];

export function logPerson(user: Person) {
    console.log(` - ${user.name}, ${user.age}`);
}

persons.forEach(logPerson);

기존에 자바스크립트를 통해 작업했던 것을 타입스크립트로 바꾸는 작업을 통해 타입스크립트를 처음 사용했었다. 뭔가 잘못된 느낌이 들면서도 그냥 ? 이거 하나 붙여서 타입을 계속 바꿨었는데 이런 방식이 있구나 벌써 깨달음을 얻었다!

exercises 3

  • in operator로 타입 좁히기
    "value" in x
    "role" in person 이 부분이다.
interface User {
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    name: string;
    age: number;
    role: string;
}

export type Person = User | Admin;

export const persons: Person[] = [
    {
        name: 'Max Mustermann',
        age: 25,
        occupation: 'Chimney sweep'
    },
    {
        name: 'Jane Doe',
        age: 32,
        role: 'Administrator'
    },
    {
        name: 'Kate Müller',
        age: 23,
        occupation: 'Astronaut'
    },
    {
        name: 'Bruce Willis',
        age: 64,
        role: 'World saver'
    }
];

export function logPerson(person: Person) {
    let additionalInformation: string;
    if ("role" in person) {
        additionalInformation = person.role;
    } else {
        additionalInformation = person.occupation;
    }
    console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}

persons.forEach(logPerson);

exercises 4

parameterName is Type
isAdmin, isUser함수가 리턴하는 값에 타입을 지정해준다.
리턴값에 타입이 지정되지 않으면 logPerson 함수 내에서 isAdmin(person)이 true라도 additionalInformation에 person.role을 할당하지 못한다. role이 없다고 하더라.

interface User {
    type: 'user';
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type: 'admin';
    name: string;
    age: number;
    role: string;
}

export type Person = User | Admin;

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' }
];

export function isAdmin(person: Person): person is Admin {
    return person.type === 'admin';
}

export function isUser(person: Person): person is User {
    return person.type === 'user';
}

export function logPerson(person: Person) {
    let additionalInformation: string = '';
    if (isAdmin(person)) {
        additionalInformation = person.role;
    }
    if (isUser(person)) {
        additionalInformation = 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);

exercises 5

내 답은 Partial<User> 인데, 레퍼런스를 보니 여기에 더해 Omit을 사용했다. Partial<Omit<User, 'type'>>

Partial<Type>

타입의 속성들을 옵션화한다. 찾아보니 부분집합을 만족하는 타입을 정의한다고 함. 아래와 같이 간주되는 듯 하다.

interface User {
    type?: 'user';
    name?: string;
    age?: number;
    occupation?: string;
}

Omit<Type, Keys>

인터페이스의 특정 키가 생략된다.

person: Omit<User, 'type'>
interface User {
  name: string;
  age: number;
  occupation: string;
}
interface User {
    type: 'user';
    name: string;
    age: number;
    occupation: string;
}

interface Admin {
    type: 'admin';
    name: string;
    age: number;
    role: string;
}

export type Person = User | Admin;

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: 'user',
        name: 'Wilson',
        age: 23,
        occupation: 'Ball'
    },
    {
        type: 'admin',
        name: 'Agent Smith',
        age: 23,
        role: 'Administrator'
    }
];

export const isAdmin = (person: Person): person is Admin => person.type === 'admin';
export const isUser = (person: Person): person is User => person.type === 'user';

export function logPerson(person: Person) {
    let additionalInformation = '';
    if (isAdmin(person)) {
        additionalInformation = person.role;
    }
    if (isUser(person)) {
        additionalInformation = person.occupation;
    }
    console.log(` - ${person.name}, ${person.age}, ${additionalInformation}`);
}
// // ------------ my answer --------------------------
export function filterUsers(persons: Person[], criteria: Partial<User>): User[] {
    return persons.filter(isUser).filter((user) => {
        const criteriaKeys = Object.keys(criteria) as (keyof User)[];
        return criteriaKeys.every((fieldName) => {
            return user[fieldName] === criteria[fieldName];
        });
    });
}
// ------------ reference --------------------------
export function filterUsers(persons: Person[], criteria: Partial<Omit<User, 'type'>>): User[] {
    return persons.filter(isUser).filter((user) => {
        const criteriaKeys = Object.keys(criteria) as (keyof Omit<User, 'type'>)[];
        return criteriaKeys.every((fieldName) => {
            return user[fieldName] === criteria[fieldName];
        });
    });
}
// ------------ reference --------------------------
console.log('Users of age 23:');

filterUsers(
    persons,
    {
        age: 23
    }
).forEach(logPerson);

(+) 2가지를 omit 하거나 pick하고 싶을 때 | 연산자를 사용하면 된다.

export interface RouterItem {
  path: string;
  element: React.ReactNode;
  withAuth: boolean;
  label: string;
}
type SidebarItem = Omit<RouterItem, "withAuth" | "element">;
profile
주니어 플러터 개발자의 고군분투기

0개의 댓글