Sie sind auf Seite 1von 373

TableofContents

Introduction

Introduction
 

1.1

1.1

GettingStarted

GettingStarted
 

1.2

1.2
WhyTypeScript   1.2.1

WhyTypeScript

 

1.2.1

1.2.1

JavaScript

JavaScript
 

1.3

1.3
Equality   1.3.1

Equality

 

1.3.1

1.3.1
References   1.3.2

References

 

1.3.2

1.3.2
Nullvs.Undefined   1.3.3

Nullvs.Undefined

 

1.3.3

1.3.3
this   1.3.4

this

 

1.3.4

1.3.4
Closure   1.3.5

Closure

 

1.3.5

1.3.5
Number   1.3.6

Number

 

1.3.6

1.3.6
Truthy   1.3.7

Truthy

 

1.3.7

1.3.7

FutureJavaScriptNow

FutureJavaScriptNow
 

1.4

1.4
Classes   1.4.1

Classes

 

1.4.1

1.4.1
 
  ClassesEmit   1.4.1.1

ClassesEmit

 

1.4.1.1

1.4.1.1
ArrowFunctions   1.4.2

ArrowFunctions

 

1.4.2

1.4.2
RestParameters   1.4.3

RestParameters

 

1.4.3

1.4.3
let 1.4.4

let

1.4.4

1.4.4
const   1.4.5

const

 

1.4.5

1.4.5
Destructuring   1.4.6

Destructuring

 

1.4.6

1.4.6
SpreadOperator   1.4.7

SpreadOperator

 

1.4.7

1.4.7
for of   1.4.8

for of

 

1.4.8

1.4.8
Iterators   1.4.9

Iterators

 

1.4.9

1.4.9
TemplateStrings   1.4.10

TemplateStrings

 

1.4.10

1.4.10
Promise   1.4.11

Promise

 

1.4.11

1.4.11
Generators   1.4.12

Generators

 

1.4.12

1.4.12
AsyncAwait   1.4.13

AsyncAwait

 

1.4.13

1.4.13

Project

Project
 

1.5

1.5
CompilationContext   1.5.1

CompilationContext

 

1.5.1

1.5.1
 
  tsconfig.json   1.5.1.1

tsconfig.json

 

1.5.1.1

1.5.1.1
WhichFiles?   1.5.1.2

WhichFiles?

 

1.5.1.2

1.5.1.2
DeclarationSpaces   1.5.2

DeclarationSpaces

 

1.5.2

1.5.2
Modules   1.5.3

Modules

 

1.5.3

1.5.3
FileModuleDetails   1.5.3.1

FileModuleDetails

 

1.5.3.1

1.5.3.1
globals.d.ts   1.5.3.2

globals.d.ts

 

1.5.3.2

1.5.3.2
Namespaces   1.5.4

Namespaces

 

1.5.4

1.5.4
DynamicImportExpressions   1.5.5

DynamicImportExpressions

 

1.5.5

1.5.5

Node.jsQuickStart

Node.jsQuickStart
 

1.6

1.6

BrowserQuickStart

BrowserQuickStart
 

1.7

1.7

TypeScript'sTypeSystem

TypeScript'sTypeSystem
 

1.8

1.8
JSMigrationGuide   1.8.1

JSMigrationGuide

 

1.8.1

1.8.1
@types   1.8.2

@types

 

1.8.2

1.8.2
AmbientDeclarations   1.8.3

AmbientDeclarations

 

1.8.3

1.8.3
DeclarationFiles   1.8.3.1

DeclarationFiles

 

1.8.3.1

1.8.3.1
Variables   1.8.3.2

Variables

 

1.8.3.2

1.8.3.2
Interfaces   1.8.4

Interfaces

 

1.8.4

1.8.4
Enums   1.8.5

Enums

 

1.8.5

1.8.5
lib.d.ts   1.8.6

lib.d.ts

 

1.8.6

1.8.6
Functions   1.8.7

Functions

 

1.8.7

1.8.7
Callable   1.8.8

Callable

 

1.8.8

1.8.8
TypeAssertion   1.8.9

TypeAssertion

 

1.8.9

1.8.9
Freshness   1.8.10

Freshness

 

1.8.10

1.8.10
TypeGuard   1.8.11

TypeGuard

 

1.8.11

1.8.11
LiteralTypes   1.8.12

LiteralTypes

 

1.8.12

1.8.12
Readonly   1.8.13

Readonly

 

1.8.13

1.8.13
Generics   1.8.14

Generics

 

1.8.14

1.8.14
TypeInference   1.8.15

TypeInference

 

1.8.15

1.8.15
TypeCompatibility   1.8.16

TypeCompatibility

 

1.8.16

1.8.16
NeverType   1.8.17

NeverType

 

1.8.17

1.8.17
DiscriminatedUnions   1.8.18

DiscriminatedUnions

 

1.8.18

1.8.18
IndexSignatures   1.8.19

IndexSignatures

 

1.8.19

1.8.19
MovingTypes   1.8.20

MovingTypes

 

1.8.20

1.8.20
ExceptionHandling   1.8.21

ExceptionHandling

 

1.8.21

1.8.21
Mixins   1.8.22

Mixins

 

1.8.22

1.8.22

JSX

JSX

1.9

1.9
React   1.9.1
React   1.9.1

React

 
1.9.1

1.9.1

1.9.1
NonReactJSX   1.9.2

NonReactJSX

 

1.9.2

1.9.2

Options

Options
 

1.10

1.10
noImplicitAny   1.10.1

noImplicitAny

 

1.10.1

1.10.1
strictNullChecks   1.10.2

strictNullChecks

 

1.10.2

1.10.2

ErrorsinTypeScript

ErrorsinTypeScript
 

1.11

1.11
InterpretingErrors   1.11.1

InterpretingErrors

 

1.11.1

1.11.1
CommonErrors   1.11.2

CommonErrors

 

1.11.2

1.11.2

NPM

NPM
 

1.12

1.12

Testing

Testing
 

1.13

1.13
Jest   1.13.1

Jest

 

1.13.1

1.13.1
Cypress   1.13.2

Cypress

 

1.13.2

1.13.2

Tools

Tools
 

1.14

1.14
Prettier   1.14.1

Prettier

 

1.14.1

1.14.1
Husky   1.14.2

Husky

 

1.14.2

1.14.2
Changelog   1.14.3

Changelog

 

1.14.3

1.14.3

TIPs

TIPs

1.15

1.15
StringBasedEnums   1.15.1

StringBasedEnums

 

1.15.1

1.15.1
NominalTyping   1.15.2

NominalTyping

 

1.15.2

1.15.2
StatefulFunctions   1.15.3

StatefulFunctions

 

1.15.3

1.15.3
BindisBad   1.15.4

BindisBad

 

1.15.4

1.15.4
Currying   1.15.5

Currying

 

1.15.5

1.15.5
TypeInstantiation   1.15.6

TypeInstantiation

 

1.15.6

1.15.6
LazyObjectLiteralInitialization   1.15.7

LazyObjectLiteralInitialization

 

1.15.7

1.15.7
ClassesareUseful   1.15.8

ClassesareUseful

 

1.15.8

1.15.8
AvoidExportDefault   1.15.9

AvoidExportDefault

 

1.15.9

1.15.9
LimitPropertySetters   1.15.10

LimitPropertySetters

 

1.15.10

1.15.10
outFilecaution   1.15.11

outFilecaution

 

1.15.11

1.15.11
JQuerytips   1.15.12

JQuerytips

 

1.15.12

1.15.12
staticconstructors   1.15.13

staticconstructors

 

1.15.13

1.15.13
singletonpattern   1.15.14

singletonpattern

 

1.15.14

1.15.14
Functionparameters   1.15.15

Functionparameters

 

1.15.15

1.15.15
BuildToggles   1.15.16

BuildToggles

 

1.15.16

1.15.16
Barrel   1.15.17

Barrel

 

1.15.17

1.15.17
CreateArrays   1.15.18

CreateArrays

 

1.15.18

1.15.18
TypesafeEventEmitter   1.15.19

TypesafeEventEmitter

 

1.15.19

1.15.19

StyleGuide

StyleGuide
 

1.16

1.16

TypeScriptCompilerInternals

TypeScriptCompilerInternals
 

1.17

1.17
Program   1.17.1

Program

 

1.17.1

1.17.1
AST 1.17.2

AST

1.17.2

1.17.2
TIP:VisitChildren   1.17.2.1

TIP:VisitChildren

 

1.17.2.1

1.17.2.1
TIP:SyntaxKindenum   1.17.2.2

TIP:SyntaxKindenum

 

1.17.2.2

1.17.2.2
Trivia   1.17.2.3

Trivia

 

1.17.2.3

1.17.2.3
Scanner   1.17.3

Scanner

 

1.17.3

1.17.3
Parser   1.17.4

Parser

 

1.17.4

1.17.4
ParserFunctions   1.17.4.1

ParserFunctions

 

1.17.4.1

1.17.4.1
Binder   1.17.5

Binder

 

1.17.5

1.17.5
BinderFunctions   1.17.5.1

BinderFunctions

 

1.17.5.1

1.17.5.1
BinderDeclarations   1.17.5.2

BinderDeclarations

 

1.17.5.2

1.17.5.2
BinderContainer   1.17.5.3

BinderContainer

 

1.17.5.3

1.17.5.3
BinderSymbolTable   1.17.5.4

BinderSymbolTable

 

1.17.5.4

1.17.5.4
BinderErrorReporting   1.17.5.5

BinderErrorReporting

 

1.17.5.5

1.17.5.5
Checker   1.17.6

Checker

 

1.17.6

1.17.6
CheckerDiagnostics   1.17.6.1

CheckerDiagnostics

 

1.17.6.1

1.17.6.1
CheckerErrorReporting 1.17.6.2

CheckerErrorReporting

1.17.6.2

1.17.6.2
Emitter   1.17.7

Emitter

 

1.17.7

1.17.7
EmitterFunctions   1.17.7.1

EmitterFunctions

 

1.17.7.1

1.17.7.1
EmitterSourceMaps   1.17.7.2

EmitterSourceMaps

 

1.17.7.2

1.17.7.2
Contributing   1.17.8

Contributing

 

1.17.8

1.17.8

Introduction

TypeScriptDeepDive

I'vebeenlookingattheissuesthatturnupcommonlywhenpeoplestartusingTypeScript.

ThisisbasedonthelessonsfromStackOverflow/DefinitelyTypedandgeneralengagement

Reviews

Thanksforthewonderfulbook.Learnedalotfromit.(link) ItsprobablytheBestTypeScriptbookoutthere.GoodJob(link) Lovehowpreciseandcleartheexamplesandexplanationsare!(link) Forthelow,lowpriceoffree,yougetpagesofpureawesomeness.Chockfullofsource codeexamplesandclear,conciseexplanations,TypeScriptDeepDivewillhelpyou learnTypeScriptdevelopment.(link)

Justabigthankyou!BestTypeScript2detailedexplanation!(link)

Thisgitbookgotmyprojectgoingpronto.Fluenteasyread5stars.(link)

Irecommendtheonline#typescriptbookby@basaratyou'llloveit.(link)

I'vealwaysfoundthisby@basaratreallyhelpful.(link)

WemusthighlightTypeScriptDeepDive,anopensourcebook.(link)

Greatonlineresourceforlearning.(link)

Thankyouforputtingthisbooktogether,andforallyourhardworkwithintheTypeScript

community.(link)

TypeScriptDeepDiveisoneofthebesttechnicaltextsI'vereadinawhile.(link)

Thanks@basaratfortheTypeScriptDeepDiveBook.Helpmealotwithmyfirst

TypeScriptproject.(link)

Thanksto@basaratforthisgreat#typescriptlearningresource.(link)

GuyzexcellentbookonTypescript(@typescriptlang)by@basarat(link)

Leaningonthelegendary@basarat's"TypeScriptDeepDive"bookheavilyatthe

moment(link)

numTimesPointedPeopleToBasaratsTypeScriptBook++;(link)

Abooknotonlyfortypescript,agoodonefordeeperJavaScriptknowledgeaswell.link

Inmynewjob,we'reusing@typescriptlang,whichIamnewto.Thisisinsanelyhelpful

hugethanks,@basarat!link

ThankyouforwritingTypeScriptDeepDive.Ihavelearnedsomuch.link

Loving@basarat's@typescriptlangonlinebookbasarat.gitbooks.io/typescript/#loaded

withgreatrecipes!link

Microsoftdocisgreatalready,butifwantto"digdeeper"intoTypeScriptIfindthisbook

Introduction

ofgreatvaluelink

Thanks,thisisagreatbook

Deepdivetotypescriptisawesomeinsomanylevels.ifinditveryinsightful.Thanks

@basarat'sintroto@typescriptlangisstilloneofthebestgoing(ifnotTHEbest)link

Thisissweet!Somany#typescriptgoodies!link

GetStarted

Ifyouareheretoreadthebookonlinegetstarted.

Translations

Bookiscompletelyfreesoyoucancopypastewhateveryouwantwithoutrequiring

permission.Ifyouhaveatranslationyouwantmetolinkhere.SendaPR.

OtherOptions

Youcanalsodownloadoneofthefollowing:

SpecialThanks

Alltheamazingcontributors

Share

Introduction

GettingStarted

GettingStarted GettingStartedwithTypeScript TypeScriptVersion GettingStartedWithTypeScript

GettingStartedwithTypeScript

TypeScriptVersion

GettingStartedWithTypeScript

TypeScriptcompilesintoJavaScript.JavaScriptiswhatyouareactuallygoingtoexecute

(eitherinthebrowserorontheserver).Soyouaregoingtoneedthefollowing:

TypeScriptcompiler(OSSavailableinsourceandonNPM) ATypeScripteditor(youcanusenotepadifyouwantbutIusevscode withan extensionIwrote.AlsolotsofotherIDESsupportitaswell)

TypeScriptVersion

InsteadofusingthestableTypeScriptcompilerwewillbepresentingalotofnewstuffinthis

bookthatmaynotbeassociatedwithaversionnumberyet.Igenerallyrecommendpeople

tousethenightlyversionbecausethecompilertestsuiteonlycatchesmorebugsover

time.

Youcaninstallitonthecommandlineas

npm install -g typescript@next

Andnowthecommandline

e.g.

tsc
tsc

willbethelatestandgreatest.VariousIDEssupportittoo,

Youcanaskvscodetousethisversionbycreating

followingcontents:

.vscode/settings.json

withthe

{

"typescript.tsdk": "./node_modules/typescript/lib"

}

GettingtheSourceCode

Thesourceforthisbookisavailableinthebooksgithubrepository

becopiedintovscodeandyoucanplaywiththemasis.Forcodesamplesthatneed

GettingStarted

additionalsetup(e.g.npmmodules),wewilllinkyoutothecodesamplebeforepresenting

thecode.e.g.

this/will/be/the/link/to/the/code.ts

// This will be the code under discussion

Withadevsetupoutofthewaylet'sjumpintoTypeScriptsyntax.

WhyTypeScript

WhyTypeScript

TherearetwomaingoalsofTypeScript:

ProvideanoptionaltypesystemforJavaScript.

ProvideplannedfeaturesfromfutureJavaScripteditionstocurrentJavaScriptengines

Thedesireforthesegoalsismotivatedbelow.

TheTypeScripttypesystem

Youmightbewondering"WhyaddtypestoJavaScript?"

Typeshaveprovenabilitytoenhancecodequalityandunderstandability.Largeteams

(Google,Microsoft,Facebook)havecontinuallyarrivedatthisconclusion.Specifically:

Typesincreaseyouragilitywhendoingrefactoring.It'sbetterforthecompilertocatch

errorsthantohavethingsfailatruntime.

Typesareoneofthebestformsofdocumentationyoucanhave.Thefunctionsignature

isatheoremandthefunctionbodyistheproof.

However,typeshaveawayofbeingunnecessarilyceremonious.TypeScriptisvery

particularaboutkeepingthebarriertoentryaslowaspossible.Here'show:

YourJavaScriptisTypeScript

TypeScriptprovidescompiletimetypesafetyforyourJavaScriptcode.Thisisnosurprise

givenitsname.Thegreatthingisthatthetypesarecompletelyoptional.YourJavaScript

code .js .js
code
.js
.js

filecanberenamedtoa

.ts
.ts

fileandTypeScriptwillstillgiveyoubackvalid

equivalenttotheoriginalJavaScriptfile.TypeScriptisintentionallyandstrictlya

supersetofJavaScriptwithoptionalTypechecking.

TypescanbeImplicit

TypeScriptwilltrytoinferasmuchofthetypeinformationasitcaninordertogiveyoutype

safetywithminimalcostofproductivityduringcodedevelopment.Forexample,inthe

followingexampleTypeScriptwillknowthatfooisoftype

erroronthesecondlineasshown:

number
number

belowandwillgivean

WhyTypeScript

var foo = 123; foo = '456'; // Error: cannot assign `string` to `number`

// Is foo a number or a string?

Thistypeinferenceiswellmotivated.Ifyoudostufflikeshowninthisexample,then,inthe

restofyourcode,youcannotbecertainthat

turnupofteninlargemulti-filecodebases.Wewilldeepdiveintothetypeinferencerules

later.

foo
foo

isa

number
number

ora

string
string

.Suchissues

TypescanbeExplicit

Aswe'vementionedbefore,TypeScriptwillinferasmuchasitcansafely.However,youcan

useannotationsto:

1. Helpalongthecompiler,andmoreimportantlydocumentstuffforthenextdeveloper

whohastoreadyourcode(thatmightbefutureyou!).

2. Enforcethatwhatthecompilersees,iswhatyouthoughtitshouldsee.Thatisyour

understandingofthecodematchesanalgorithmicanalysisofthecode(donebythe

compiler).

TypeScriptusespostfixtypeannotationspopularinotheroptionallyannotatedlanguages

(e.g.ActionScriptandF#).

var foo: number = 123;

Soifyoudosomethingwrongthecompilerwillerrore.g.:

var foo: number = '123'; // Error: cannot assign a `string` to a `number`

WewilldiscussallthedetailsofalltheannotationsyntaxsupportedbyTypeScriptinalater

chapter.

Typesarestructural

Insomelanguages(specificallynominallytypedones)statictypingresultsinunnecessary

ceremonybecauseeventhoughyouknowthatthecodewillworkfinethelanguage

semanticsforceyoutocopystuffaround.ThisiswhystufflikeautomapperforC#isvitalfor

C#.InTypeScriptbecausewereallywantittobeeasyforJavaScriptdeveloperswitha

WhyTypeScript

minimumcognitiveoverload,typesarestructural.Thismeansthatducktypingisafirstclass

languageconstruct.Considerthefollowingexample.Thefunction

anythingthatcontainsallthethings(

iTakePoint2D

willaccept

x
x

and

y
y

)itexpects:

interface Point2D { x: number; y: number;

}

interface Point3D { x: number; y: number; z: number;

}

var point2D: Point2D = { x: 0, y: 10 } var point3D: Point3D = { x: 0, y: 10, z: 20 } function iTakePoint2D(point: Point2D) { /* do something */ }

iTakePoint2D(point2D); // exact match okay iTakePoint2D(point3D); // extra information okay iTakePoint2D({ x: 0 }); // Error: missing information `y`

TypeerrorsdonotpreventJavaScriptemit

TomakeiteasyforyoutomigrateyourJavaScriptcodetoTypeScript,evenifthereare

compilationerrors,bydefaultTypeScriptwillemitvalidJavaScriptthebestthatitcan.e.g.

var foo = 123; foo = '456'; // Error: cannot assign a `string` to a `number`

willemitthefollowingjs:

var foo = 123; foo = '456';

SoyoucanincrementallyupgradeyourJavaScriptcodetoTypeScript.Thisisverydifferent

fromhowmanyotherlanguagecompilersworkandyetanotherreasontomoveto

TypeScript.

Typescanbeambient

AmajordesigngoalofTypeScriptwastomakeitpossibleforyoutosafelyandeasilyuse

existingJavaScriptlibrariesinTypeScript.TypeScriptdoesthisbymeansofdeclaration.

TypeScriptprovidesyouwithaslidingscaleofhowmuchorhowlittleeffortyouwanttoput

WhyTypeScript

inyourdeclarations,themoreeffortyouputthemoretypesafety+codeintelligenceyou

get.NotethatdefinitionsformostofthepopularJavaScriptlibrarieshavealreadybeen

writtenforyoubytheDefinitelyTypedcommunitysoformostpurposeseither:

1. Thedefinitionfilealreadyexists.

2. Orattheveryleast,youhaveavastlistofwellreviewedTypeScriptdeclaration

templatesalreadyavailable

Asaquickexampleofhowyouwouldauthoryourowndeclarationfile,consideratrivial

exampleofjquery.Bydefault(asistobeexpectedofgoodJScode)TypeScriptexpectsyou

todeclare(i.e.use

var
var

somewhere)beforeyouuseavariable

$('.awesome').show(); // Error: cannot find name `$`

AsaquickfixyoucantellTypeScriptthatthereisindeedsomethingcalled

$ :
$
:

declare var $: any; $('.awesome').show(); // Okay!

Ifyouwantyoucanbuildonthisbasicdefinitionandprovidemoreinformationtohelp

protectyoufromerrors:

declare var $: { (selector:string): any;

}; $('.awesome').show(); // Okay! $(123).show(); // Error: selector needs to be a string

WewilldiscussthedetailsofcreatingTypeScriptdefinitionsforexistingJavaScriptindetail

lateronceyouknowmoreaboutTypeScript(e.g.stufflike

interface

andthe

any ).
any
).

FutureJavaScript=>Now

TypeScriptprovidesanumberoffeaturesthatareplannedinES6forcurrentJavaScript

engines(thatonlysupportES5etc).TheTypeScriptteamisactivelyaddingthesefeatures

andthislistisonlygoingtogetbiggerovertimeandwewillcoverthisinitsownsection.But

justasaspecimenhereisanexampleofaclass:

WhyTypeScript

class Point {

constructor(public x: number, public y: number) {

}

add(point: Point) { return new Point(this.x + point.x, this.y + point.y);

}

}

var p1 = new Point(0, 10); var p2 = new Point(10, 20); var p3 = p1.add(p2); // { x: 10, y: 30 }

andthelovelyfatarrowfunction:

var inc = x => x+1;

Summary

InthissectionwehaveprovidedyouwiththemotivationanddesigngoalsofTypeScript.

WiththisoutofthewaywecandigintothenittygrittydetailsofTypeScript.

JavaScript

YourJavaScriptisTypeScript

Therewere(andwillcontinuetobe)alotofcompetitorsinSomesyntaxtoJavaScript

compilers.TypeScriptisdifferentfromtheminthatYourJavaScriptisTypeScript.Here'sa

diagram:

YourJavaScriptisTypeScript .Here'sa diagram: However,itdoesmeanthat youneedtolearnJavaScript

However,itdoesmeanthatyouneedtolearnJavaScript(thegoodnewsisyouonlyneed

tolearnJavaScript).TypeScriptisjuststandardizingallthewaysyouprovidegood

documentationonJavaScript.

Justgivingyouanewsyntaxdoesn'thelpfixbugs(lookingatyouCoffeeScript).

Creatinganewlanguageabstractsyoutoofarfromyourruntimes,communities

(lookingatyouDart).

TypeScriptisjustJavaScriptwithdocs.

JavaScript

MakingJavaScriptBetter

TypeScriptwilltrytoprotectyoufromportionsofJavaScriptthatneverworked(soyoudon't

needtorememberthisstuff):

[]

+ []; // JavaScript will give you "" (which makes little sense), TypeScript will er

ror

// // other things that are nonsensical in JavaScript // - don't give a runtime error (making debugging hard)

 

// - but TypeScript will give a compile time error (making debugging unnecessary) // {} + []; // JS : 0, TS Error

[]

+ {}; // JS : "[object Object]", TS Error

{} + {}; // JS : NaN or [object Object][object Object] depending upon browser, TS Error

"hello" - 1; // JS : NaN, TS Error

 

function add(a,b) { return a + b; // JS : undefined, TS Error 'unreachable code detected'

}

  function add ( a,b ) { return a + b; // JS : undefined, TS
  function add ( a,b ) { return a + b; // JS : undefined, TS

EssentiallyTypeScriptislintingJavaScript.Justdoingabetterjobatitthanotherlintersthat

don'thavetypeinformation.

YoustillneedtolearnJavaScript

ThatsaidTypeScriptisverypragmaticaboutthefactthatyoudowriteJavaScriptsothere

aresomethingsaboutJavaScriptthatyoustillneedtoknowinordertonotbecaughtoff-

guard.Let'sdiscussthemnext.

Note:TypeScriptisasupersetofJavaScript.Justwithdocumentationthatcanactually

beusedbycompilers/IDEs;)

Equality

Equality

OnethingtobecarefulaboutinJavaScriptisthedifferencebetween

JavaScripttriestoberesilientagainstprogrammingerrors

betweentwovariablese.g.convertsastringtoanumbersothatyoucancomparewitha

numberasshownbelow:

==
==

and

===
===

.As

==
==

triestodotypecoercion

, TS Error

console.log(5 === "5"); // false , TS Error

console.log(5 == "5"); // true

However,thechoicesJavaScriptmakesarenotalwaysideal.Forexample,inthebelow

examplethefirststatementisfalsebecause

notequal.However,inthesecondcaseboth

behavelike

whenyouuse

"" 0
""
0

and

"0"
"0"

arebothstringsandareclearly

""
""

)arefalsy(i.e.

andtheemptystring(

==
==
false === .
false
===
.

)andarethereforeequalwithrespectto

.Bothstatementsarefalse

console.log("" == "0"); // false console.log(0 == ""); // true

console.log("" === "0"); // false console.log(0 === ""); // false

Notethat

TypeScript,soyoudon'tnormallyneedtoworryaboutthis.

string == number

and

string === number

arebothcompiletimeerrorsin

Similarto

==
==

vs.

===
===

SoProTip:Alwaysuse

,thereis != vs. !== === and !== exceptfornullchecks,whichwecoverlater.
,thereis
!=
vs.
!==
===
and
!==
exceptfornullchecks,whichwecoverlater.

StructuralEquality

Ifyouwanttocomparetwoobjectsforstructuralequality

== / ===
==
/ ===

arenotsufficient.e.g.

console.log({a:123} == {a:123}); // False console.log({a:123} === {a:123}); // False

Todosuchchecksusethedeep-equalnpmpackagee.g.

Equality

import * as deepEqual from "deep-equal";

console.log(deepEqual({a:123},{a:123})); // True

However,quitecommonlyyoudon'tneeddeepchecksandallyoureallyneedistocheckby

some

id
id

e.g.

type IdDisplay = { id: string, display: string

}

const list: IdDisplay[] = [

{

 

id: 'foo', display: 'Foo Select'

},

{

 

id: 'bar', display: 'Bar Select'

},

]

const fooIndex = list.map(i => i.id).indexOf('foo'); console.log(fooIndex); // 0

References

References

Beyondliterals,anyObjectinJavaScript(includingfunctions,arrays,regexpetc)are

references.Thismeansthefollowing

Mutationsareacrossallreferences

var foo = {}; var bar = foo; // bar is a reference to the same object

foo.baz = 123; console.log(bar.baz); // 123

Equalityisforreferences

var foo = {}; var bar = foo; // bar is a reference var baz = {}; // baz is a *new object* distinct from `foo`

console.log(foo === bar); // true console.log(foo === baz); // false

Nullvs.Undefined

NullandUndefined

JavaScript(andbyextensionTypeScript)hastwobottomtypes:

Theyareintendedtomeandifferentthings:

Somethinghasn'tbeeninitialized:

Somethingiscurrentlyunavailable:

undefined . null .
undefined
.
null
.

Checkingforeither

Factisyouwillneedtodealwithboth.Justcheckforeitherwith

null
null

and

==
==

check.

undefined

.

/// Imagine you are doing `foo.bar == undefined` where bar can be one of:

console.log(undefined == undefined); // true console.log(null == undefined); // true

// You don't have to worry about falsy values making through this check console.log(0 == undefined); // false console.log('' == undefined); // false console.log(false == undefined); // false

Recommend

makeadistinctionbetweenthetwo.

== null
== null

tocheckforboth

undefined

or

null
null

.Yougenerallydon'twantto

function foo(arg: string | null | undefined) { if (arg != null) { // arg must be a string as `!=` rules out both null and undefined.

}

}

Oneexception,rootlevelundefinedvalueswhichwediscussnext.

Checkingforrootlevelundefined

RememberhowIsaidyoushoulduse

Don'tuseitforrootlevelthings.Instrictmodeifyouuse

geta

== null
== null

.Ofcourseyoudo(causeIjustsaidit^).

foo
foo

and

foo
foo

isundefinedyou

ReferenceError

exceptionandthewholecallstackunwinds.

Youshouldusestrictmode

modules

andinfacttheTScompilerwillinsertitforyouifyouuse

moreonthoselaterinthebooksoyoudon'thavetobeexplicitaboutit:)

Sotocheckifavariableisdefinedornotatagloballevelyounormallyuse

typeof :
typeof
:

Nullvs.Undefined

if (typeof someglobal !== 'undefined') { // someglobal is now safe to use console.log(someglobal);

}

Limitexplicituseof

undefined

BecauseTypeScriptgivesyoutheopportunitytodocumentyourstructuresseparatelyfrom

valuesinsteadofstufflike:

function foo(){ // if Something return {a:1,b:2}; // else return {a:1,b:undefined};

}

youshoulduseatypeannotation:

function foo():{a:number,b?:number}{ // if Something return {a:1,b:2}; // else return {a:1};

}

Nodestylecallbacks

Nodestylecallbackfunctions(e.g.

(err,somethingElse)=>{ /* something */ }

)aregenerally

calledwith err thisanyways:
calledwith
err
thisanyways:

setto

null
null

ifthereisn'tanerror.Yougenerallyjustuseatruthycheckfor

fs.readFile('someFile', 'utf8', (err,data) => { if (err) { // do something } else { // no error

}

});

WhencreatingyourownAPIsit'sokaytouse

sincerityforyourownAPIsyoushouldlookatpromises,inthatcaseyouactuallydon'tneed

tobotherwithabsenterrorvalues(youhandlethemwith

null
null

inthiscaseforconsistency.Inall

.then
.then

vs.

.catch ).
.catch
).

Nullvs.Undefined

Don'tuse

undefined

asameansofdenotingvalidity

Forexampleanawfulfunctionlikethis:

function toInt(str:string) { return str ? parseInt(str) : undefined;

}

canbemuchbetterwrittenlikethis:

function toInt(str: string): { valid: boolean, int?: number } { const int = parseInt(str); if (isNaN(int)) { return { valid: false };

}

else { return { valid: true, int };

}

}

Finalthoughts

TypeScriptteamdoesn'tuse

problems.DouglasCrockfordthinks

null null
null
null

:TypeScriptcodingguidelinesandithasn'tcausedany

isabadideaandweshouldalljustuse

undefined .

However,NodeJSstylecodebasesuses

denotes

thetwoasmostprojectsuselibrarieswithdifferingopinionsandjustruleoutbothwith

null
null

forErrorargumentsasstandardasit

Something is currently unavailable

.Ipersonallydon'tcaretodistinguishbetween

==
==
null .
null
.

this

this

Anyaccessto

actuallycalled.Itiscommonlyreferredtoasthe“callingcontext.”

this
this

keywordwithinafunctionisactuallycontrolledbyhowthefunctionis

Hereisanexample:

function foo() { console.log(this);

}

foo(); // logs out the global e.g. `window` in browsers let bar = { foo

}

bar.foo(); // Logs out `bar` as `foo` was called on `bar`

Sobemindfulofyourusageof

callingcontextuseanarrowfunction,moreonthatlater.

this
this

.Ifyouwanttodisconnect

this
this

inaclassfromthe

Closure

Closure

ThebestthingthatJavaScriptevergotwasclosures.AfunctioninJavaScripthasaccessto

anyvariablesdefinedintheouterscope.Closuresarebestexplainedwithexamples:

function outerFunction(arg) { var variableInOuterFunction = arg; function bar() { console.log(variableInOuterFunction);
function outerFunction(arg) {
var variableInOuterFunction = arg;
function bar() {
console.log(variableInOuterFunction); // Access a variable from the outer scope
}
// Call the local function to demonstrate that it has access to arg
bar();
}
outerFunction("hello closure"); // logs hello closure!

Youcanseethattheinnerfunctionhasaccesstoavariable(variableInOuterFunction)from

theouterscope.Thevariablesintheouterfunctionhavebeenclosedby(orboundin)the

innerfunction.Hencethetermclosure.Theconceptinitselfissimpleenoughandpretty

intuitive.

Nowtheawesomepart:Theinnerfunctioncanaccessthevariablesfromtheouterscope

evenaftertheouterfunctionhasreturned.Thisisbecausethevariablesarestillboundin

theinnerfunctionandnotdependentontheouterfunction.Againlet'slookatanexample:

function outerFunction(arg) { var variableInOuterFunction = arg; return function() { console.log(variableInOuterFunction);

}

}

var innerFunction = outerFunction("hello closure!");

// Note the outerFunction has returned innerFunction(); // logs hello closure!

Reasonwhyit'sawesome

Itallowsyoutocomposeobjectseasilye.g.therevealingmodulepattern:

Closure

function createCounter() { let val = 0; return { increment() { val++ }, getVal() { return val }

}

}

let counter = createCounter(); counter.increment(); console.log(counter.getVal()); // 1 counter.increment(); console.log(counter.getVal()); // 2

AtahighlevelitisalsowhatmakessomethinglikeNode.jspossible(don'tworryifitdoesn't

clickinyourbrainrightnow.Itwilleventually):

// Pseudo code to explain the concept server.on(function handler(req, res) { loadData(req.id).then(function(data) { // the `res` has been closed over and is available res.send(data);

});

})

Number

Number

Wheneveryouarehandlingnumbersinanyprogramminglanguageyouneedtobeawareof

theidiosyncrasiesofhowthelanguagehandlesnumbers.Hereareafewcriticalpiecesof

informationaboutnumbersinJavaScriptthatyoushouldbeawareof.

CoreType

JavaScripthasonlyonenumbertype.Itisadouble-precision64-bit

discussitslimitationsalongwitharecommendedsolution.

Number
Number

.Belowwe

Decimal

Forthosefamiliarwithdoubles/floatinotherlanguages,youwouldknowthatbinaryfloating

pointnumbersdonotmapcorrectlytoDecimalnumbers.Atrivial(andfamous)examplewith

JavaScript'sbuiltinnumbersisshownbelow:

console.log(.1 + .2); // 0.30000000000000004

Fortruedecimalmathuse

big.js
big.js

mentionedbelow.

Integer

Theintegerlimitsrepresentedbythebuiltinnumbertypeare

Number.MIN_SAFE_INTEGER

.

Number.MAX_SAFE_INTEGER

and

console.log({max: Number.MAX_SAFE_INTEGER, min: Number.MIN_SAFE_INTEGER}); // {max: 9007199254740991, min: -9007199254740991}

Safeinthiscontextreferstothefactthatthevaluecannotbetheresultofaroundingerror.

Theunsafevaluesare

subtractionwillroundtheresult.

+1 / -1
+1 / -1

awayfromthesesafevaluesandanyamountofaddition/

Number

console.log(Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2); // true! console.log(Number.MIN_SAFE_INTEGER - 1 === Number.MIN_SAFE_INTEGER - 2); // true!

console.log(Number.MAX_SAFE_INTEGER);

console.log(Number.MAX_SAFE_INTEGER + 1); // 9007199254740992 - Correct console.log(Number.MAX_SAFE_INTEGER + 2); // 9007199254740992 - Rounded! console.log(Number.MAX_SAFE_INTEGER + 3); // 9007199254740994 - Rounded - correct by luck console.log(Number.MAX_SAFE_INTEGER + 4); // 9007199254740996 - Rounded!

// 9007199254740991

TochecksafetyyoucanuseES6

Number.isSafeInteger

:

// Safe value console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER)); // true

// Unsafe value console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 1)); // false

// Because it might have been rounded to it due to overflow console.log(Number.isSafeInteger(Number.MAX_SAFE_INTEGER + 10)); // false

JavaScriptwilleventuallygetBigIntsupport.Fornow,ifyouwantarbitraryprecision

integermathuse

big.js
big.js

mentionedbelow.

big.js

Wheneveryouusemathforfinancialcalculations(e.g.GSTcalculation,moneywithcents,

additionetc)usealibrarylikebig.jswhichisdesignedfor

additionetc)usealibrarylike big.js whichisdesignedfor Perfectdecimalmath Safeoutofboundintegervalues

Perfectdecimalmath

Safeoutofboundintegervalues

Installationissimple:

npm install big.js @types/big.js

QuickUsageexample:

import { Big } from 'big.js';

export const foo = new Big('111.11111111111111111111'); export const bar = foo.plus(new Big('0.00000000000000000001'));

// To get a number:

const x: number = Number(bar.toString()); // Loses the precision

Number

DonotusethislibraryformathusedforUI/performanceintensivepurposese.gcharts,

canvasdrawingetc.

NaN

Whensomenumbercalculationisnotrepresentablebyavalidnumber,JavaScriptreturnsa

special

NaN
NaN

value.Aclassicexampleisimaginarynumbers:

console.log(Math.sqrt(-1)); // NaN

Note:Equalitychecksdon'tworkon

NaN
NaN

values.Use

Number.isNaN

instead:

// Don't do this console.log(NaN === NaN); // false!!

// Do this console.log(Number.isNaN(NaN)); // true

Infinity

TheouterboundsofvaluesrepresentableinNumberareavailableasstatic

Number.MAX_VALUE

and

-Number.MAX_VALUE

values.

console.log(Number.MAX_VALUE); // 1.7976931348623157e+308 console.log(-Number.MAX_VALUE); // -1.7976931348623157e+308

Valuesoutsidetherangewhereprecisionisn'tchangedareclampedtotheselimitse.g.

// true!

console.log(-Number.MAX_VALUE - 1 == -Number.MAX_VALUE); // true!

console.log(Number.MAX_VALUE + 1 == Number.MAX_VALUE);

Valuesoutsidetherangewhereprecisionischangedresolvetospecialvalues

Infinity
Infinity

e.g.

Infinity / -
Infinity / -

console.log(Number.MAX_VALUE + 10**1000); // Infinity console.log(-Number.MAX_VALUE - 10**1000); // -Infinity

Of-course,thesespecialinfinityvaluesalsoshowupwitharithmeticthatrequiresite.g.

console.log( 1 / 0); // Infinity console.log(-1 / 0); // -Infinity

Number

Youcanusethese

asshownbelow:

Infinity

valuesmanuallyorusingstaticmembersofthe

Number
Number

class

console.log(Number.POSITIVE_INFINITY === Infinity); // true console.log(Number.NEGATIVE_INFINITY === -Infinity); // true

Fortunatelycomparisonoperators(

<
<

/

>
>

)workreliablyoninfinityvalues:

console.log( Infinity > 1); // true console.log(-Infinity < -1); // true

Infinitesimal

Thesmallestnon-zerovaluerepresentableinNumberisavailableasstatic

Number.MIN_VALUE

console.log(Number.MIN_VALUE); // 5e-324

Valuessmallerthan

MIN_VALUE

("underflowvalues")areconvertedto0.

console.log(Number.MIN_VALUE / 10); // 0

Furtherintuition:Justlikevaluesbiggerthan

INFINITY,valuessmallerthan

Number.MAX_VALUE

getclampedto

getclampedto

0 .
0
.

Number.MIN_VALUE

Truthy

Truthy

JavaScripthasaconceptof

positions(e.g.

truthyinJavaScript.Anexampleisanynumberotherthan

truthy
truthy

i.e.thingsthatevaluatelike

&& ||
&&
||
true
true

wouldincertain

if
if

conditionsandtheboolean

operators).Thefollowingthingsare

0
0

e.g.

if (123) { // Will be treated like `true` console.log('Any number other than 0 is truthy');

}

Somethingthatisn'ttruthyiscalled

falsy .
falsy
.

Here'sahandytableforyourreference.

   

Whenitis

 

VariableType

Whenitisfalsy

truthy

boolean
boolean
 
false
false
true
true
string
string
 
''
''

(empty

anyotherstring

string)

number
number
 
0 NaN
0
NaN

anyother

number

null
null
 

always

never

undefined

always

never

AnyotherObjectincludingemptyoneslike

never

always

{}
{}
, []
,
[]

Beingexplicit

The !! pattern Quitecommonlyithelpstobeexplicitthattheintentistotreatthevalueasa boolean and
The
!!
pattern
Quitecommonlyithelpstobeexplicitthattheintentistotreatthevalueasa
boolean
and
convertitintoatrueboolean(oneof
true
|
false
).Youcaneasilyconvertvaluestoatrue
booleanbyprefixingitwith
!!
e.g.
!!foo
.Itsjust
!
usedtwice.Thefirst
!
convertsthe
variable(inthiscase
foo
)toabooleanbutinvertsthelogic(truthy-
!
>
false
,falsy-
!
>
true
).Thesecondonetogglesitagaintomatchthenatureoftheoriginalobject(e.g.truthy
-
!
>
false
-
!
>
true
).

Itiscommontousethispatterninlotsofplacese.g.

Truthy

// Direct variables const hasName = !!name;

// As members of objects const someObj = { hasName: !!name

}

// e.g. in ReactJS JSX {!!someName && <div>{someName}</div>}

FutureJavaScriptNow

FutureJavaScript:Now

OneofthemainsellingpointsofTypeScriptisthatitallowsyoutouseabunchoffeatures

fromES6andbeyondincurrent(ES3andES5level)JavaScriptengines(likecurrent

browsersandNode.js).Herewedeepdiveintowhythesefeaturesareusefulfollowedby

howthesefeaturesareimplementedinTypeScript.

Note:NotallofthesefeaturesareslatedforimmediateadditiontoJavaScriptbutprovide

greatutilitytoyourcodeorganizationandmaintenance.Alsonotethatyouarefreetoignore

anyoftheconstructsthatdon'tmakesenseforyourproject,althoughyouwillendupusing

mostofthemeventually;)

Classes

Classes

Thereasonwhyit'simportanttohaveclassesinJavaScriptasafirstclassitemisthat:

1. Classesofferausefulstructuralabstraction

2. Providesaconsistentwayfordeveloperstouseclassesinsteadofeveryframework

(emberjs,reactjsetc)comingupwiththeirownversion.

3. ObjectOrientedDevelopersalreadyunderstandclasses.

FinallyJavaScriptdeveloperscanhave

class
class

.HerewehaveabasicclasscalledPoint:

class Point { x: number; y: number; constructor(x: number, y: number) { this.x = x; this.y = y;

}

add(point: Point) { return new Point(this.x + point.x, this.y + point.y);

}

}

var p1 = new Point(0, 10); var p2 = new Point(10, 20); var p3 = p1.add(p2); // {x:10,y:30}

ThisclassgeneratesthefollowingJavaScriptonES5emit:

var Point = (function () { function Point(x, y) { this.x = x; this.y = y;

}

Point.prototype.add = function (point) { return new Point(this.x + point.x, this.y + point.y);

}; return Point; })();

ThisisafairlyidiomatictraditionalJavaScriptclasspatternnowasafirstclasslanguage

construct.

Inheritance

Classes

ClassesinTypeScript(likeotherlanguages)supportsingleinheritanceusingthe

keywordasshownbelow:

extends
extends

class Point3D extends Point { z: number; constructor(x: number, y: number, z: number) { super(x, y); this.z = z;

}

add(point: Point3D) { var point2D = super.add(point); return new Point3D(point2D.x, point2D.y, this.z + point.z);

}

}

Ifyouhaveaconstructorinyourclassthenyoumustcalltheparentconstructorfromyour

constructor(TypeScriptwillpointthisouttoyou).Thisensuresthatthestuffthatitneedsto

seton

wanttodoinyourconstructor(hereweaddanothermember

this
this

getsset.Followedbythecallto

super
super

youcanaddanyadditionalstuffyou

z ).
z
).
Notethatyouoverrideparentmemberfunctionseasily(hereweoverride add thefunctionalityofthesuperclassinyourmembers(using
Notethatyouoverrideparentmemberfunctionseasily(hereweoverride
add
thefunctionalityofthesuperclassinyourmembers(using
super.
syntax).

)andstilluse

Statics

TypeScriptclassessupport

Anaturalplacetoput(andaccess)themisontheclassitselfandthatiswhatTypeScript

does:

static
static

propertiesthataresharedbyallinstancesoftheclass.

class Something { static instances = 0; constructor() { Something.instances++;

}

}

var s1 = new Something(); var s2 = new Something(); console.log(Something.instances); // 2

Youcanhavestaticmembersaswellasstaticfunctions.

AccessModifiers

Classes

TypeScriptsupportsaccessmodifiers

theaccessibilityofa

public , private
public
, private
class
class

memberasshownbelow:

and

protected

whichdetermine

accessibleon

public
public
 

protected

private
private

class

yes

yes

yes

classchildren

yes

yes

no

classinstances

yes

no

no

Ifanaccessmodifierisnotspecifieditisimplicitly

natureofJavaScript.

public
public

asthatmatchestheconvenient

Notethatatruntime(inthegeneratedJS)thesehavenosignificancebutwillgiveyou

compiletimeerrorsifyouusethemincorrectly.Anexampleofeachisshownbelow:

class FooBase { public x: number; private y: number; protected z: number;

}

// EFFECT ON INSTANCES var foo = new FooBase(); foo.x; // okay foo.y; // ERROR : private foo.z; // ERROR : protected

// EFFECT ON CHILD CLASSES class FooChild extends FooBase { constructor() { super(); this.x; // okay this.y; // ERROR: private this.z; // okay

}

}

Asalwaysthesemodifiersworkforbothmemberpropertiesandmemberfunctions.

Abstract

abstract

canbethoughtofasanaccessmodifier.Wepresentitseparatelybecause

opposedtothepreviouslymentionedmodifiersitcanbeona

oftheclass.Havingan

directlyinvokedandachildclassmustprovidethefunctionality.

class
class

aswellasanymember

abstract

modifierprimarilymeansthatsuchfunctionalitycannotbe

abstract
abstract

classescannotbedirectlyinstantiated.Insteadtheusermustcreatesome

Classes

class abstract
class
abstract

thatinheritsfromthe

abstract class

.

memberscannotbedirectlyaccessedandachildclassmustprovidethe

functionality.

Constructorisoptional

Theclassdoesnotneedtohaveaconstructor.e.g.thefollowingisperfectlyfine.

class Foo {} var foo = new Foo();

Defineusingconstructor

Havingamemberinaclassandinitializingitlikebelow:

class Foo { x: number; constructor(x:number) { this.x = x;

}

}

issuchacommonpatternthatTypeScriptprovidesashorthandwhereyoucanprefixthe

memberwithanaccessmodifieranditisautomaticallydeclaredontheclassandcopied

fromtheconstructor.Sothepreviousexamplecanbere-writtenas(notice

public
public
x:number ):
x:number
):

class Foo {

constructor(public x:number) {

}

}

Propertyinitializer

ThisisaniftyfeaturesupportedbyTypeScript(fromES7actually).Youcaninitializeany

memberoftheclassoutsidetheclassconstructor,usefultoprovidedefault(notice

= [] )
= []
)
members
members

Classes

class Foo { members = []; // Initialize directly add(x) { this.members.push(x);

}

}

ClassesEmit

What'supwiththeIIFE

Thejsgeneratedfortheclasscouldhavebeen:

function Point(x, y) { this.x = x; this.y = y;

}

Point.prototype.add = function (point) { return new Point(this.x + point.x, this.y + point.y);

};

Thereasonit'swrappedinanImmediately-InvokedFunctionExpression(IIFE)i.e.

(function () {

// BODY

return Point; })();

hastodowithinheritance.ItallowsTypeScripttocapturethebaseclassasavariable

_super
_super

e.g.

var Point3D = (function (_super) {

extends(Point3D,

_super);

function Point3D(x, y, z) { _super.call(this, x, y); this.z = z;

}

Point3D.prototype.add = function (point) { var point2D = _super.prototype.add.call(this, point); return new Point3D(point2D.x, point2D.y, this.z + point.z);

}; return Point3D; })(Point);

NoticethattheIIFEallowsTypeScripttoeasilycapturethebaseclass

variableandthatisusedconsistentlyintheclassbody.

extends

Point
Point

ina

_super
_super

YouwillnoticethatassoonasyouinheritaclassTypeScriptalsogeneratesthefollowing

function: