Type | Treat Challenge 3


Tags: typescript, javascript, codenewbie, challenge
Published: 2020-10-28 20:00:36

Welcome to the third `Type | Treat` challenge! Today we will be going over yesterday's answers and diving into some new problems to solve.

## Yesterday's Solution

### Beginner/Learner Challenge

The `typeof` operator is one of those small tools which helps you avoid duplication, if you already have the type in the runtime - why not re-use it?

```diff
- type Pumpkin = any
+ type Pumpkin = typeof pumpkin

- type PumpkinFromFunction = any
+ type PumpkinFromFunction = ReturnType<typeof Pumpkin>
```

### Intermediate/Advanced Challenge 

This one is a tricky one. Made a bit harder by an accident of not including every ghost in the `Ghosts` type.

The challenge aimed give a subtle nod to day 1's question, where the rest of the challenge becomes easier if you first make a set of types via conditionals or Extract.

```ts
type Gods = Extract<Ghosts, { god: true }>;
type Demons = Extract<Ghosts, { demon: true }>;
type EctoPlasmics = Extract<Ghosts, { ectoplasmic: true }>;
```

This does actually work in the current challenge, even though it's not quite right. From there, you can create [user-defined type guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) to change the code flow in the main algorithm to work as expected.

```ts
function areGods(ghosts: Ghosts[]): ghosts is Gods[] {
  return ghosts.every(ghost => "god" in ghost);
}

function areDemons(ghosts: Ghosts[]): ghosts is Demons[] {
  return ghosts.every(ghost => "demon" in ghost);
}

function areEctoPlasmic(ghosts: Ghosts[]): ghosts is EctoPlasmics[] {
  return ghosts.every(ghost => "ectoplasmic" in ghost);
}
```

That said, let's try work within the constraint of _'maybe the TypeScript team know what they are doing, and this challenge is meant to be this way?!'_ - which is kinda provably `false` from this challenge.

In the TypeScript structural type system, you don't really need to know much more than is required, and you could safely create a singular `type` for `God`, `Demon` and `EctoPlasmics`, then declare an array of those types:

```ts
type God = Ghosts & { god: true };
type Demon = Ghosts & { demon: true, sendBackToHell(): void };
type EctoPlasmic = Ghosts &  { ectoplasmic: true };

function areGods(ghosts: Ghosts[]): ghosts is God[] {
  return ghosts.every(ghost => "god" in ghost);
}

function areEctoPlasmic(ghosts: Ghosts[]): ghosts is EctoPlasmic[] {
  return ghosts.every(ghost => "ectoplasmic" in ghost);
}

function areDemons(ghosts: Ghosts[]): ghosts is Demon[] {
  return ghosts.every(ghost => "demon" in ghost);
}
```

That type-safety is enough for the algorithm, but could bite you later on because `Ghosts & [x]` makes any other property optional. 
If you are going for minimalism, here's a terse answer in 3 one-liners which takes into account usage inside the algorithm:

```ts
const areDemons = (ghosts: Ghosts[]): ghosts is Extract<Ghosts, { demon: true }>[] => ghosts.every(ghost => "demon" in ghost);
const areEctoPlasmic = (ghosts: Ghosts[]): ghosts is Extract<Ghosts, { ectoplasmic: true }>[] => ghosts.every(ghost => "ectoplasmic" in ghost);
const areGods = (ghosts: Ghosts[]): boolean => ghosts.every(ghost => "god" in ghost);
```

[@igorbek managed to get it to two lines!](https://twitter.com/igorbek/status/1321514610717904896)

## The Challenge
### Beginner/Learner Challenge

You've been keeping tally of how the houses on your street respond to trick-or-treaters. Can you reduce duplication from the types needed to describe the results?

[Help out here](https://www.typescriptlang.org/play?#code/PTAEE0HsFcHIDcCmoBGjEDtQGt0AcBLDAc1AENQATAsgJwE9RIAzUemW0AF1oIGNsTTj0RkuAKBChaiAM7QANl1mhmkTu2idZIxFwA03ABaJGxTIlpkFCxs2sLQRLpFCSwXIzOR8xiYuoEcgBc3DJisoY8-NgqZBiUoBiQALSyRpAA7rIAdOLuoADC8WwwoAC2ZLjG3tz0eHKgmUb8RqC+WJRyfLxoTMwFnnLIMvJKsgD8+XyQGDphosqgALygANrioKAA3qAKkL5cBLOhAEQAEjCyyACMp4ajilxnImL3C2Khux2U9GcAMscsAAhOinUAAX0h+k2Oz2BzEQLOl2g11AAGZ3o8lC9wlx3q9nnCfn9QKcALJ0FSg2jgqEQmFbXb7Q5IskotEAFixcieuMWBLxX1QVUQlDOhUgkGwQVk7xJZwASuhrrA5ZDIeIALrTWbzaICFSrDZM+Gsk7sq7IABMPLGRNOBuwgpiZ0pxH4dMZcJZiItFytoAA7Ha+WSnS6BGcAMpaPC8a6UOna3VzLhJSDRjLZFbrWHMhFHf0c5AANlDOLJyTS2eTOoKADkssYxKVoKAjGQkMZkFx6nJDB02xVRT3ygVkunKNA8Ap+H5QLBfUWMLByAlF9iuGuUIxUURSAUKNAMEDVOpN7ylGv4okKBhEJknBguJZrnwV3UGlMgA)

### Intermediate/Advanced Challenge  

You have a list of trunk or treat spots, in your rush you hardcoded the result of your map function to convert it from an array to an object. 
Now the list is longer than three items, it's time to map that hardcoded result into a type. Can you refactor this TODO list function?

[Refactor](https://www.typescriptlang.org/play?#code/PTAEBEEMDsHMBpQGEDyA1AkuAjATlABaQDOoATgKaQA21AnqAA4CuALqJKAEYCW0AJqAD20UKwIVQ0SK2aVhAMzFkeAYwDWwssqqs+sAHQAoEKACaQud2pCNhEsMasAtBUGshoPsVZVB-T05WMmZoTSFtYN0vaB8-YxMwDFFOEOICMU9GSkZIeQUIsQlQCgA3CmhWRDpLezJ+VSF+NyKKRPIKYmZqVlI+D1bQAHIAFRCwlDIx3QAlTu7eobE6RkkAdwI1DJ5SGkpIfjp2y3YhJX4ZSWcvViHSAFsd4n0OUAUKNaYyIVWyPU6AITtJAwUA1ZgdNYqXzDMahdSTaYyOZdHrEJYOUFCLgAKwoqnYrBWknEMnaPkgdD6omIdGgqlAax44kGPhUcGpw2C8MR+1YAGVGEJFgB+IxGRqxQnjBFTPmC4WkAC8oAA2kZQLDigAFPLqIaIDXDAASlmIkgAxNgDaAjUNTcxzaALQAmA12pARaAUbT8gg-d2aoba6iQVSSM6gADqEXSPEY7oAuhxSJKfOKjETVqA4RM5bN5mjQCqAN5GzUAIhGOr1FYAXKAy5rm82At6G1whEJqFRoPByy3Gf6G2z9P3B82bMKG3NGvUADyjuCIGB0AB8A4AvuPmxWHU6rRXQA2mxPQG2KB2uz2YDuJxshCPgmOBy2p6wZ-iIvxF8-lxxoHXLc71APczUtF160bV9WxES9uGvXsQJbB8n3ZBAYM1d9PznH8lwQACgJbTcjBIowFFCAkeBEUB7kgdQKBGFBwBQAAKYghV6BsswoSNuTzJEBU44gAEoG1zWVBJRBZSFPTVKFkMgaWEgxKH4Zhw1Y1jsjKRBVDkShKhE4s12gs8OkU0Q5PM0ADDsnTSmQs9VX0shDNYRMT0wmyLwbBQaHNJybNAbDG23bzzNQ0CKwi5sSPM+K4sQEtNxTHMZV5AtUV6ETSPFUwLAhVRQQcngPkGShstIUoeE4CsZlCI9IE7cpxTTQkmk8FU6IYpiWNY-jJPlYTcrTbsKAMGxYAGzrcvaGMyHUYhM061UqxrRaK0TAwL2LZRmDado-UsahBAW9QVoCNbPSUn1QGOxgtsmrt2FLMjTAAMUgHhqGWjwrrAx1LQAZie3aVX837DqOoUfp9ZwdgyH49BEGgxHjXZ5E4d5PmoPhOm4CgbE+cQdltDMKYp0wozyaB9AbBU4bIZb8rAbADBzTY+l2WjIEYVZ3GJUhsmxHt7kp9oXQ56sfUkMnOHashvsqYRRHESQ6P5loeI4MhYGYe4KlYCXTGBjnCtAYrREoZwgdeXI-kUQZfFUAg6YARwOt5vnuQYuAoWA+G9bRXZoHs4EkbBMlAWAKEJYoKAADzDdgGKpb2hHF0xm3V3WlboBsCFYVhGGIOsQGaUoDA8YAeOIVQVCcWviWcKIZGcUPaAqWPnBdZxgegbAADYgA)

## Share

Be sure to submit your solution by using the **Share** button in the TypeScript playground.

Then go to Twitter, and create a tweet about the challenge, add the link to your code and mention the TypeScript page (@typescript) 

## Need Extra Help?

If you need additional help you can utilize the following:

- [The TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
- [TypeScript Discord Page](https://discord.com/invite/typescript)
- The comments on each Dev.to posts!

Happy Typing :)