みなさんこんにちは。宮水です。
今日は、TypeScript エクササイズの7に取り組んでみました。
翻訳はGoogle翻訳にぶち込みました。
こちらのリポジトリをforkして、cloneして取り組みます。
rootディレクトリで、yarn installしてから問題文にあるRun this exerciseのコマンドを叩くと、答え合わせができます。すごい!!
github.com
本日の問題
import chalk from 'chalk'; /* Intro: Project grew and we ended up in a situation with some users starting to have more influence. Therefore, we decided to create a new person type called PowerUser which is supposed to combine everything User and Admin have. プロジェクトが成長し、一部のユーザーがより大きな影響力を持つようになる状況になりました。 そのため、UserとAdminが持つすべてのものを組み合わせることになっているPowerUserという新しい人物タイプを作成することにしました。 Higher difficulty exercise: Define type PowerUser which should have all fields from both User and Admin (except for type), and also have type 'powerUser' without duplicating all the fields in the code. UserとAdminの両方からのすべてのフィールドが必要なタイプPowerUserを定義します(typeを除く)。 また、コード内のすべてのフィールドを複製することなく、タイプ 'powerUser'を持ちます。 Run: npm run 7 - OR - yarn -s 7 */ interface User { type: 'user'; name: string; age: number; occupation: string; } interface Admin { type: 'admin'; name: string; age: number; role: string; } type PowerUser = unknown; type Person = User | Admin | PowerUser; 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'; } 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(`${chalk.green(person.name)}, ${person.age}, ${additionalInformation}`); } console.log(chalk.yellow('Admins:')); persons.filter(isAdmin).forEach(logPerson); console.log(); console.log(chalk.yellow('Users:')); persons.filter(isUser).forEach(logPerson); console.log(); console.log(chalk.yellow('Power users:')); persons.filter(isPowerUser).forEach(logPerson); // In case if you are stuck: // https://www.typescriptlang.org/docs/handbook/utility-types.html
答え
まず問題の意味を読み解くのに時間がかかりました😇
interface powerUserは作らずに、UserもAdminの特性をもつpowerUser型を作りましょうという意味でした。
つまり、UserだけがもつoccupationもAdminだけがもつroleも持ちます。
// ココニカイテアッタヨ { type: 'powerUser', name: 'Nikki Stone', age: 45, role: 'Moderator', occupation: 'Cat groomer' }
今回のヒントはこちらです。
TypeScript: Handbook - Utility Types
TypeScript provides several utility types to facilitate common type transformations. These utilities are available globally.
ユーティリティ型は、一般的な型変換を容易にしてくれるTypeScriptが用意してくれた型のことだそうです。
今回は、Omitだけ馴染みがあったので、Omitを使いました。
Userのtypeを取り除く & Adminのtypeを取り除く & type: powerUserを追加するという意味の型を作りました。
type PowerUser = Omit<User, 'type'> & Omit<Admin, 'type'> & {type: 'powerUser'};
多分いい感じだと思います。
他に回答あったらご教示いただけると嬉しいです!以上です!