LE

A

PLAY

GaME

@phenomnomnominal 2022

@phenomnomnominal 2022

Sign

here

in

@phenomnomnominal 2022

HELLO!?

@phenomnomnominal 2022

What's going on?

@phenomnomnominal 2022

I'm CrAig

@phenomnomnominal 2022

@phenomnomnominal 2022

&

ex

in

type A

te

nd

s

fer

= B ?

C :

D

@phenomnomnominal 2022

@phenomnomnominal 2022

UnKno

inter

wn

face

ty

class

number

null

|

pe

@phenomnomnominal 2022

string

Date

boolean

Thingie

@phenomnomnominal 2022

const name: string = 'Craig';

Cannot Assign String to Number

const isKidnapped: boolean = true;

const timeRemaining: string = 18;

@phenomnomnominal 2022

const name: string = 'Craig';

CAN ASSIGN ANYTHING TO ANY

const isKidnapped: boolean = true;

const timeRemaining: any = 18;

@phenomnomnominal 2022

any

ANY IS A

TOP TYPE

string

Date

boolean

Thingie

@phenomnomnominal 2022

const isDead: boolean = true;

CAN ASSIGN ANYTHING TO unknown

const isAlive: boolean = false;

const timeRemaining: unknown = 18;

@phenomnomnominal 2022

any

string

Date

boolean

Thingie

Unknown IS Also A

TOP TYPE

unknown

@phenomnomnominal 2022

any

never

unknown

@phenomnomnominal 2022

Can't Assign anything to never

const nada: never = true;

const nope: never = null;

const nothing: never = 'Eighteen';

const nej: never = [];

const nein: never = () => ({});

@phenomnomnominal 2022

any

never

Never IS THE

Bottom TYPE

unknown

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

We got it!

@phenomnomnominal 2022

@phenomnomnominal 2022

asserts

PASS =

input

is

PASS

`${string}

_${string}`

in

string

|

number

|

Null

=

@phenomnomnominal 2022

@phenomnomnominal 2022

never

any

unknown

@phenomnomnominal 2022

const input: unknown = 'HELP';

function shout (input: string): string {

  return `${input}!`;

}

shout(input);

Can't Assign unknown to string

@phenomnomnominal 2022

string

unknown

@phenomnomnominal 2022

if (typeof input === 'string') {
 

}

  shout(input);

Input is definitely a string

const input: unknown = 'HELP';

function shout (input: string): string {

  return `${input}!`;

}

@phenomnomnominal 2022

string

"HELP" | "PLEASE" | "SAVE US"

@phenomnomnominal 2022

function isHelp (input: unknown): input is Help {
 
const HELPS = ['HELP', 'PLEASE', 'SAVE US'];

  return HELPS.includes(input as Help);

}

SPecial Type Guard Syntax

type Help = 'HELP' | 'PLEASE' | 'SAVE US';

@phenomnomnominal 2022

Input is definitely a valid string

if (isHelp(input)) {

  shout(input);

}

const input: unknown = 'HELP';

type Help = 'HELP' | 'PLEASE' | 'SAVE US';

function isHelp (input: unknown): input is Help {
 
const HELPS = ['HELP', 'PLEASE', 'SAVE US'];

  return HELPS.includes(input as Help);

}

@phenomnomnominal 2022

string

`${string}!`

@phenomnomnominal 2022

type Exclamation = `${string}!`;

special assertion guard syntax

function validate (input: unknown):                              {

  if (typeof input !== 'string' || !input.endsWith('!')) {
   
throw new Error();
  }

}

                                    asserts input is Exclamation

@phenomnomnominal 2022

Input is definitely an Exclamation

validate(input);

 

shout(input);

type Exclamation = `${string}!`;

const input: unknown = 'HELP!';

function validate (input: unknown): asserts input is Exclamation {

  if (typeof input !== 'string' || !input.endsWith('!')) {
   
throw new Error();
  }

}

@phenomnomnominal 2022

type Scream = Uppercase<Exclamation>;

type GoodPassword = `${Scream}_${Whisper}`;

type Whisper = Lowercase<Exclamation>;

'A!_a!' | 'AA!_a!' | 'AAA!_aaa!' | 'AAAA!_aaaa! | 'AAAAA!_aaaaa!' | 'AAAAAA!_aaaaaa!' | ...

type Exclamation = `${string}!`;

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

ty

prop

peof

in

key

erty

<>

of

[index: string]

@phenomnomnominal 2022

Array<Item>

Promise<Resolved>

Uppercase<`${string}!`>;

Intrinsic string manipulation type

@phenomnomnominal 2022

type VictimName = string;
type VictimNames = Array<string>

type Help = 'HELP' | 'PLEASE' | 'SAVE US'

type Exclamation = `${string}!`;

@phenomnomnominal 2022

const status = {
  'Ana': 'ungrateful',
  'Rhubarb': 'grateful',
  'Chau': 'ungrateful',
  'Jeff': 'ungrateful',
  'Santosh': 'ungrateful',
  'Sherry': 'ungrateful'
};

type VictimStatus = Record<string, string>;

@phenomnomnominal 2022

type VictimStatus = {
  [key:
VictimName]: string;
}

type MikeStatus = VictimStatus['Mike']; // string

@phenomnomnominal 2022

type MakeGrateful<Victims> = {
    [Name in keyof
Victims]: 'grateful'
}

type Grateful = MakeGrateful<VictimStatus>;

type CraigStatus = Grateful['Craig']; // 'grateful'

type VictimStatus = {
  [key:
VictimName]: string;
}

@phenomnomnominal 2022

typefunction MakeGrateful (input) {


 


 


}

This is imaginary syntax!

    type output = {};
 

        output[name] = 'grateful';

    return output;


    for (name in input) {


    }
 

@phenomnomnominal 2022

type MakeMemorial<Victims> = {
  [Name in keyof
Victims as `❤️ ${Name}`]: Victims[Name]
}

const LAST_WORDS = {

  'Kirk': 'Plz',
  'Spivey': 'My god, what have I done?',
  'Erik': 'Will I get brutally murdered?',
  'Srashti': 'Why not 😁',
  'Katerina': '🐈'
}

define the new property

Lookup the type with the original name

@phenomnomnominal 2022

typefunction MakeMemorial (input) {


 



 

}

Lookup the type with the original name

define the new property

 


 

                            = input[name];

 

 


    for (name in input) {


    }
 

 

    type output = {};
 

        output[`❤️${name}`]

    return output;

@phenomnomnominal 2022

type Memorials = MakeMemorial<typeof LAST_WORDS>;

const LAST_WORDS = {

  'Kirk': 'Plz',
  'Spivey': 'My god, what have I done?',
  'Erik': 'Will I get brutally murdered?',
  'Srashti': 'Why not 😁',
  'Katerina': '🐈'
} as const;

Use typeof to Get a type from a POJO

Use specific string types

@phenomnomnominal 2022

type Memorials = MakeMemorial<typeof LAST_WORDS>;

const LAST_WORDS = {

  'Kirk': 'Plz',
  'Spivey': 'My god, what have I done?',
  'Erik': 'Will I get brutally murdered?',
  'Srashti': 'Why not 😁',
  'Katerina': '🐈'
} as const;

type KirkMemorial = Memorials['❤️ Kirk']; // 'Plz'

look up the type with the mapped key

type KirkMemorial = Memorials['Kirk'];
// Error: Property "Kirk" does not exist

@phenomnomnominal 2022

type MappedType<A> = {
  [B in keyof A
 as C]: D
}

 A: Input Type

 B: Union of KEY names

 C: Mapped Key

 D: Mapped TYpe

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

_!#J?:>

_!#7?:>

_!#3?:>

_!#E?:>

in

A ext

fer

 B ?

C :

D

ends

Para

meters

extends

@phenomnomnominal 2022

type A extends B ? C : D

@phenomnomnominal 2022

type ConditionalType<A> = A extends B ? C : D

B: Super type

 A: Input Type

 C: True type

 D: False type

@phenomnomnominal 2022

type Open<Key> = Key extends Password

  ? true

  : false;

type Password = `${string}!_${string}!`;

type Locked = Open<'ngconf'>; // false

type Unlocked = Open<'HELP!_ME!'>; // true

@phenomnomnominal 2022

typefunction Open (Key) {
  if (Key extends
Password) {

    return true;
  }

  return false;
}

type Password = `${string}!_${string}!`;

@phenomnomnominal 2022

type Encoded = `_!#${string}?:>`;
 

type Detect<Code> = Code extends Encoded

  ? Code

  : never;

@phenomnomnominal 2022

type Encoded = `_!#${string}?:>`;
 

type Decode<Code> =
 
Code extends `_!#${infer Info}?:>`

    ? Info

    : never;

type Decoded = Decode<`_!#J?:>`>; // J

@phenomnomnominal 2022

_!#J?:>

_!#7?:>

_!#3?:>

_!#F?:>

_!#9?:>

_!#)?:>

_!#E?:>

_!#%?:>

@phenomnomnominal 2022

type Letter = 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z';

 

type Decode<Input extends `_!#${Letter}?:>`> =
 
Input extends `_!#${infer Info}?:>`

    ? Info

    : never;

type Bad = Decode<'_!#%?:>`>; // never
 

type Good = Decode<'_!#J?:>`>; // J
 

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

@phenomnomnominal 2022

The TypeScript Type System

Type Narrowing

Top and Bottom Types

Template Literal Types

Mapped Types

Conditional Types

Extracting data with Infer

@phenomnomnominal 2022

THE END!

@phenomnomnominal 2022

THANKS!

@phenomnominal

LETS PLAY A GAME

By Craig Spence