宮水の日記

宮水の日記

主に書評や資格取得について記事を書いています。

Typescript exercises やってみた 6問目

みなさんこんにちは。宮水です。
今日は、TypeScript エクササイズの6に取り組んでみました。
翻訳はめんどくさくなったので、Google翻訳に突っ込みました。

こちらのリポジトリをforkして、cloneして取り組みます。
rootディレクトリで、yarn installしてから問題文にあるRun this exerciseのコマンドを叩くと、答え合わせができます。すごい!!
github.com

本日の問題

import chalk from 'chalk';

/*

Intro:

    Filtering was completely removed from the project.
    It turned out that this feature was just not needed
    for the end-user and we spent a lot of time just because
    our office manager told us to do so. Next time we should
    instead listen to the product management.
 
 フィルタリングはプロジェクトから完全に削除されました。
    この機能はエンドユーザーには必要ないだけで、オフィスマネージャーから指示されただけで多くの時間が費やされたことがわかりました。次回は代わりに製品管理に耳を傾ける必要があります。

    Anyway we have a new plan. CEO's friend Nick told us
    that if we randomly swap user names from time to time
    in the community, it would be very funny and the project
    would definitely succeed!

    とにかく新しい計画があります。 CEOの友人であるニックは、コミュニティで時々ユーザー名をランダムに入れ替えると非常に面白くなり、プロジェクトは確実に成功すると語っています

Exercise:

    Implement swap which receives 2 persons and returns them in
    the reverse order. The function itself is already
    there, actually. We just need to provide it with proper types.
    Also this function shouldn't necessary be limited to just
    Person types, lets type it so that it works with any two types
    specified.

    2人を受け取り、逆の順序で返すスワップを実装します。関数自体は、実際にはすでに存在しています。適切なタイプを提供する必要があるだけです。
    また、この機能は必ずしも必要ではありません。
    人物のタイプを入力して、指定した2つのタイプで機能するようにタイプします。

Run:

    npm run 6

    - OR -

    yarn -s 6

*/

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

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

function logUser(user: User) {
    const pos = users.indexOf(user) + 1;
    console.log(` - #${pos} User: ${chalk.green(user.name)}, ${user.age}, ${user.occupation}`);
}

function logAdmin(admin: Admin) {
    const pos = admins.indexOf(admin) + 1;
    console.log(` - #${pos} Admin: ${chalk.green(admin.name)}, ${admin.age}, ${admin.role}`);
}

const admins: Admin[] = [
    {
        type: 'admin',
        name: 'Will Bruces',
        age: 30,
        role: 'Overseer'
    },
    {
        type: 'admin',
        name: 'Steve',
        age: 40,
        role: 'Steve'
    }
];

const users: User[] = [
    {
        type: 'user',
        name: 'Moses',
        age: 70,
        occupation: 'Desert guide'
    },
    {
        type: 'user',
        name: 'Superman',
        age: 28,
        occupation: 'Ordinary person'
    }
];

function swap(v1, v2) {
    return [v2, v1];
}

function test1() {
    console.log(chalk.yellow('test1:'));
    const [secondUser, firstAdmin] = swap(admins[0], users[1]);
    logUser(secondUser);
    logAdmin(firstAdmin);
}

function test2() {
    console.log(chalk.yellow('test2:'));
    const [secondAdmin, firstUser] = swap(users[0], admins[1]);
    logAdmin(secondAdmin);
    logUser(firstUser);
}

function test3() {
    console.log(chalk.yellow('test3:'));
    const [secondUser, firstUser] = swap(users[0], users[1]);
    logUser(secondUser);
    logUser(firstUser);
}

function test4() {
    console.log(chalk.yellow('test4:'));
    const [firstAdmin, secondAdmin] = swap(admins[1], admins[0]);
    logAdmin(firstAdmin);
    logAdmin(secondAdmin);
}

function test5() {
    console.log(chalk.yellow('test5:'));
    const [stringValue, numericValue] = swap(123, 'Hello World');
    console.log(` - String: ${stringValue}`);
    console.log(` - Numeric: ${numericValue}`);
}

[test1, test2, test3, test4, test5].forEach((test) => test());

// In case if you are stuck:
// https://www.typescriptlang.org/docs/handbook/basic-types.html#tuple
// https://www.typescriptlang.org/docs/handbook/generics.html

答え

function swap<A, B>(v1: A, v2: B): [B,A] {
    return [v2, v1];
}

感想

今回は、swap関数に型をつけるという問題でした。
v1にもv2にもUserかAdminが入る可能性があるので、困りました...。
f:id:kattyan53:20200729211309p:plain


そんなときは、ジェネリクスですね!!
4歳娘「パパ、具体的な名前をつけないで?」 - Qiita

swap< A, B > は関数の型
v1: A, v2: Bは引数の型
[B,A]は返り値の型です。

function swap<A, B>(v1: A, v2: B): [B,A] {
    return [v2, v1];
}

A, B→B,Aで型を反対にすることも表現できるとは、初めて知りました!


以上です!