.
Into the Unknown
@phenomnominal 2024
Into the Unknown
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505765/frozen-II.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Hi Everyone,
I'm Craig !
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/5383998/craig-spence-1.jpg)
- he/him
- twitter/phenomnominal
- github/phenomnomnominal
Hi Everyone,
I'm Craig !
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395408/Untitled_1.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
I'm going to tell you a story!
I'm going to tell you a story!
Chapter One
Chapter One
A very helpful reindeer
A very helpful reindeer
It was nearing the end of winter in the Kingdom of Arendelle...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175227/Mar-17-2020_02-29-18.gif)
It was nearing the end of winter in the Kingdom of Arendelle...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Sven the reindeer was feeling very productive!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158828/Mar-11-2020_01-00-52.gif)
Sven the reindeer was feeling very productive!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
He had been helping his best friend Kristoff, the Royal Ice Master!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158833/Mar-11-2020_01-04-22.gif)
He had been helping his best friend Kristoff, the Royal Ice Master!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Kristoff and Sven had been friends since they were very little...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7154388/Mar-10-2020_00-28-50.gif)
Kristoff and Sven had been friends since they were very little...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
And it was their job to make sure that Arendelle had enough ice!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7154406/Mar-10-2020_00-39-43.gif)
And it was their job to make sure that Arendelle had enough ice!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Sven was always looking for ways to work smarter...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158871/Mar-11-2020_01-25-29.gif)
Sven was always looking for ways to work smarter...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
And he could always count on help from Olaf the Snowman!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158860/Mar-11-2020_01-19-16.gif)
And he could always count on help from Olaf the Snowman!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Less work means more time for adventures!
Less work means more time for adventures!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7184675/Mar-20-2020_01-32-16.gif)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
sven and Olaf LOVE adventures...
sven and Olaf LOVE adventures...
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7184669/Mar-20-2020_01-24-56.gif)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Chapter Two
Chapter Two
Sven's most magical idea
Sven's most magical idea
Sven and Olaf had two other very special friends in the kingdom
Sven and Olaf had two other very special friends in the kingdom
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7184721/Mar-20-2020_01-38-21.gif)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Princess Anna!
Princess Anna!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505772/Annafrozen2-1.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
And Queen Elsa!
![](https://officialpsds.com/imageview/7y/18/7y18n1_large.png?1521316566)
And Queen Elsa!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7184741/Mar-20-2020_01-51-02.gif)
Anna was the brave, tenacious princess of Arendelle.
Anna was the brave, tenacious princess of Arendelle.
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
and Queen Elsa was her big sister!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7184746/Mar-20-2020_01-54-58.gif)
and Queen Elsa was her big sister!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Queen Elsa had amazing powers!
Queen Elsa had amazing powers!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158941/Mar-11-2020_02-22-15.gif)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
She could sense the water molecules around her,
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158953/Mar-11-2020_02-30-01.gif)
She could sense the water molecules around her,
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Transform the water molecules into ice,
Transform the water molecules into ice,
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158951/Mar-11-2020_02-28-53.gif)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
And control that ice however she liked!
And control that ice however she liked!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158946/Mar-11-2020_02-26-36.gif)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Sven would never forget the Day that Elsa
explained her
magic...
![](https://i.pinimg.com/originals/38/25/df/3825df091e4e60c1bb31e54ff730a252.png)
Sven would never forget the Day that Elsa
explained her
magic...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/6452778/elsa-hero.png)
"I'm going to let you in on my little secret"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/6452778/elsa-hero.png)
"You may have heard that any sufficiently advanced technology is indistinguishable from magic,"
"but actually, it's the other way around..."
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Any sufficiently incredible magic, is actually technology!"
![](https://officialpsds.com/imageview/7y/18/7y18n1_large.png?1521316566)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"And the technology that makes my snow magic work is called..."
"TypeScript"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505776/eefa069ee6f248990e723987995f5e9b.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://media.giphy.com/media/VECTSz9Kc7aCs/giphy.gif)
Sven already Knew TypeScript from his work running the website for the local sauna, and he couldn't wait to learn more!
Sven already Knew TypeScript from his work running the website for the local sauna, and he couldn't wait to learn more!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Sven and Olaf wanted to use Elsa's magic to make Kristoff's life easier!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158982/Mar-11-2020_02-51-57.gif)
Sven and Olaf wanted to use Elsa's magic to make Kristoff's life easier!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
and they had figured out the perfect plan!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7158860/Mar-11-2020_01-19-16.gif)
and they had figured out the perfect plan!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
They were so excited to share it with Anna and Elsa!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7184792/Mar-20-2020_02-34-32.gif)
They were so excited to share it with Anna and Elsa!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
*Snort*
![](https://i.pinimg.com/originals/14/64/55/14645559142954b8aee30422e628345f.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"That's a great idea Sven!"
![](http://images6.fanpop.com/image/photos/35900000/Anna-frozen-35904954-1200-1200.png)
"You can take Elsa's TypeScript ice magic, and create a library that anyone can use!"
"This is going to save so much time!"
Anna was thrilled!
Anna was thrilled!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://officialpsds.com/imageview/7y/18/7y18n1_large.png?1521316566)
"Let's do this!"
"Anna and I will help you learn about TypeScript!"
Elsa couldn't wait to help!
Elsa couldn't wait to help!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Chapter Three
Chapter Three
You can't freeze everything
You can't freeze Everything
Sven and Olaf got straight to work on their new library!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7169817/Mar-14-2020_11-15-43.gif)
Sven and Olaf got straight to work on their new library!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
import { freeze, thaw } from '@queen-elsa/frozen';
const thing = {};
const frozen = freeze(thing);
const thawed = thaw(frozen);
They designed their ideal API...
They designed their ideal API...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
export function freeze (toFreeze: any): any {
return doElsaMagic(toFreeze);
}
// TODO (Sven): Ask Elsa to write later...
function doElsaMagic (toFreeze) {
return toFreeze;
}
They started building the functionality...
They started building the functionality...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"This is going GREAT! We're amazing!"
"Anna and Elsa, what do you think?!"
![](https://i.pinimg.com/originals/93/3a/eb/933aeb62ef8993f151b15acb3e3283c8.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Do you want to make it even better?!"
"This is really good! Great work!"
"Let's talk about Developer Experience..."
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
import { freeze } from '@queen-elsa/frozen';
import { MagicFire } from '@bruni/fire';
const fire = new MagicFire();
const frozenFire = freeze(fire);
"What would happen if a user imported some Magic Fire...
and tried to freeze it?"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"If they were to try to freeze MagicFire, there would be serious consequences, but our library allows it!"
"It's our job as library authors to save our users from these kinds of traps!"
"You and I know that you can't freeze MagicFire, but our users may not know that!"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Right now, we're using the any type:"
"But that's okay! It's not easy to see how best to type this code!"
export function freeze (toFreeze: any): any {
return doElsaMagic(toFreeze);
}
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505776/eefa069ee6f248990e723987995f5e9b.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
export function freeze (toFreeze: any): any {
return doElsaMagic(toFreeze);
}
"We want to be able to freeze almost any input..."
"Right now the code says you can freeze absolutely anything!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505776/eefa069ee6f248990e723987995f5e9b.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://i.pinimg.com/originals/38/25/df/3825df091e4e60c1bb31e54ff730a252.png)
*grunt*
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"That's right Sven, we need to find some way to limit the kind of objects that can be frozen, so that no one can freeze something that is unfreezable!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
export function freeze (toFreeze: any): any {
if (toFreeze.unfreezable) {
throw new FrozenError(`Can't freeze that! ❄️`);
}
return doElsaMagic(toFreeze);
}
"One thing we could do is catch the problem at run-time:"
![](https://vignette.wikia.nocookie.net/disneyfanon/images/d/d6/Elsa_render_making_snow.png/revision/latest?cb=20160229155717)
"But we can do better!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"It would be better for the library user to know about the issue before they run the code..."
"That's where TypeScript can help! Anna, why don't you explain?"
![](https://vignette.wikia.nocookie.net/disneyfanon/images/d/d6/Elsa_render_making_snow.png/revision/latest?cb=20160229155717)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"TypeScript has lots of different types!"
"There's all the primitive types, like boolean and string,"
"There's all the built-in types, like Array and Date,"
"And then there's all the custom user-defined types!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"These types all form the TypeScript Type System!"
"One way to think about it is like a Venn diagram!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
*hrrmpf*
![](https://i.pinimg.com/originals/14/64/55/14645559142954b8aee30422e628345f.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://vignette.wikia.nocookie.net/disney/images/e/ee/Anna_KHIII_Render.png/revision/latest?cb=20181019060228)
"Not a Sven diagram, Sven, a Venn Diagram!"
"Let's check it out!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
boolean
number
Array
string
Date
any
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"The any type is what is called a top type of the type system."
"It is a type for which all values are valid."
"It is a super-type of all other types!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"Using the any type tells TypeScript that any value can be assigned to the variable."
"When TypeScript sees an any, it basically stops type-checking from that point on!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"The any type makes our code very flexible, but it can be dangerous!"
export function freeze (toFreeze: any): any {
// This may break at run-time,
// but not at compile-time
if (toFreeze.unfreezable) {
// throw ...
}
return doElsaMagic(toFreeze);
}
"If the input is undefined, our code will break, but the compiler doesn't complain!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Is that possible?!"
"So we want our library to be flexible, but without the danger?!"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505778/frozen_PNG59.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Yes! TypeScript gives us another tool for this!"
![](https://www.pngkey.com/png/full/387-3879943_disney-frozen-portugal-e-brasil-anna-frozen.png)
"Let's look at the Venn diagram again..."
"We can use the unknown type!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
boolean
number
Array
string
Date
any
unknown
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](http://images6.fanpop.com/image/photos/35000000/Transparent-Anna-frozen-35046873-388-750.png)
"The unknown type is also a top type of the type system. It is also a super-type of all other types! All values are also valid!"
"But it behaves a little bit differently...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"And we get a compile-time error! We can't use the unfreezable property, because the input might not exist!"
export function freeze (toFreeze: unknown): unknown {
// This may break at run-time,
// so now we get an error at compile-time!
if (toFreeze.unfreezable) {
// throw ...
}
return doElsaMagic(toFreeze);
}
"We can replace the any with unknown..."
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"So, we need to fix our compile-time error! We need a way for the compiler to decipher the unknown value."
![](https://www.pngkey.com/png/full/387-3879943_disney-frozen-portugal-e-brasil-anna-frozen.png)
"One way to do this is to use a type guard!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"A type guard is a special kind of function that gives TypeScript hints about how to narrow a type."
"It tells TypeScript how to go from a broad type - like any or unknown - to a specific type!"
![](https://www.pngkey.com/png/full/387-3879943_disney-frozen-portugal-e-brasil-anna-frozen.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
function isUnfreezable (thing: unknown): thing is Unfreezable {
return thing && (thing as Unfreezable).unfreezeable;
}
type Unfreezable = {
unfreezable: true
}
export function freeze (toFreeze: unknown): unknown {
if (!isUnfreezable(toFreeze)) {
// toFreeze is freezable!
}
// throw ...
}
"A type guard is a run-time check that maps to a type:"
Special is keyword
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
function isUnfreezable (thing: unknown): thing is Unfreezable {
return thing && (thing as Unfreezable).unfreezeable;
}
type Unfreezable = {
unfreezable: true
}
export function freeze (toFreeze: unknown): unknown {
if (!isUnfreezable(toFreeze)) {
// toFreeze is freezable!
}
// throw ...
}
"Right now, the implementation is a little weird..."
Weird double negative...
Confusing control flow...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"It would be better if we could talk about something being freezable!"
![](https://vignette.wikia.nocookie.net/disney/images/e/ee/Anna_KHIII_Render.png/revision/latest?cb=20181019060228)
"TypeScript has another handy type to help. Let's go back to our Venn diagram..."
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
boolean
number
Array
string
Date
unknown
![](https://vignette.wikia.nocookie.net/disney/images/e/ee/Anna_KHIII_Render.png/revision/latest?cb=20181019060228)
any
never
"The never type is the bottom type of the
type system. It
is a type which
has no valid
values!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Freezable = {
unfreezable: never
}
![](https://vignette.wikia.nocookie.net/disney/images/e/ee/Anna_KHIII_Render.png/revision/latest?cb=20181019060228)
"We can use the never type to describe what a freezable object is:"
"An object with a value for to the unfreezable property is never assignable to Freezable!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://vignette.wikia.nocookie.net/disney/images/e/ee/Anna_KHIII_Render.png/revision/latest?cb=20181019060228)
"This means we can invert our type guard:"
// Before:
function isUnfreezable (thing: unknown): thing is Unfreezable {
return thing && (thing as Freezable).unfreezeable;
}
// After:
function isFreezable (thing: unknown): thing is Freezable {
return thing && !(thing as Freezable).unfreezeable;
}
export function freeze (toFreeze: unknown): unknown {
if (isFreezable(toFreeze)) {
// toFreeze is freezable!
}
// throw ...
}
No more double negative!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://vignette.wikia.nocookie.net/disney/images/e/ee/Anna_KHIII_Render.png/revision/latest?cb=20181019060228)
"Another way to use never is for the return type of a function that never returns:"
function throwError (error: string): never {
throw new FrozenError(error);
}
export function freeze (toFreeze: unknown): unknown {
if (isFreezable(toFreeze)) {
// toFreeze is freezable!
}
throwError(`Can't freeze that! ❄️`);
}
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Assertion guards combine the ideas from type guards and never:"
function assertFreezable (thing: unknown): asserts thing is Freezable {
if (!thing || (thing as Freezable).unfreezable) {
throw new FrozenError(`Can't freeze that! ❄️`);
}
}
export function freeze (toFreeze: unknown): unknown {
assertFreezable(toFreeze);
// toFreeze is freezable!
return doElsaMagic(toFreeze);
}
Special asserts keyword
More sensible flow!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"That's great! But we can still go further!"
export function freeze (toFreeze: unknown): unknown {
assertFreezable(toFreeze);
return doElsaMagic(toFreeze);
}
freeze({ unfreezable: true }); // run-time error!
"Our input is still typed as unknown..."
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505783/Frozen2-elsa-hojas-742x1024.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"We can restrict our input to the Freezable type:"
export function freeze (toFreeze: Freezable): unknown {
assertFreezable(toFreeze);
return doElsaMagic(toFreeze);
}
freeze({ unfreezable: true }); // compile-time error!
"Now we have run-time and compile-time safety checks!"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505783/Frozen2-elsa-hojas-742x1024.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Chapter Four
Chapter Four
To be frozen
To be frozen
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175148/Mar-17-2020_01-40-26.gif)
Sven and Olaf were delighted!
Sven and Olaf were delighted!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Next, we need to talk about what is involved with freezing something!"
"I use a very obscure dialect of TypeScript, that looks something like this..."
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505776/eefa069ee6f248990e723987995f5e9b.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]+((+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[+!+[]+[+!+[]]]+(![]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+([]+[])[(![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(!![]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]()[+!+[]+[!+[]+!+[]]]
"You'll need to trust me that it works!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
function doElsaMagic (toFreeze: Freezable): unknown {
const result = ([]+[])[(![]+[])[+[]...
(toFreeze as any).frozen = result;
return toFreeze as unknown;
}
"We can simplify it down to understand what's going on:"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505776/eefa069ee6f248990e723987995f5e9b.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
function doElsaMagic(toFreeze: Freezable): unknown {
const result = ([]+[])[(![]+[])[+[]...
(toFreeze as any).frozen = result;
return toFreeze as unknown;
}
"But now we have some messy types to fix!"
Oh no!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"We already have a Freezable type, but we need to replace the unknowns and any..."
function doElsaMagic(toFreeze: Freezable): unknown {
const result = ([]+[])[(![]+[])[+[]...
(toFreeze as any).frozen = result;
return toFreeze as unknown;
}
"We need a Frozen type!"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type BasicFrozen = {
frozen: true;
}
"But it doesn't really express what we mean..."
"The most basic version could look like this:"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"We want to combine the type of the Freezable thing, with the BasicFrozen type..."
Freezable
BasicFrozen
Freezable and BasicFrozen
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"We can use TypeScript to express this, by using generic types and intersection types..."
type Frozen<T> = T & {
frozen: true;
}
T is a convention, but it could be named anything!
& is the syntax for an intersection type
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Frozen<BaseType> = BaseType;
function Frozen (baseType) {
return baseType;
}
type Frozen<BaseType> = BaseType & {
frozen: true;
}
function Frozen (baseType) {
return {
...baseType,
frozen: true
};
}
"It can be useful to think about complex types in equivalent JavaScript syntax:"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505777/032a28d5014ff1a92e736965b2bf430d.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Frozen<T> = T & {
frozen: true;
}
function freeze<T>(toFreeze: T): Frozen<T> {
assertFreezable(toFreeze);
(toFreeze as Frozen<T>).frozen = ([]+[])[(![]+[])[+[] ...;
return toFreeze as Frozen<T>;
}
"And now we can almost correctly express our function:"
"Do you see what is missing?"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175201/589ee36764b351149f22a86e.png)
"It doesn't say that the type of the input has to be Freezable?"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Exactly! For that we need to express one more type relationship:"
Freezable
Super-type of Freezable
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"For that we can use the extends keyword:"
type Frozen<T extends Freezable> = T & {
frozen: true;
}
function Frozen (baseType: Freezable) {
return {
...baseType,
frozen: true
};
}
Uses the extends keyword just like with classes!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"We can even set a default type for the type parameter:"
type Frozen<T extends Freezable = Freezable> = T & {
frozen: true;
}
function Frozen (baseType: Freezable = {}) {
return {
...baseType,
frozen: true
};
}
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"That gives us everything we need for the freeze function!"
![](https://www.pngkey.com/png/full/387-3879943_disney-frozen-portugal-e-brasil-anna-frozen.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Freezable = {
unfreezable: never
}
type Frozen<T extends Freezable> = T & {
frozen: true;
}
function assertFreezable (thing: unknown): asserts thing is Freezable {
if (!thing || (thing as Freezable).unfreezable) {
throw new FrozenError(`Can't freeze that! ❄️`);
}
}
function freeze <T extends Freezable> (toFreeze: T): Frozen<T> {
assertFreezable(toFreeze);
(toFreeze as Frozen<T>).frozen = ([]+[])[(![]+[])[+[] ...;
return toFreeze as Frozen<T>;
}
Freezable type! An object with a unfreezable property is never assignable to Freezable
Frozen type! A Frozen object is the intersection of a Freezable object and an object with the frozen property set to true
Assert Freezable function! An Assertion Guard that takes an unknown input and throws an error if the object is not Freezable
Freeze function! A function that takes a Freezable input, asserts that it is Freezable, freezes the object, and returns a Frozen type
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://i.pinimg.com/originals/b2/9a/8c/b29a8c0bfbfce40b8988c12d5428c39c.png)
"The library is finished!?"
"Come on Sven, let's go show Kristoff right away!"
Olaf was very excited!
Olaf was very excited!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
And before Anna and Elsa could even try to stop them, Sven and Olaf were out the door and on their way...
And before Anna and Elsa could even try to stop them, Sven and Olaf were out the door and on their way...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Chapter Five
Chapter Five
2 fast 2 frozen
2 fast 2 frozen
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7169817/Mar-14-2020_11-15-43.gif)
Olaf and Sven rushed to show Kristoff their library!
Olaf and Sven rushed to show Kristoff their library!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
*snort*
"Hi Kristoff! We made you a library to help make your job easier!"
![](https://i.pinimg.com/originals/34/14/aa/3414aa5c5474cdf9db9ad4f815559595.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
import { freeze } from '@queen-elsa/frozen';
const thing = {};
const frozenThing = freeze(thing);
const unfreezableThing = { unfreezable: true };
freeze(unfreezableThing); // compile-time error!
"You can use it to freeze anything you like, just like Elsa!"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9505786/frozen_PNG59.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/a85ea6ea-16aa-4285-b9cb-e3b3cf66d6ef/d9bau3k-da895ccb-dc64-444b-84c2-f98d37945302.png?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcL2E4NWVhNmVhLTE2YWEtNDI4NS1iOWNiLWUzYjNjZjY2ZDZlZlwvZDliYXUzay1kYTg5NWNjYi1kYzY0LTQ0NGItODRjMi1mOThkMzc5NDUzMDIucG5nIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.o5nx2PqsuUi3lexUcPDxi7HduvC5CAj25v2ZVaboyqU)
"You made this for me!?"
Kristoff was blown away!
Kristoff was blown away!
"Let's try it out on me right now!"
![](https://i.pinimg.com/originals/65/77/11/657711832e28d7d79e3fc90947eb48eb.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175314/Mar-17-2020_03-37-57.gif)
Kristoff is quite the rockstar developer, so he wrote a little script very quickly...
Kristoff is quite the rockstar developer, so he wrote a little script very quickly...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175315/Mar-17-2020_03-41-07.gif)
But just as he ran the script, Anna and Elsa burst in!
But just as he ran the script, Anna and Elsa burst in!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Wait! Stop!"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175317/_familyrenders.com_ElsayAnna_Frozen2.png)
"We still need to write the thaw function!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7175319/Mar-17-2020_03-51-12.gif)
But it was too late...
The library worked...
But it was too late...
The library worked...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Olaf was frozen.
Olaf was frozen.
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
Chapter Six
Chapter Six
Do you want to thaw a snowman?
Do you want to thaw a snowman?
"Oh no, what have I done!? I've frozen Olaf!"
Kristoff was devastated
Kristoff was devastated
![](http://www.pngmart.com/files/6/Kristoff-PNG-Photos.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://pluspng.com/img-png/frozen-png-elsa-elsa-frozen-disney-05-1200.png)
"We need to move fast!"
"Or Olaf could be frozen forever..."
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9615414/codestantine-6-logo.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
function thaw (toThaw) {
assertFrozen(toThaw);
delete toThaw.frozen;
return toThaw;
}
function assertFrozen(thing) {
if (!thing || !thing.frozen) {
throw new FrozenError(`Can't thaw that! ❄️`);
}
}
"Quickly, let's start with the JavaScript:"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9615414/codestantine-6-logo.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Can't we just add any everywhere and fix it!?"
"It's too risky, we don't want something going wrong!"
![](https://cdn131.picsart.com/314734176201211.png?type=webp&to=min&r=640)
![](http://images6.fanpop.com/image/photos/38500000/Kristoff-frozen-38561155-556-835.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
@phenomnominal 2020
"Sven, why don't you add types to the assertion guard first!"
![](https://pngimg.com/uploads/frozen/frozen_PNG45.png)
*gulp*
![](https://cdn131.picsart.com/314734176201211.png?type=webp&to=min&r=640)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
@phenomnominal 2020
function assertFrozen(thing: unknown): asserts thing is Frozen {
if (!thing || !(thing as Frozen).frozen) {
throw new FrozenError(`Can't thaw that! ❄️`);
}
}
Add the unknown type to the input
![](https://pngimg.com/uploads/frozen/frozen_PNG45.png)
Cast the input to Frozen to do the check
Add the asserts statement for the return type
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"That's perfect!"
*clip clop!*
![](https://vignette.wikia.nocookie.net/p__/images/a/ac/Annafrozen2.png/revision/latest?cb=20191121010106&path-prefix=protagonist)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395384/1706760576_SvenKristoff10-1.webp)
"Now we need to add types to the thaw function!"
"Kristoff, I need your help!"
![](https://vignette.wikia.nocookie.net/p__/images/a/ac/Annafrozen2.png/revision/latest?cb=20191121010106&path-prefix=protagonist)
![](http://images6.fanpop.com/image/photos/38500000/Kristoff-frozen-38561155-556-835.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9615414/codestantine-6-logo.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
function thaw<T extends Frozen>(toThaw: T) {
assertFrozen(toThaw);
delete toThaw.frozen;
return toThaw;
}
"We can start by adding a generic type for the input that has to extend Frozen?"
"But I have no idea how to do the return type! Help!"
![](http://images6.fanpop.com/image/photos/38500000/Kristoff-frozen-38561155-556-835.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"We need to use TypeScript to extract the type of the original object from the Frozen type!"
![](https://cdn131.picsart.com/313612563197211.png?type=webp&to=min&r=640)
"This is the perfect time to use..."
"Conditional Types!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
T extends X ? Y : Z;
![](https://cdn131.picsart.com/314734176201211.png?type=webp&to=min&r=640)
Condition
Pass
Fail
"Conditional types let us change type based on the state of other types!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://cdn131.picsart.com/314734176201211.png?type=webp&to=min&r=640)
type Foo<T> = T extends X ? Y : Z;
function fooType (T) {
if (T === X) {
return Y;
} else {
return Z;
}
}
"A Conditional types is like a type function with an if statement!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://cdn131.picsart.com/313612563197211.png?type=webp&to=min&r=640)
"Conditional Types have an extra special power..."
"Type inference!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Type inference gives us a mechanism to extract types from other types!"
"Imagine that we want to extract the type of the return value of a function..."
![](https://cdn131.picsart.com/313612563197211.png?type=webp&to=min&r=640)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type ReturnType<T> =
T extends (...args: Array<any>) => infer R
? R
: never;
function one () {
return 1;
}
type A = ReturnType<typeof one>; // number
![](https://cdn131.picsart.com/313612563197211.png?type=webp&to=min&r=640)
The infer tells TypeScript to work it out for us!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Parameters<T> =
T extends (...args: infer P) => any
? P
: never
function add (a: number, b: number) {
return a + b;
}
type P = Parameters<typeof add>; // [number, number]
![](https://cdn131.picsart.com/313612563197211.png?type=webp&to=min&r=640)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Thawed<T> =
T extends Frozen<infer R>
? R
: never;
type Water = {};
type Ice = Frozen<Water>;
type W = Thawed<Ice>; // Water
![](https://cdn131.picsart.com/313612563197211.png?type=webp&to=min&r=640)
"We can use type inference to extract the type of the generic Frozen object:"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
type Thawed<T> = T extends Frozen<infer R>
? R
: never;
function thaw<T extends Frozen>(toThaw: T): Thawed<T> {
assertFrozen(toThaw);
delete toThaw.frozen;
return toThaw as Thawed<T>;
}
![](https://vignette.wikia.nocookie.net/frozen/images/1/1b/Kristoff_1.png/revision/latest/top-crop/width/360/height/450?cb=20180309165350&path-prefix=es)
"Okay, I got this! I'll update the thaw function!"
Add the Thawed conditional type
Use Thawed as the return type
And cast the result!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"That looks perfect to me!"
"Let's save Olaf, before it's too late!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395378/Elsa%2Band%2BAnna%2B2.png)
Chapter Seven
Chapter Seven
That was weird
That was weird
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7178393/Mar-18-2020_04-24-55.gif)
Kristoff, Sven, Anna & Elsa all worked together to quickly write a new script...
Kristoff, Sven, Anna & Elsa all worked together to quickly write a new script...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7178442/Mar-18-2020_04-42-30.gif)
Thanks to the library's excellent types, they were confident that the code was good...
Thanks to the library's excellent types, they were confident that the code was good...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
So they ran the script...
So they ran the script...
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/7178448/Mar-18-2020_04-37-45.gif)
And just like that, Olaf was back to his normal self!
And just like that, Olaf was back to his normal self!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
"Hi everyone, my name's Olaf!"
"What happened?"
"That was weird!"
![](https://i.pinimg.com/originals/c0/30/d9/c030d9e6515d803e0bc3997098cfa9b4.png)
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://pluspng.com/img-png/elsa-and-anna-png-anna-and-elsa-frozen-transparent-png-image-2500.png)
"Kristoff, I think you'd better reccap!"
"Oh Olaf! We're so glad you're okay! So much has happened!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://i.pinimg.com/originals/45/b9/8a/45b98afdc30cabf60e33a0afa05af065.png)
Prefer unknown over any when you don't know what type something is!
*
*
*The never type can be used to describe types that cannot happen!*
We can use Type Guards and Assertion Guards to narrow types based on run-time behaviour
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://i.pinimg.com/originals/45/b9/8a/45b98afdc30cabf60e33a0afa05af065.png)
We can use Generics to help describe unknown types. Sub-types, union type and intersection types are also really useful!
*Conditional types and type inference can also be really powerful*
It's worth putting in the effort with your types so that people who consume your code have a good experience!
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/9615656/9146cbd6dfc6709aba82777cf137a941.png)
"Neat!"
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
The End
The End
The End
Thanks everyone!
Thanks everyone!
Slides
Code
@phenomnominal 2024
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395306/download.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395421/Untitled_1.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395423/Untitled_1_copy.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/319854/images/11395625/anna_elsa_kristoff_olaf_and_sven_png_by_jakeysamra_dfr3tv9-pre.png)
Into the Unknown! - CityJS Athens
By Craig Spence
Into the Unknown! - CityJS Athens
Craig Spence - CityJS Athens - Into The Unknown
- 376