loading...
Cover image for Type | Treat Challenge 4
typescript

Type | Treat Challenge 4

gcrev93 profile image Gabrielle Crevecoeur ・3 min read

Type | Treat Challenge 4

Welcome to the fourth Type | Treat challenge! Today we will be stopping hauntings and putting puppies in their place.

Yesterday's Solution

Beginner/Learner Challenge

We were looking for some pretty simple types in this challenge:

type Treat = { 
  location: string
  result: "treat",
  treat: { candy: string, baked?: string } 
}

type Trick = {
  location: string
  result: "trick",
  trick: string
}

type NoShow = {
  location: string
 result: "no-show"
}
Enter fullscreen mode Exit fullscreen mode

We can safely and efficiently reuse the properties in each field by extending them with an interface.

type House = {
  location: string
  result: "treat" | "trick" | "no-show"
}

interface Treat extends House { treat: { candy: string, baked?: string } }
interface Trick extends House  { trick: string }
interface NoShow extends House { trick: string }
Enter fullscreen mode Exit fullscreen mode

We can specialize each result property with the specific value a Trick, Treat, or NoShow will hold by re-declaring it.

interface Treat extends House { result: "treat", treat: { candy: string, baked?: string } }
interface Trick extends House { result: "trick", trick: string }
interface NoShow extends House { result: "no-show" }
Enter fullscreen mode Exit fullscreen mode

Which would give the exact string value for result in each type.

Our answer.

Intermediate/Advanced Challenge

This one either stumped people for ten minutes or was considered a breeze. We had a few different answers in the TypeScript team, but we think this one is the most elegant.

type Result = {
    done: boolean,
    who: string,
    loot: Record<string, any>
}

type TrunkOrTreatResults = Record<typeof trunkOrTreatSpots[number], Result>
Enter fullscreen mode Exit fullscreen mode

This challenge was a great reminder that a Record is simply a type-alias to a conditional type:

type Record<K extends string | number | symbol, T> = { [P in K]: T; }
Enter fullscreen mode Exit fullscreen mode

Which can convert the original answer:

type Result = {
    done: boolean,
    who: string,
    loot: Record<string, any>
}

type ResultMapper<P extends readonly string[]> = {
    [K in P[number]]: Result
};

type TrunkOrTreatResults = ResultMapper<typeof trunkOrTreatSpots>;
Enter fullscreen mode Exit fullscreen mode

into code which is both easier to read, and requires knowing less language concepts. Kudos to the folks who made it seem very easy!

Here's our answer. Bonus: the weirdest answer.

The Challenge

Beginner/Learner Challenge

Don't freak out... Ok freak out a little bit cause WE ARE BEING HAUNTED! And they are after our code! We have tried everything but we cant seem to get it right!

Somehow they keep manipulating the objects set this snippet of code. Take a look and see if you can force the ghosts to stop moving things around.

Intermediate/Advanced Challenge

You've been roped into helping out the halloween puppy parade, it was such a distracting even that you did the minimum possible to spend as much time watching the show.

Now it's over, you figure it's time to clean up your code and try get it type-safe.

Submissions

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:

Happy Typing :)

Discussion

pic
Editor guide
Collapse
dungdung profile image
Houston

Is this an acceptable answer to yesterday's beginner problem?

type House<R extends "treat" | "trick" | "no-show"> = {
  location: string
  result: R
}

type Treat = House<"treat"> & { treat: { candy: string, baked?: string } }
type Trick = House<"trick"> & { trick: string }
type NoShow = House<"no-show">
Enter fullscreen mode Exit fullscreen mode
Collapse
orta profile image
Orta

Yep - it's a solid answer too!

Collapse
dungdung profile image
Houston

Thanks!

Collapse
cbejensen profile image
Christian Jensen

My intermediate/advanced solution: typescriptlang.org/play?ts=4.1.0-b...

Collapse
andrewgreenh profile image
Andreas Roth

Cool to play around with beta features!

Collapse
graciegregory profile image
Gracie Gregory (she/her)

This is awesome πŸ˜†