1. typescript handbook€¦ · the typescript handbook is intended to be a comprehensive document...

87
1. TypeScript Handbook 2. Table of Contents 3. The TypeScript Handbook 4. Basic Types 5. Interfaces 6. Functions 7. Literal Types 8. Unions and Intersection Types 9. Classes 10. Enums 11. Generics

Upload: others

Post on 09-Feb-2021

22 views

Category:

Documents


0 download

TRANSCRIPT

  • 1. TypeScriptHandbook2. TableofContents3. TheTypeScriptHandbook4. BasicTypes5. Interfaces6. Functions7. LiteralTypes8. UnionsandIntersectionTypes9. Classes10. Enums11. Generics

  • ThiscopyoftheTypeScripthandbookwasgeneratedonWednesday,March3,2021againstcommit422674withTypeScript4.2.

    https://github.com/microsoft/TypeScript-Website/tree/422674https://www.typescriptlang.org//docs/handbook/release-notes/typescript-4-2.html

  • TheTypeScriptHandbook

    AboutthisHandbook

    Over20yearsafteritsintroductiontotheprogrammingcommunity,JavaScriptisnowoneofthemostwidespreadcross-platformlanguagesevercreated.Startingasasmallscriptinglanguageforaddingtrivialinteractivitytowebpages,JavaScripthasgrowntobealanguageofchoiceforbothfrontendandbackendapplicationsofeverysize.Whilethesize,scope,andcomplexityofprogramswritteninJavaScripthasgrownexponentially,theabilityoftheJavaScriptlanguagetoexpresstherelationshipsbetweendifferentunitsofcodehasnot.CombinedwithJavaScript'sratherpeculiarruntimesemantics,thismismatchbetweenlanguageandprogramcomplexityhasmadeJavaScriptdevelopmentadifficulttasktomanageatscale.

    Themostcommonkindsoferrorsthatprogrammerswritecanbedescribedastypeerrors:acertainkindofvaluewasusedwhereadifferentkindofvaluewasexpected.Thiscouldbeduetosimpletypos,afailuretounderstandtheAPIsurfaceofalibrary,incorrectassumptionsaboutruntimebehavior,orothererrors.ThegoalofTypeScriptistobeastatictypecheckerforJavaScriptprograms-inotherwords,atoolthatrunsbeforeyourcoderuns(static)andensuresthatthetypesoftheprogramarecorrect(typechecked).

    IfyouarecomingtoTypeScriptwithoutaJavaScriptbackground,withtheintentionofTypeScriptbeingyourfirstlanguage,werecommendyoufirststartreadingthedocumentationonJavaScriptattheMozillaWebDocs.Ifyouhaveexperienceinotherlanguages,youshouldbeabletopickupJavaScriptsyntaxquitequicklybyreadingthehandbook.

    https://developer.mozilla.org/docs/Web/JavaScript/Guide

  • HowisthisHandbookStructured

    Thehandbookissplitintotwosections:

    TheHandbook

    TheTypeScriptHandbookisintendedtobeacomprehensivedocumentthatexplainsTypeScripttoeverydayprogrammers.Youcanreadthehandbookbygoingfromtoptobottomintheleft-handnavigation.

    Youshouldexpecteachchapterorpagetoprovideyouwithastrongunderstandingofthegivenconcepts.TheTypeScriptHandbookisnotacompletelanguagespecification,butitisintendedtobeacomprehensiveguidetoallofthelanguage'sfeaturesandbehaviors.

    Areaderwhocompletesthewalkthroughshouldbeableto:

    Readandunderstandcommonly-usedTypeScriptsyntaxandpatternsExplaintheeffectsofimportantcompileroptionsCorrectlypredicttypesystembehaviorinmostcasesWritea.d.tsdeclarationforasimplefunction,object,orclass

    Intheinterestsofclarityandbrevity,themaincontentoftheHandbookwillnotexploreeveryedgecaseorminutiaeofthefeaturesbeingcovered.Youcanfindmoredetailsonparticularconceptsinthereferencearticles.

    ReferenceFiles

    ThereferencesectionisbuilttoprovidearicherunderstandingofhowaparticularpartofTypeScriptworks.Youcanreadittop-to-bottom,buteachsectionaimstoprovideadeeperexplanationofasingleconcept-meaningthereisnoaimforcontinuity.

    Non-Goals

  • Non-GoalsTheHandbookisalsointendedtobeaconcisedocumentthatcanbecomfortablyreadinafewhours.Certaintopicswon'tbecoveredinordertokeepthingsshort.

    Specifically,theHandbookdoesnotfullyintroducecoreJavaScriptbasicslikefunctions,classes,andclosures.Whereappropriate,we'llincludelinkstobackgroundreadingthatyoucanusetoreaduponthoseconcepts.

    TheHandbookalsoisn'tintendedtobeareplacementforalanguagespecification.Insomecases,edgecasesorformaldescriptionsofbehaviorwillbeskippedinfavorofhigh-level,easier-to-understandexplanations.Instead,thereareseparatereferencepagesthatmorepreciselyandformallydescribemanyaspectsofTypeScript'sbehavior.ThereferencepagesarenotintendedforreadersunfamiliarwithTypeScript,sotheymayuseadvancedterminologyorreferencetopicsyouhaven'treadaboutyet.

    Finally,theHandbookwon'tcoverhowTypeScriptinteractswithothertools,exceptwherenecessary.TopicslikehowtoconfigureTypeScriptwithwebpack,rollup,parcel,react,babel,closure,lerna,rush,bazel,preact,vue,angular,svelte,jquery,yarn,ornpmareoutofscope-youcanfindtheseresourceselsewhereontheweb.

    GetStarted

    BeforegettingstartedwithBasicTypes,werecommendreadingoneofthefollowingintroductorypages.TheseintroductionsareintendedtohighlightkeysimilaritiesanddifferencesbetweenTypeScriptandyourfavoredprogramminglanguage,andclearupcommonmisconceptionsspecifictothoselanguages.

    TypeScriptforNewProgrammersTypeScriptforJavaScriptProgrammersTypeScriptforOOPProgrammersTypeScriptforFunctionalProgrammers

    https://www.staging-typescript.org/docs/handbook/basic-types.htmlhttps://www.staging-typescript.org/docs/handbook/typescript-from-scratch.htmlhttps://www.staging-typescript.org/docs/handbook/typescript-in-5-minutes.htmlhttps://www.staging-typescript.org/docs/handbook/typescript-in-5-minutes-oop.htmlhttps://www.staging-typescript.org/docs/handbook/typescript-in-5-minutes-func.html

  • BasicTypesForprogramstobeuseful,weneedtobeabletoworkwithsomeofthesimplestunitsofdata:numbers,strings,structures,booleanvalues,andthelike.InTypeScript,wesupportthesametypesasyouwouldexpectinJavaScript,withanextraenumerationtypethrownintohelpthingsalong.

    Boolean

    Themostbasicdatatypeisthesimpletrue/falsevalue,whichJavaScriptandTypeScriptcallabooleanvalue.

    letisDone:boolean=false;

    Number

    AsinJavaScript,allnumbersinTypeScriptareeitherfloatingpointvaluesorBigIntegers.Thesefloatingpointnumbersgetthetypenumber,whileBigIntegersgetthetypebigint.Inadditiontohexadecimalanddecimalliterals,TypeScriptalsosupportsbinaryandoctalliteralsintroducedinECMAScript2015.

    letdecimal:number=6;lethex:number=0xf00d;letbinary:number=0b1010;letoctal:number=0o744;letbig:bigint=100n;

    String

    AnotherfundamentalpartofcreatingprogramsinJavaScriptforwebpagesandserversalikeisworkingwithtextualdata.Asinotherlanguages,weusethetype

    https://www.typescriptlang.org/play/#code/DYUwLgBAlgzgIgewHYgFwQEYIaAhkiAXggDNdgYQBuIAhttps://www.typescriptlang.org/play/#code/PTAEAEBcEMCcHMCmkBcoCiBlATABjwFAA2yoAJogMYCWAttEWgHYCutARorKALygBsAbmKkAFogAezNp259cEgGa5cZYSUih21JnACe0jl16hc7AIy5L60gHtKMRqFZG5p2wHYALF5ubt8GgBOpp8lrhMgkAhttps://www.typescriptlang.org/play/#code/DYUwLgBAxg9sMCcBcEDOYEEsB2BzCAvBAEQBGwAriMQNwBQA9AxAA4LhiYgIC0mu2RCDqx4CQhADk7ACaSaQAhttps://www.typescriptlang.org/play/#code/DYUwLgBAZgrswDkCGBbEAuCBnMAnAlgHYDmEAvBAAYBCA9gEYR331HFi2GUDcAUKJCTEMEQjBT0QuchADMAdj4DsIQmFUBjETgIkZlABIh4tADQQUAT1GoQEfFggASAN6x4yNAF8AdL14AkgDk8BCSzi5CdgDUEACMXhCWIEi4jrTAACaiIAAekCicYAAWPjxAAhttps://www.typescriptlang.org/play/#code/DYUwLgBAZgrswDkCGBbEAuCBnMAnAlgHYDmEAvBAAYBCA9gEYR331HFi2GUDcAUKJCTEMEQjBT0QuchADMAdj4B6JRAC0GgMYwwGtf3DYQhMMc0icBEuV4QIAIgASIeLQA0EFAE9RqEBHwsBwgAaltoOEQ-UPD7ADoAHUIk+xi7ewBJAHJ4CElgsLsACiF-EIgARgBKNOCvECRcINpgABNREAAPSBROMAALOPtuIAhttps://www.typescriptlang.org/play/#code/DYUwLgBMCWDOYC4IDsCuBbARiATgbQF0IBeCPARgBoIAmagZgIG4ghttps://www.typescriptlang.org/play/#code/DYUwLgBMCWDOYC4IEEBOqCGBPAPAOwFcBbAIxFQD4IBeCAbQEYAaCAJhYGYBdAbiAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGY1oFAlACKQDGANgIbSSjmgAuArgA6nV0CeTkOrdoAHqgDaiOtACWAOwDmAGlCSGAWwBGMALoBuPGACSk8XXHlS4gF7VDOfqAC8oIQCIAFpFKk4j+QEYADFtB8AHkAaR1QfUNjUwtQQzjJYgQqYjpSdms7Bz95FzcPRwD8AFFYBCAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYME4BQAbSAF1AA9UBtRI6ASwDsBzAGlHoFcBbAIxgF0A3LlKgAvKAoAiABaR8+OJNYBGAAyDQIUAHkA0rhBgAtCYDG7IiaMGwe3Kbj1EcQgDoFjABSkK614nZuajomT2UASnChe0dnNw9vCmU+f0Dghi8IqKAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwBYCcBmdBWHNdItAKABtIAXUAD1QG1FroBLAOwHMAaUDgK4BbAEYwAugG4ydUAF5QjAEQALSBQpwlfAIwAGKaBCgA8gGkyIMAFpbAYwHVb1mYxzj5oJQHcEFACZK0mR2cByIcFQAdJpcABR0jPjiUdRwAMqsnPEAlDmSQAhttps://www.typescriptlang.org/play/#code/KYOwrgtgBAwg9gGzgJygbwFBSgJWAEwBosoBxZYUY7AIQTGGIF8MFgAXKAYwC5ZEUUALz8kyAHTlKIANxAhttps://www.typescriptlang.org/play/#code/KYOwrgtgBAwg9gGzgJygbwFBSgJWAEygF4oBGAGiygHFlhRLsAhBMYSgXwwWABcoAxgC5YiFMVFJkAOlr0QAbiAhttps://www.typescriptlang.org/play/#code/KYOwrgtgBAwg9gGzgJygbwFBSgJWAEygF4oBGAGiygHFlhRioAmS7AIQTGEYBZKBfDAmAAXKAGMAXLEQpG8JMgB0teiADcQAhttps://www.typescriptlang.org/play/#code/KYOwrgtgBAwg9gGzgJygbwFBSgJWAEygF4oBGAGiygHFlhRLsAhBMYSgXwwWABcoAxohQA5AIYRgALigBnXsgCWIAObFYw5AG0ATAF0A3BgwB6E1AAii2QAcEYgJ6yoAclr0QLjEJCzEwADokFQAKISRkcUkASgMgAhttps://www.typescriptlang.org/play/#code/DYUwLgBAdg9mDKBXATiAXBRUDWsDuUEAvBACwDcAULAiiMRAEQC2AhgJ4BG9rEAzmGQBLKAHMIIgSFYATRlUoB6RRADyAaQA0EGSABmIoWBDB2EXpxgxQrKNThJUDPa2B8Q5IAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGY1vVnnsAoAE0gGMAbAQ2klDLgDtEAXUAWyoE8AjSVAK6MA1ozgB3RgG5CIUAHJOvSPPpwBFYqD6gqoVtACWjAOYAaUHB4Arciws84cCpCqMLQ0gDNjkYhYRLFgALGFAWLgAHSERCBmY2KgA5AXY+aFRGVPTQAF4Obj4ZQkMvUAAKJR1cmvDoAUgASlAAb0JQUDkAFSjIAGUyI0i2UQlEcOCqNiq6Q3G9R2dXRlAxcXa1BN0AIScXN1RF-ZX8mZkOuT64C0M2MjcxNh09A2MTDfjWXT6WI1NUV6mPIFZQyAC+hBKZXKEWicDKMzytQARICTMjmm0LmAetEBkMRmtxiEpiCdHNdPpfm8PkwvlQfn8TADqUDToVIOdOmArjc7g84E86As9staVsqLslgdtKK3MCzoQwUAhttps://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwHMQMA1KCZEACgGsQBPALngGcMYtUCBKZqVegG4AUAHpR8APIBpADTw4GZDHwA3cpXg5E8AORFSGkLvhYW8VDgzwwAC3B1gwsHjat2zNhy7wAvIWIyCmoAIgBbegBldk4CEO5BIAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYDsBGAUADaQAuoBccikBAngCo0AOkAJqgIYB2NoAvKABYA3HhCgA8gGkANKACWAMwCSxAKIAPOYmKJQAWzkBzABalIm7aHaloAV07E5eyIQpVaDZiwB0ilRq0dAAoAShExKVliOAAxOXVWUHNA3SCAI1tSYmNIUABjOD1GOSJoUBY4SEROAHJSPJy8gGsQ10pqeiZWb2i4hJZQkUISUG1oOTziDy62UHsmzjgAd04+QRExianOrx7Y+NZBoAhttps://www.typescriptlang.org/play/#code/DYUwLgBMD20M4mATwCpIA4gCYC4IEMA7JCAXggG8BfAbgChRIsypYFk1MsA6fbgI24BjblnoB6cRAgA9APxAhttps://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAdwIYCcwFUDOBTdACgEoAuRANzhgBNEBvAKEUQgRzgBs8A6TuAOaEARABUAFjByIpiALYBPFBjAwwA+Xhw5UAvMOIBuRgF8gAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDZ7SgCuAdmZJgEbFoBuA9vACagC85Fbe68CnjYBuAiFAB5ANKh46UAAMAtMpgJkAOTLZsAYQAWeRAGtIiuZFAVmpAObxGeCgUrU6xLtZ3YRQAhttps://www.typescriptlang.org/play/#code/PTAEDkHsBdQWwK4GMAWoCmAbAzu0B3PJAQwDtRjtsBLAc3OklGhXV1ADdiAna4gI0xsAhACghsBAC5QCUgBN0AM2ql080AF5ZC5avUBucelikZpBJkxbQFqwaAhttps://www.typescriptlang.org/play/#code/PTAEDEFcDsGMBcCWB7aoBOBTel3UdAOajSYBum6oAtpAM7wnKMAWAhhaGxpm7OwCMANplCZoAE1AAHZAXgAoAGYwEKNJXTJ0ACmqY6dNoUwAuUA3QFCASnOkKVAN4LQoeCy0B3Eph8BRdC1dfUNjTBsAbgUAXwUFEFAASWglTUwpLBw8dwBPaVFEOl9HZVUkVFAlNkQhHRtQFzcs3A0g7R0AIgBlZH0PayqakQlOqNj4xKg4CrQWvEGHShp6RmhmUHZObiw+QRExSRk5aEUVGfVQAiUCRHhMABlkZGl6+3JlptAvFlrRHXg6EgEUacRiQAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUACaQDGANgIbSSgBmArgHbEAuAlnA6MVec5ABRxUcAEYArEs1AAfUAzqlSASlQA3OKwIBuPHhCgA8gGk83SLwEBvUAAd4N1AAZQAXyU6zF-vMXvTPPn5GIhpWBkgCd1B9ACVIAFsEkRgAGlBgyFDwglBWRDk4KXJQRDoRZgBPG2o4GjkFUl1PQKw0P2aBACJEZmgwgHNO9oCBGnJSREh3IAhttps://www.typescriptlang.org/play/#code/DYUwLgBAzg9gtiAagQ2AVxALgmgdga1xgHdcIBeCAIjAAsBLKCRiZaMAJ3twHMqBuAFCDQkKJwAyIXnWy40cAEYgOFCAApYCFOhCsm4rrwCUAOlAza-IAhttps://www.typescriptlang.org/play/#code/DYUwLgBAzg9gtiAagQ2AVxALgmgdga1xgHdcIBeCAIjAAsBLKCRiZaMAJ3twHMqBuAFCDQkKJwAyIXnWy40cAEYgOFCAAoAPOK68AfLAQp0IAJQA6UDNr8gAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYME4BQAzAVwDsBjAFwEs5jRpIA3GRSAChVAGVzpLiBzAJSpuvAaADeuUHUjlC0WogB0iAA4AbSuVYAiXYOX0mSNoYBWcPnoMBuXAF9cuY8za6AFpA0a4oAO4IGgAmdkAhttps://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAJwKYDdXIM6oBTYBci2UyMYA5gJTGnlWIDeAUIiqlCMktgHTYADgBsYUPACIJ1Pmkw58MgFZwKk6QG4WAXxYs5WXJIAWqYcLiIA7nGTCAJpqA

  • stringtorefertothesetextualdatatypes.JustlikeJavaScript,TypeScriptalsousesdoublequotes(")orsinglequotes(')tosurroundstringdata.

    letcolor:string="blue";color='red';

    Youcanalsousetemplatestrings,whichcanspanmultiplelinesandhaveembeddedexpressions.Thesestringsaresurroundedbythebacktick/backquote(`)character,andembeddedexpressionsareoftheform${expr}.

    letfullName:string=`BobBobbington`;letage:number=37;letsentence:string=`Hello,mynameis${fullName}.

    I'llbe${age+1}yearsoldnextmonth.`;

    Thisisequivalenttodeclaringsentencelikeso:

    letsentence:string="Hello,mynameis"+fullName+".\n\n"+"I'llbe"+(age+1)+"yearsoldnextmonth.";

    Array

    TypeScript,likeJavaScript,allowsyoutoworkwitharraysofvalues.Arraytypescanbewritteninoneoftwoways.Inthefirst,youusethetypeoftheelementsfollowedby[]todenoteanarrayofthatelementtype:

    letlist:number[]=[1,2,3];

    Thesecondwayusesagenericarraytype,Array:

    letlist:Array=[1,2,3];

    Tuple

  • Tuple

    Tupletypesallowyoutoexpressanarraywithafixednumberofelementswhosetypesareknown,butneednotbethesame.Forexample,youmaywanttorepresentavalueasapairofastringandanumber:

    //Declareatupletypeletx:[string,number];//Initializeitx=["hello",10];//OK//Initializeitincorrectlyx=[10,"hello"];//Error

    Type'number'isnotassignabletotype'string'.Type'string'isnotassignabletotype'number'.

    Whenaccessinganelementwithaknownindex,thecorrecttypeisretrieved:

    //OKconsole.log(x[0].substring(1));

    console.log(x[1].substring(1));

    Property'substring'doesnotexistontype'number'.

    Accessinganelementoutsidethesetofknownindicesfailswithanerror:

    x[3]="world";

    Tupletype'[string,number]'oflength'2'hasnoelementatindex'3'.

    console.log(x[5].toString());

    Objectispossibly'undefined'.Tupletype'[string,number]'oflength'2'hasnoelementatindex'5'.

    Enum

    AhelpfuladditiontothestandardsetofdatatypesfromJavaScriptistheenum.AsinlanguageslikeC#,anenumisawayofgivingmorefriendlynamestosetsofnumericvalues.

    enumColor{Red,

  • Green,Blue,}letc:Color=Color.Green;

    Bydefault,enumsbeginnumberingtheirmembersstartingat0.Youcanchangethisbymanuallysettingthevalueofoneofitsmembers.Forexample,wecanstartthepreviousexampleat1insteadof0:

    enumColor{Red=1,Green,Blue,}letc:Color=Color.Green;

    Or,evenmanuallysetallthevaluesintheenum:

    enumColor{Red=1,Green=2,Blue=4,}letc:Color=Color.Green;

    Ahandyfeatureofenumsisthatyoucanalsogofromanumericvaluetothenameofthatvalueintheenum.Forexample,ifwehadthevalue2butweren'tsurewhatthatmappedtointheColorenumabove,wecouldlookupthecorrespondingname:

    enumColor{Red=1,Green,Blue,}letcolorName:string=Color[2];

    //Displays'Green'console.log(colorName);

    Unknown

  • Wemayneedtodescribethetypeofvariablesthatwedonotknowwhenwearewritinganapplication.Thesevaluesmaycomefromdynamiccontent–e.g.fromtheuser–orwemaywanttointentionallyacceptallvaluesinourAPI.Inthesecases,wewanttoprovideatypethattellsthecompilerandfuturereadersthatthisvariablecouldbeanything,sowegiveittheunknowntype.

    letnotSure:unknown=4;notSure="maybeastringinstead";

    //OK,definitelyabooleannotSure=false;

    Ifyouhaveavariablewithanunknowntype,youcannarrowittosomethingmorespecificbydoingtypeofchecks,comparisonchecks,ormoreadvancedtypeguardsthatwillbediscussedinalaterchapter:

    declareconstmaybe:unknown;//'maybe'couldbeastring,object,boolean,undefined,orothertypesconstaNumber:number=maybe;

    Type'unknown'isnotassignabletotype'number'.

    if(maybe===true){//TypeScriptknowsthatmaybeisabooleannowconstaBoolean:boolean=maybe;//So,itcannotbeastringconstaString:string=maybe;

    Type'boolean'isnotassignabletotype'string'.}

    if(typeofmaybe==="string"){//TypeScriptknowsthatmaybeisastringconstaString:string=maybe;//So,itcannotbeabooleanconstaBoolean:boolean=maybe;

    Type'string'isnotassignabletotype'boolean'.}

    Any

    Insomesituations,notalltypeinformationisavailableoritsdeclarationwouldtakeaninappropriateamountofeffort.Thesemayoccurforvaluesfromcode

  • thathasbeenwrittenwithoutTypeScriptora3rdpartylibrary.Inthesecases,wemightwanttoopt-outoftypechecking.Todoso,welabelthesevalueswiththeanytype:

    declarefunctiongetValue(key:string):any;//OK,returnvalueof'getValue'isnotcheckedconststr:string=getValue("myString");

    TheanytypeisapowerfulwaytoworkwithexistingJavaScript,allowingyoutograduallyopt-inandopt-outoftypecheckingduringcompilation.

    Unlikeunknown,variablesoftypeanyallowyoutoaccessarbitraryproperties,evenonesthatdon'texist.ThesepropertiesincludefunctionsandTypeScriptwillnotchecktheirexistenceortype:

    letlooselyTyped:any=4;//OK,ifItExistsmightexistatruntimelooselyTyped.ifItExists();//OK,toFixedexists(butthecompilerdoesn'tcheck)looselyTyped.toFixed();

    letstrictlyTyped:unknown=4;strictlyTyped.toFixed();

    Objectisoftype'unknown'.

    Theanywillcontinuetopropagatethroughyourobjects:

    letlooselyTyped:any={};letd=looselyTyped.a.b.c.d;//^=letd:any

    Afterall,rememberthatalltheconvenienceofanycomesatthecostoflosingtypesafety.TypesafetyisoneofthemainmotivationsforusingTypeScriptandyoushouldtrytoavoidusinganywhennotnecessary.

    Void

    voidisalittleliketheoppositeofany:theabsenceofhavinganytypeatall.Youmaycommonlyseethisasthereturntypeoffunctionsthatdonotreturnavalue:

  • functionwarnUser():void{console.log("Thisismywarningmessage");}

    Declaringvariablesoftypevoidisnotusefulbecauseyoucanonlyassignnull(onlyif--strictNullChecksisnotspecified,seenextsection)orundefinedtothem:

    letunusable:void=undefined;//OKif`--strictNullChecks`isnotgivenunusable=null;

    NullandUndefined

    InTypeScript,bothundefinedandnullactuallyhavetheirtypesnamedundefinedandnullrespectively.Muchlikevoid,they'renotextremelyusefulontheirown:

    //Notmuchelsewecanassigntothesevariables!letu:undefined=undefined;letn:null=null;

    Bydefaultnullandundefinedaresubtypesofallothertypes.Thatmeansyoucanassignnullandundefinedtosomethinglikenumber.

    However,whenusingthe--strictNullChecksflag,nullandundefinedareonlyassignabletounknown,anyandtheirrespectivetypes(theoneexceptionbeingthatundefinedisalsoassignabletovoid).Thishelpsavoidmanycommonerrors.Incaseswhereyouwanttopassineitherastringornullorundefined,youcanusetheuniontypestring|null|undefined.

    Uniontypesareanadvancedtopicthatwe'llcoverinalaterchapter.

    Asanote:weencouragetheuseof--strictNullCheckswhenpossible,butforthepurposesofthishandbook,wewillassumeitisturnedoff.

    Never

  • Never

    Thenevertyperepresentsthetypeofvaluesthatneveroccur.Forinstance,neveristhereturntypeforafunctionexpressionoranarrowfunctionexpressionthatalwaysthrowsanexceptionoronethatneverreturns.Variablesalsoacquirethetypeneverwhennarrowedbyanytypeguardsthatcanneverbetrue.

    Thenevertypeisasubtypeof,andassignableto,everytype;however,notypeisasubtypeof,orassignableto,never(exceptneveritself).Evenanyisn'tassignabletonever.

    Someexamplesoffunctionsreturningnever:

    //Functionreturningnevermustnothaveareachableendpointfunctionerror(message:string):never{thrownewError(message);}

    //Inferredreturntypeisneverfunctionfail(){returnerror("Somethingfailed");}

    //FunctionreturningnevermustnothaveareachableendpointfunctioninfiniteLoop():never{while(true){}}

    Object

    objectisatypethatrepresentsthenon-primitivetype,i.e.anythingthatisnotnumber,string,boolean,bigint,symbol,null,orundefined.

    Withobjecttype,APIslikeObject.createcanbebetterrepresented.Forexample:

    declarefunctioncreate(o:object|null):void;

    //OKcreate({prop:0});create(null);

  • create(undefined);//Remember,undefinedisnotasubtypeofnull

    Argumentoftype'undefined'isnotassignabletoparameteroftype'object|null'.

    create(42);

    Argumentoftype'42'isnotassignabletoparameteroftype'object|null'.create("string");

    Argumentoftype'"string"'isnotassignabletoparameteroftype'object|null'.create(false);

    Argumentoftype'false'isnotassignabletoparameteroftype'object|null'.

    Generally,youwon'tneedtousethis.

    Typeassertions

    Sometimesyou'llendupinasituationwhereyou'llknowmoreaboutavaluethanTypeScriptdoes.Usually,thiswillhappenwhenyouknowthetypeofsomeentitycouldbemorespecificthanitscurrenttype.

    Typeassertionsareawaytotellthecompiler"trustme,IknowwhatI'mdoing."Atypeassertionislikeatypecastinotherlanguages,butitperformsnospecialcheckingorrestructuringofdata.Ithasnoruntimeimpactandisusedpurelybythecompiler.TypeScriptassumesthatyou,theprogrammer,haveperformedanyspecialchecksthatyouneed.

    Typeassertionshavetwoforms.

    Oneistheas-syntax:

    letsomeValue:unknown="thisisastring";

    letstrLength:number=(someValueasstring).length;

    Theotherversionisthe"angle-bracket"syntax:

    letsomeValue:unknown="thisisastring";

    letstrLength:number=(someValue).length;

    Thetwosamplesareequivalent.Usingoneovertheotherismostlyachoiceof

  • preference;however,whenusingTypeScriptwithJSX,onlyas-styleassertionsareallowed.

    Anoteaboutlet

    Youmayhavenoticedthatsofar,we'vebeenusingtheletkeywordinsteadofJavaScript'svarkeywordwhichyoumightbemorefamiliarwith.TheletkeywordisactuallyanewerJavaScriptconstructthatTypeScriptmakesavailable.YoucanreadintheHandbookReferenceonVariableDeclarationsmoreabouthowletandconstfixalotoftheproblemswithvar.

    AboutNumber,String,Boolean,SymbolandObject

    ItcanbetemptingtothinkthatthetypesNumber,String,Boolean,Symbol,orObjectarethesameasthelowercaseversionsrecommendedabove.Thesetypesdonotrefertothelanguageprimitiveshowever,andalmostnevershouldbeusedasatype.

    functionreverse(s:String):String{returns.split("").reverse().join("");}

    reverse("helloworld");

    Instead,usethetypesnumber,string,boolean,objectandsymbol.

    functionreverse(s:string):string{returns.split("").reverse().join("");}

    reverse("helloworld");

    https://www.staging-typescript.org/docs/handbook/variable-declarations.html

  • InterfacesOneofTypeScript'scoreprinciplesisthattypecheckingfocusesontheshapethatvalueshave.Thisissometimescalled"ducktyping"or"structuralsubtyping".InTypeScript,interfacesfilltheroleofnamingthesetypes,andareapowerfulwayofdefiningcontractswithinyourcodeaswellascontractswithcodeoutsideofyourproject.

    OurFirstInterface

    Theeasiestwaytoseehowinterfacesworkistostartwithasimpleexample:

    functionprintLabel(labeledObj:{label:string}){console.log(labeledObj.label);}

    letmyObj={size:10,label:"Size10Object"};printLabel(myObj);

    ThetypecheckerchecksthecalltoprintLabel.TheprintLabelfunctionhasasingleparameterthatrequiresthattheobjectpassedinhasapropertycalledlabeloftypestring.Noticethatourobjectactuallyhasmorepropertiesthanthis,butthecompileronlychecksthatatleasttheonesrequiredarepresentandmatchthetypesrequired.TherearesomecaseswhereTypeScriptisn'taslenient,whichwe'llcoverinabit.

    Wecanwritethesameexampleagain,thistimeusinganinterfacetodescribetherequirementofhavingthelabelpropertythatisastring:

    interfaceLabeledValue{label:string;}

    functionprintLabel(labeledObj:LabeledValue){console.log(labeledObj.label);}

    letmyObj={size:10,label:"Size10Object"};

    https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABABwE4zFAMgQwEYCmANgBRH7EEAmA8ngFYBciA3ouYUcwM5TpgBzRAF8AlKwBQiRBATc4RAgDoicAWQqLaDFZtEBuCcIkTFURAFsAnnXqIAvK0TcYALwLMAjAAYANO01mACIAZTcCRB9EWwJoIJFDNAxsTRJrWwMgAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgDJwEYQDYQCYBqc2ArigN4BQyy2mOAXMgM5hSgDmA3JQL6WUYJEAjDAA9iGQAHduHRZsACjqL8AeQwArJgpz4ipCAEpkVGgknNxuAHTZxHFfVx5NW+y+M9+lXGGQAWwBPd2QAXjMWYAAvCCYARgAGABpaFyYAIgBlWJRk5HcIUUzkXh5ZUDA9ZRD3byAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoEcCucoQMID2IMwA5sgN4BQyyCBANgVAPwBcyAzmFKKQNw1kAd2AATMAAt2yEJgC2AI2iCAvlSoxMIBGGBE6uOJAzZcACnrEyHUznxESpAJQcKdRsw7deIAcns4DjklaGRVSiEGCDBZCGE7XGQAXkoPJigOACJhSWBILIAaAKMOAEYABgrwwVpgGGRLRzIAOnoM50jaWhB4xIg2zygUj2tSQYza8KF6xqsnFtEJSU7qbriErHsWwJH51qWpZAAqUYXDySn1WlwwTCgQDf61DWjY+QBPfr2jEy2LdztLzILKKBiIADWWXCzn4QAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYMEYBQBLAOwBcYAzAQwGNJQBlARwFcLpIBhOQs-Ac1ADeuUKCpwANggD8qRMWhFeAbmGgA7vgAmxABYzQhJgFsARjBUBfXLjJNCVYvi6i2FUoxZsAFGO59UHqwcXDy8AJSoAqISCLLyikqgQRSohqYwoBaCquKQxAaQaoFsoAC8gtGS0KgARGo6+KQ1ADRJrqjYAAydmSoi+GSgPiF8AHRUVWHZIiIgoACisLGgAArwAA4wxACeoADkEwh7oJpwkIgGcPmQAB74cqDOO5v7xcF+vHuqIoSFb+MxaBlaIfcZVPqZVQDIa+UKjDTaHRTIQzApFZhBUbJYGwsYI3SgABUILh+J0EKsIjYxCY0EIaLelmsuXyRm2bxxrncGO8UTEVVqJnE1AA1jVMmElEAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgAoHtRmQbwFDLJQRwAm6IANgJ7IAeAXMiAK4C2ARtANwFEnkqtak1aceeAL5Ahttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYAsAGAUAJYB2ALjAGYCGAxpKAApzEmgDeeoo0klAJnEQA2AT1AAPVEQCuAWwBGMANwcuPfkNHDJshdGUBfPCFABaM9SkkzJvIMgsADgEZUjZqAC8bcaic4ANKBa6Dig+srOAHRinqAYiqDGMPDQAIRAAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYAsb0GY8BOdbABlCwEZSsAoAG0gBdQBDVAOwFcBbAIxgBtALqgAvKEGUANOll5ZWYQG4GzUPFQAlSKwAmcDvQCeAQVitjAHm78YAPnFtVteINKiJlNMtAhQMPDQAISucAB0AA5ciAAWABQYAJS+-oEIofDhjBwA5kyxTtSkqWDpIbSsTvClAbAZQAhttps://www.typescriptlang.org/play/#code/DYUwLgBAhgXBB2BXAtgIxAJwNoF0IF4IsBGAGggCZyBmcgFhwG4AoUSDAezgCUQoATDvGABPAIIYMUEQB4kaTAD4C0FsygrO0AM4IU6bEyAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWdB2DATgCgBLAOwBcYAzAQwGNJQBlARwFd7pIBhOBVpkA5qADeJUKEZwANggD8qRFWiURAbimgA7mQAmVABbLQFTgFsARjG0BfEiVqcKjKmUEze9Gh268ABSyQqKo-jz8gsIiAJSo4jLyCCpqGpqgkfSoFjYwoPYSOrxUnNAURdLSsgrQqCExAHQ1CKAAPm2gAES8Bl0ANDrSWfXRoo36RsagikmhIhOGJqAAVHNNk8uoaAAMg9L2Dk5ykFSglgCeEbygALzekL6Q15CBiS1lqD2Qff16S8ZUABGHY7AqxTRAAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWdB2DATgCgBLAOwBcYAzAQwGNJQBlARwFd7pIBhOBVpkA5qADeJUKEZwANggD8qRFWiURAbimgA7mQAmVABbLQFTgFsARjG0BfEiVqcKjKmUEze9Gh268ABSyQqKo-jz8gsIiAJSo4jLyCCpqGpqgkfSoFjYwoPYSOrxUnNAURdLSsgrQqCExAHQ1CKAAPm2gAES8Bl0ANDrSWfXRoo36RsagikmhIhOGJqAAVHNNk8uoaAAMg9L2DiQgoAC054ycVOenJHKQVKCWAJ4RvKAAvN6QvpBvkIFEi0yqgepA+v09EtjKgAIw7HYFWKaIAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWdB2DATgCgBLAOwBcYAzAQwGNJQBlARwFd7pIBhOBVpkA5qADeJUKEZwANggD8qRFWiURAbimgA7mQAmVABbLQFTgFsARjG0BfEiVqcKjKmUEze9Gh268ABSyQqKo-jz8gsIiAJSo4jLyCCpqGpqgkfSoFjYwoPYSOrxUnNAURdLSsgrQqCExAHQ1CKAAPm2gAES8Bl0ANDrSWfXRoo36RsagikmhIhOGJqAAVHNNk8uoaAAMg9L2DiQgoAC054ycVOenJHKQVKCWAJ4RvKAAvN6QvpBvkIFEptjKgAIw7PagOAAByYZCoz1QO0aeEK9EQbC4kQE81imiAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoEcCucoQMID2IMwA5sgN4BQyyCBANgVAPwBcyAzmFKKQNw1kAd2AATMAAt2yEJgC2AI2iDaAbQAOUAhoByceRA7deIUgF0OcEAE9BAXyAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoEcCucoQMID2IMwA5sgN4BQyyCBANgVAPwBcyAzmFKKQNw1kAd2AATMAAt2yEJgC2AI2iDaAbQAOUAhoByceRA7deIUgF0OcEAE9BAXypUYmEAjDAidXHEgZsuAAU9MRkHP44+EQkpACUHBR0jMzGPHz8yJFwHHJK0Mj2lEK4YJhQIEW0tPRMUBwhMQB0NczIAD5tyABEuGJdADRCtFn10WSNohKSyCxJoaQT4lLIAFRzTZPLHABMAAyDtPYOVAD0J8gAtFcImGBXF1QMEGBcWJEA8hoeRJzIALyUJJMMocHoQPr9ERLSQcACMu12BUETxe8hsEVw-28EF8EAxEECnDeuE+3xAnFi-CAAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYME4BQBLAOwBcYAzAQwGNJQBlARwFcLpIBhOQs-Ac1ADeuUKCpwANggD8qRMWhFeAbmGgA7vgAmxABYzQhJgFsARjBUBfXLjJNCVYvi6i2FUoxZsAFGO59UHqwcXDy8AJSoAqISCLLyikqgQRSohqYwoBaCqmzETNCE2SIiYpLQqL6hAHSlCKAAPvWgAERsms0ANKoiyRUhfFUa2jqgUtF+vINauqAAVOPVQzOoaAAMXSIWlrggoAC0B1RMxAd7uOKQxKCIzEEA8gAOjlyIoAC8gtGS+aitkO2ZFQXK5GACegTY7xckDckAhkC8N08kEez0IiDCSiAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoTlBALAYgVxAWQG8AoZZACgGcB7fLCALmRrClAHMAaN-AEaoO3Vu04guASlYC6dADYYQAbjIBfIAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoTlBALAYgVxAWQG8AoZZACgGcB7fLCALmRrClAHMAaN-AEaoO3Vu04guASlYC6dADYYQAbjIBfMgHotyALQGE+MAb1klYZAFsAnukw5W9rHkII1ZW85zIAvMhg3MGA6EGp6RiQxEUk+GkFhCS5opJlkOUVlUgpkC2QoCHiFS38IpgA6GgwXWgSY6TVKArBGMIKiywA+fQBGNXUVIAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoTlBALAYgVxAWQG8AoZZACgGcB7fLCALmRrClAHMAaN-AEaoO3Vu04guASlYC6dADYYQAbjIBfMgHotyALQGE+MAb1klYZAFsAnukw5W9rHkII1ZW85zIAvMhg3MGA6EGoaLDERST4aQSiJaVl5JTgw8koLZCgIOIVLfwiEADoaDBdaQSk1ShywRjCcvMsAPn0ARjV1FSAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoTlBALAYgVxAWQG8AoZZACgGcB7fLCALmRrClAHMAaN-AEaoO3Vu04guASlYC6dADYYQAbjIBfMgHotyALQGE+MAb1klYZAFsAnukw5W9rHkII1ZW85zIAvMhg3MGA6EGoaLD4aQSlSCmQLZCgIaIVLfwiEADoaDBdaGLVKZLBGMOTUywA+fQBGNXUVIAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGY1oFAEsA7AFxgDMBDAY0lAGVJzpKALAMQFcDLQBvHUUAApEcdk0ipERaIQDmAGlCJ2AI1rS5kjQVkBKVCrhwANgwIBuHAF8cIUAFpHldkUf2cpoqAC2AT3qMLKgBTGyclJY4fiEsoAC8oKThRHhwBEKITIrKKrq8-KCeoNCQysZeCZmUAHSIDKHCqrqWAiVEYukARFIyOp2WVuZAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMpiqA5gQSlOAT2QG8AoZZAbVABMIAPALmRAFcBbAI2gF0WAzhmwBuMgF8yZADYQwyDoTwFCLdJhC58RMYuVFkAXmoAiAEIB7LiYA0yEwDEoEWid5iZchYXWDhmo299QioABncgAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwBYCMBmAUCBIgC7QCWAxsQArwAOMxAngJIB2ZxZAhgDZkAvblzhtUAMz6JIeMm2IxJFSKACCHALZ9QAbzyhQbbhsioS5NgHMA3HgC+eWfMXdloACJxLoSAA8FbAAmiGqa2noGAEbQkJCBZqRyNvaOhACisAiocoF+SaAA7pwAFqDchgCuJuQUoOb5GmSWxcSglpCtTHAVZaAUcBp0vB2QvEx1kHTc0MIqzAygcOKhZFq8AIROCtBKKgBycMQA8gDW3OMRoADavqhsVZEwALqo6qt8tgY3CRaWLx5eWx2IAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwBYCMWBQBLAOwBcYAzAQwGNJQA5AVwFsAjGAEXyuPzkIugBPUAG9coUAG0iAE0gAPVImLQiAcwC6qQszbQA3ONAAbSITXEAFtt0x9oEKDgBrADQmzFy6HyJQFUB1WGCN+JkglFXV7Rxh4aHcrWmJBAAdaODJQAHIwyGyfP0I4Yn9QRAYWFPSnLKSfQjl5EIBfIAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgHIFcC2AjaB5KAZTClAHMARYBMYAexDigE9kBvAKGWQG1QATCAA8AXMgDOJcgF0xILLijIAPhKkgyAbi7IANhA1gAFnIXRNyAPSXkdANYAaPQbLHkwccjjJ5OaDsZMCDFJUg0La1tHHzgg909vUPIOAF8gAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYAsaBQBLAOwBcYAzAQwGNJQAlSCgEzkIBsBPAZWOiIHMAgrAodQAb1yhQ0Ri3ZiA2kSaQAHqkIBXALYAjGAF1UiXgIDcuAL65cbSMVA6Ow6KNQNmrTjz6EhImIAvKCKAESCbPg0YQA0oGEAQnB6YYaWzq6iimiGoCFhALIUbGwIHGHmoCCgMPDQAIRAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMIBsD2CDWBJcaeJZAbwChlkEBXKKCcAFWAFsIAuZAETkgG5yAX3LkE6OAGdJaLLmRsADugjtwMjNnyFYiFBSq16jMC3ZdekZAF5kICAHcefCAAoAlIMOYQksFBoEMEwoVwALLhAaVgAjaAAaZFZI6LiodzIRISAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0AKsD2AHApraBPASQDt5p4BDAG3gC8Lz1iAuUAM2smwCh5jpcHRNlABhKukQBrEgNhCRAb26hQiAK6xY2fgBV4AW2ysAIg2wBuFaC7R9RgBQATU+YCUrAG7p4TqwF9ubkQqCkhIMQlpUENMKmwjfgjxSRl+QQphUGVVDS0dO0NjUDMBUABeUGJsAHcS8wc3K1Vbe2xnVwE3bOtVaAALeEgAOjztPSKK0D9rQNymGFh1ZHRYB37WYnUDACNcABpQA03tvdhuxUD-IAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygOwAYCMBmUAmAFnwwIFYA2QgKBAkQBdoBLAYwYAV4AHGBgTwCSAO2YNmAQwA2zAF4TxcYagBm0xJFphwwuIIC23GazEBBYf1XrNzYQxhrWkUAGEpcVgGsXSxtACu7AigAN7UoKDCkADuoAAUABZw-tCowv76AEYwADSg+rb+9mkZ2dAAlADc1AC+1NSsUhKIiK7uXqDMhlKQ+pB2rW4e3r5MgQzBYRGsKdD9DAAqXZCoACIKkNXTowFB0IklWbn5h2XloXU1QAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMIBsD2CDWrMgDOYUArgmJlMgN4BQyyIEA7sgBQAWmpUAXE1IBbAEbQANMiGhSkASGFioASgEZsOAJLho8JAG46AXzp1QkWIhTrc2i3pT1GYYLnarkAN0zAAJoZM6GFIQCmACZAQoCDhIGxx2BkjKfjQsXHwiEnIU8STuXnlFCSTpBTlBUWg6D3i7XStaJOiwXhAmVmSqLh4oSTLZCGUA0wR0OEJCZAARYABzYDA4dHjkYCEAB3QIIQhwKbqdSyQmxgQCYjIKbs4iqr6pO6VlWhNnVwSXp0ZIi8xtgB0WDm7AARGIIBtkBCNqDhkkTIExhMpgBBEDLTBzVbrLY7PZgA7pLRHBynX5ZK4pLhPCSPSrPV5JFxuL5JM5-QHAsEsnDISi4OGGRiI0zbMDIXzzRbLZAAXki0ViEHi7FmCyWK2JkgAjAAmXUAdnh4uQcAxwPlipicWJ7HRmOx2uQhskAGY9cMgAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0AKsD2AHApraBPASQDt5p4BDAG3gC8Lz1iAuUAM2smwCgQJj0hALaYaiMgEFi+Vhypdu8YtFwdE2UAGEq6RAGtNTGLACuydLFABvbqFDFsAd1AAKABboTsVsRNCARrgANKBCSiYqPn6BsACUrNq6eiQqsGrYANzcAL7cisqqFOpaOvophcU2duT6LvGgAG7o8AAmWbnciEbQJUkJpQbdpuaWALygiFQUkJC9+qDwIlTYQtjKs4llBWlFGlUTQ2bQFu5RAcGhZzGx1rnVSHp11rZ2B8SQ6MsAdDoA5i4AIkC2EwoGBmABsSydly2Sy3GWPUmSVA4wczk2jwAjAAmEJYgDsUM6Ay+NUeUKAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoAs4AcUG8BQyyCA9gDYlQBcyAzmFKAOYDc+AvvvqJLIiqgCOAVzhQUEAB6QQAE1ppMOZASK1gsiABkIIJmHQ0QwgLYAjaG074yEMHRFiUAXhXtkcBUNHi2tR+IAdKQUUMiuAERmZMIQEX4BEIHqmjp6BuHIAIwADCxAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMoAs4AcUG8BQyyCA9gDYlQBcyAzmFKAOYDc+AvvvqJLIigAUIIVAxIBrPIWQ4QAdWAATMOhogArgFsARtDadu4aPCRoAjurhQUEAB6QQi2mkw4ANMiEixk5ASK0ShAAMsJMKmpaulD6XGQQYHQWVigAvH7syHDOqMnWbLR5EAB0pBRQyOkARNpk6hBVBUXFgYohYSqVyACMAAxNltbFsgrK6F0ArMX9QAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMIHsCu5rIN4BQyyAFAM5hxRgBcyImAtgEbQCUdFUoA5gNxFkoSFABucADZ0GLaAOJQIZCGBIdko9MAAmAgL4ECMbAjDB0IZDxUZsItXVs4o+QRJXIEWZ8gC8yYxBTc0tySmppJlYoNnw9ZDgyNG8ReU8U6AA6YWhxCT9kAEYAJgBmNK87LMVlMALA4ItSWLw9NMUwTChLSud9Q3c6hALrMCd7NgEEEkKABkmCBEyalTUp7Oc8goBWTNm+IAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAMX0BY1dMcAoAYwBsBDRRUAYTgDsAXeC0AbxNFAAdoASwBuVFpFCIWYyKipMAngG4SAXxIlBrGADMqZCQGVIFSGWkAjU41btQkAB7imAEzo22cDt16ITZlgAKAEpUYThBFxV1cmpaUAAhAFcWFmZ7J0hXd2ZPDkEAWz5TAqyWOmNTcyorSA87H0l-cxCudRjKGjoAFUcWBLgHDOc3BlyGniaqoOC2tQ1O+IBJAqoAczrxr1BC4shS1grmy2st70mBERlJaXE5RRVfY9bOdqA

  • printLabel(myObj);

    TheinterfaceLabeledValueisanamewecannowusetodescribetherequirementinthepreviousexample.Itstillrepresentshavingasinglepropertycalledlabelthatisoftypestring.Noticewedidn'thavetoexplicitlysaythattheobjectwepasstoprintLabelimplementsthisinterfacelikewemighthavetoinotherlanguages.Here,it'sonlytheshapethatmatters.Iftheobjectwepasstothefunctionmeetstherequirementslisted,thenit'sallowed.

    It'sworthpointingoutthatthetypecheckerdoesnotrequirethatthesepropertiescomeinanysortoforder,onlythatthepropertiestheinterfacerequiresarepresentandhavetherequiredtype.

    OptionalProperties

    Notallpropertiesofaninterfacemayberequired.Someexistundercertainconditionsormaynotbethereatall.Theseoptionalpropertiesarepopularwhencreatingpatternslike"optionbags"whereyoupassanobjecttoafunctionthatonlyhasacoupleofpropertiesfilledin.

    Here'sanexampleofthispattern:

    interfaceSquareConfig{color?:string;width?:number;}

    functioncreateSquare(config:SquareConfig):{color:string;area:numberletnewSquare={color:"white",area:100};if(config.color){newSquare.color=config.color;}if(config.width){newSquare.area=config.width*config.width;}returnnewSquare;}

    letmySquare=createSquare({color:"black"});

  • Interfaceswithoptionalpropertiesarewrittensimilartootherinterfaces,witheachoptionalpropertydenotedbya?attheendofthepropertynameinthedeclaration.

    Theadvantageofoptionalpropertiesisthatyoucandescribethesepossiblyavailablepropertieswhilestillalsopreventinguseofpropertiesthatarenotpartoftheinterface.Forexample,hadwemistypedthenameofthecolorpropertyincreateSquare,wewouldgetanerrormessagelettingusknow:

    interfaceSquareConfig{color?:string;width?:number;}

    functioncreateSquare(config:SquareConfig):{color:string;area:numberletnewSquare={color:"white",area:100};if(config.clor){

    Property'clor'doesnotexistontype'SquareConfig'.Didyoumean'color'?//Error:Property'clor'doesnotexistontype'SquareConfig'newSquare.color=config.clor;

    Property'clor'doesnotexistontype'SquareConfig'.Didyoumean'color'?}if(config.width){newSquare.area=config.width*config.width;}returnnewSquare;}

    letmySquare=createSquare({color:"black"});

    Readonlyproperties

    Somepropertiesshouldonlybemodifiablewhenanobjectisfirstcreated.Youcanspecifythisbyputtingreadonlybeforethenameoftheproperty:

    interfacePoint{readonlyx:number;readonlyy:number;}

    YoucanconstructaPointbyassigninganobjectliteral.Aftertheassignment,x

  • andycan'tbechanged.

    letp1:Point={x:10,y:20};p1.x=5;//error!

    Cannotassignto'x'becauseitisaread-onlyproperty.

    TypeScriptcomeswithaReadonlyArraytypethatisthesameasArraywithallmutatingmethodsremoved,soyoucanmakesureyoudon'tchangeyourarraysaftercreation:

    leta:number[]=[1,2,3,4];letro:ReadonlyArray=a;

    ro[0]=12;//error!

    Indexsignatureintype'readonlynumber[]'onlypermitsreading.ro.push(5);//error!

    Property'push'doesnotexistontype'readonlynumber[]'.ro.length=100;//error!

    Cannotassignto'length'becauseitisaread-onlyproperty.a=ro;//error!

    Thetype'readonlynumber[]'is'readonly'andcannotbeassignedtothemutabletype'number[]'.

    OnthelastlineofthesnippetyoucanseethatevenassigningtheentireReadonlyArraybacktoanormalarrayisillegal.Youcanstilloverrideitwithatypeassertion,though:

    leta:number[]=[1,2,3,4];letro:ReadonlyArray=a;

    a=roasnumber[];

    readonlyvsconstTheeasiestwaytorememberwhethertousereadonlyorconstistoaskwhetheryou'reusingitonavariableoraproperty.Variablesuseconstwhereaspropertiesusereadonly.

    ExcessPropertyChecks

  • ExcessPropertyChecks

    Inourfirstexampleusinginterfaces,TypeScriptletsuspass{size:number;label:string;}tosomethingthatonlyexpecteda{label:string;}.Wealsojustlearnedaboutoptionalproperties,andhowthey'reusefulwhendescribingso-called"optionbags".

    However,combiningthetwonaivelywouldallowanerrortosneakin.Forexample,takingourlastexampleusingcreateSquare:

    interfaceSquareConfig{color?:string;width?:number;}

    functioncreateSquare(config:SquareConfig):{color:string;area:numberreturn{color:config.color||"red",area:config.width?config.width*config.width:20,};}

    letmySquare=createSquare({colour:"red",width:100});

    Argumentoftype'{colour:string;width:number;}'isnotassignabletoparameteroftype'SquareConfig'.Objectliteralmayonlyspecifyknownproperties,but'colour'doesnotexistintype'SquareConfig'.Didyoumeantowrite'color'?

    NoticethegivenargumenttocreateSquareisspelledcolourinsteadofcolor.InplainJavaScript,thissortofthingfailssilently.

    Youcouldarguethatthisprogramiscorrectlytyped,sincethewidthpropertiesarecompatible,there'snocolorpropertypresent,andtheextracolourpropertyisinsignificant.

    However,TypeScripttakesthestancethatthere'sprobablyabuginthiscode.Objectliteralsgetspecialtreatmentandundergoexcesspropertycheckingwhenassigningthemtoothervariables,orpassingthemasarguments.Ifanobjectliteralhasanypropertiesthatthe"targettype"doesn'thave,you'llgetanerror:

    letmySquare=createSquare({colour:"red",width:100});

    Argumentoftype'{colour:string;width:number;}'isnotassignabletoparameteroftype'SquareConfig'.Objectliteralmayonlyspecifyknownproperties,but'colour'doesnotexistintype'SquareConfig'.Didyoumeantowrite'color'?

    Gettingaroundthesechecksisactuallyreallysimple.Theeasiestmethodistojustuseatypeassertion:

  • justuseatypeassertion:

    letmySquare=createSquare({width:100,opacity:0.5}asSquareConfig

    However,abetterapproachmightbetoaddastringindexsignatureifyou'resurethattheobjectcanhavesomeextrapropertiesthatareusedinsomespecialway.IfSquareConfigcanhavecolorandwidthpropertieswiththeabovetypes,butcouldalsohaveanynumberofotherproperties,thenwecoulddefineitlikeso:

    interfaceSquareConfig{color?:string;width?:number;[propName:string]:any;}

    We'lldiscussindexsignaturesinabit,butherewe'resayingaSquareConfigcanhaveanynumberofproperties,andaslongastheyaren'tcolororwidth,theirtypesdon'tmatter.

    Onefinalwaytogetaroundthesechecks,whichmightbeabitsurprising,istoassigntheobjecttoanothervariable:SincesquareOptionswon'tundergoexcesspropertychecks,thecompilerwon'tgiveyouanerror.

    letsquareOptions={colour:"red",width:100};letmySquare=createSquare(squareOptions);

    TheaboveworkaroundwillworkaslongasyouhaveacommonpropertybetweensquareOptionsandSquareConfig.Inthisexample,itwasthepropertywidth.Itwillhowever,failifthevariabledoesnothaveanycommonobjectproperty.Forexample:

    letsquareOptions={colour:"red"};letmySquare=createSquare(squareOptions);

    Type'{colour:string;}'hasnopropertiesincommonwithtype'SquareConfig'.

    Keepinmindthatforsimplecodelikeabove,youprobablyshouldn'tbetryingto"getaround"thesechecks.Formorecomplexobjectliteralsthathavemethodsandholdstate,youmightneedtokeepthesetechniquesinmind,butamajorityofexcesspropertyerrorsareactuallybugs.Thatmeansifyou'rerunningintoexcesspropertycheckingproblemsforsomethinglikeoptionbags,youmight

  • needtorevisesomeofyourtypedeclarations.Inthisinstance,ifit'sokaytopassanobjectwithbothacolororcolourpropertytocreateSquare,youshouldfixupthedefinitionofSquareConfigtoreflectthat.

    FunctionTypes

    InterfacesarecapableofdescribingthewiderangeofshapesthatJavaScriptobjectscantake.Inadditiontodescribinganobjectwithproperties,interfacesarealsocapableofdescribingfunctiontypes.

    Todescribeafunctiontypewithaninterface,wegivetheinterfaceacallsignature.Thisislikeafunctiondeclarationwithonlytheparameterlistandreturntypegiven.Eachparameterintheparameterlistrequiresbothnameandtype.

    interfaceSearchFunc{(source:string,subString:string):boolean;}

    Oncedefined,wecanusethisfunctiontypeinterfacelikewewouldotherinterfaces.Here,weshowhowyoucancreateavariableofafunctiontypeandassignitafunctionvalueofthesametype.

    letmySearch:SearchFunc;

    mySearch=function(source:string,subString:string):boolean{letresult=source.search(subString);returnresult>-1;};

    Forfunctiontypestocorrectlytypecheck,thenamesoftheparametersdonotneedtomatch.Wecouldhave,forexample,writtentheaboveexamplelikethis:

    letmySearch:SearchFunc;

    mySearch=function(src:string,sub:string):boolean{letresult=src.search(sub);returnresult>-1;};

  • Functionparametersarecheckedoneatatime,withthetypeineachcorrespondingparameterpositioncheckedagainsteachother.Ifyoudonotwanttospecifytypesatall,TypeScript'scontextualtypingcaninfertheargumenttypessincethefunctionvalueisassigneddirectlytoavariableoftypeSearchFunc.Here,also,thereturntypeofourfunctionexpressionisimpliedbythevaluesitreturns(herefalseandtrue).

    letmySearch:SearchFunc;

    mySearch=function(src,sub){letresult=src.search(sub);returnresult>-1;};

    Hadthefunctionexpressionreturnednumbersorstrings,thetypecheckerwouldhavemadeanerrorthatindicatesreturntypedoesn'tmatchthereturntypedescribedintheSearchFuncinterface.

    letmySearch:SearchFunc;

    mySearch=function(src,sub){

    Type'(src:string,sub:string)=>string'isnotassignabletotype'SearchFunc'.Type'string'isnotassignabletotype'boolean'.letresult=src.search(sub);return"string";};

    IndexableTypes

    Similarlytohowwecanuseinterfacestodescribefunctiontypes,wecanalsodescribetypesthatwecan"indexinto"likea[10],orageMap["daniel"].Indexabletypeshaveanindexsignaturethatdescribesthetypeswecanusetoindexintotheobject,alongwiththecorrespondingreturntypeswhenindexing.Let'stakeanexample:

    interfaceStringArray{[index:number]:string;}

    letmyArray:StringArray;

  • myArray=["Bob","Fred"];

    letmyStr:string=myArray[0];

    Above,wehaveaStringArrayinterfacethathasanindexsignature.ThisindexsignaturestatesthatwhenaStringArrayisindexedwithanumber,itwillreturnastring.

    Therearetwotypesofsupportedindexsignatures:stringandnumber.Itispossibletosupportbothtypesofindexers,butthetypereturnedfromanumericindexermustbeasubtypeofthetypereturnedfromthestringindexer.Thisisbecausewhenindexingwithanumber,JavaScriptwillactuallyconvertthattoastringbeforeindexingintoanobject.Thatmeansthatindexingwith100(anumber)isthesamethingasindexingwith"100"(astring),sothetwoneedtobeconsistent.

    interfaceAnimal{name:string;}

    interfaceDogextendsAnimal{breed:string;}

    //Error:indexingwithanumericstringmightgetyouacompletelyseparatetypeofAnimal!interfaceNotOkay{[x:number]:Animal;

    Numericindextype'Animal'isnotassignabletostringindextype'Dog'.[x:string]:Dog;}

    Whilestringindexsignaturesareapowerfulwaytodescribethe"dictionary"pattern,theyalsoenforcethatallpropertiesmatchtheirreturntype.Thisisbecauseastringindexdeclaresthatobj.propertyisalsoavailableasobj["property"].Inthefollowingexample,name'stypedoesnotmatchthestringindex'stype,andthetypecheckergivesanerror:

    interfaceNumberDictionary{[index:string]:number;length:number;//ok,lengthisanumbername:string;//error,thetypeof'name'isnotasubtypeoftheindexer

    Property'name'oftype'string'isnotassignabletostringindextype'number'.}

  • However,propertiesofdifferenttypesareacceptableiftheindexsignatureisaunionofthepropertytypes:

    interfaceNumberOrStringDictionary{[index:string]:number|string;length:number;//ok,lengthisanumbername:string;//ok,nameisastring}

    Finally,youcanmakeindexsignaturesreadonlyinordertopreventassignmenttotheirindices:

    interfaceReadonlyStringArray{readonly[index:number]:string;}

    letmyArray:ReadonlyStringArray=["Alice","Bob"];myArray[2]="Mallory";//error!

    Indexsignatureintype'ReadonlyStringArray'onlypermitsreading.

    Youcan'tsetmyArray[2]becausetheindexsignatureisreadonly.

    ClassTypes

    ImplementinganinterfaceOneofthemostcommonusesofinterfacesinlanguageslikeC#andJava,thatofexplicitlyenforcingthataclassmeetsaparticularcontract,isalsopossibleinTypeScript.

    interfaceClockInterface{currentTime:Date;}

    classClockimplementsClockInterface{currentTime:Date=newDate();constructor(h:number,m:number){}}

  • Youcanalsodescribemethodsinaninterfacethatareimplementedintheclass,aswedowithsetTimeinthebelowexample:

    interfaceClockInterface{currentTime:Date;setTime(d:Date):void;}

    classClockimplementsClockInterface{currentTime:Date=newDate();setTime(d:Date){this.currentTime=d;}constructor(h:number,m:number){}}

    Interfacesdescribethepublicsideoftheclass,ratherthanboththepublicandprivateside.Thisprohibitsyoufromusingthemtocheckthataclassalsohasparticulartypesfortheprivatesideoftheclassinstance.

    DifferencebetweenthestaticandinstancesidesofclassesWhenworkingwithclassesandinterfaces,ithelpstokeepinmindthataclasshastwotypes:thetypeofthestaticsideandthetypeoftheinstanceside.Youmaynoticethatifyoucreateaninterfacewithaconstructsignatureandtrytocreateaclassthatimplementsthisinterfaceyougetanerror:

    interfaceClockConstructor{new(hour:number,minute:number);}

    classClockimplementsClockConstructor{

    Class'Clock'incorrectlyimplementsinterface'ClockConstructor'.Type'Clock'providesnomatchforthesignature'new(hour:number,minute:number):any'.currentTime:Date;constructor(h:number,m:number){}}

    Thisisbecausewhenaclassimplementsaninterface,onlytheinstancesideoftheclassischecked.Sincetheconstructorsitsinthestaticside,itisnotincludedinthischeck.

  • Instead,youwouldneedtoworkwiththestaticsideoftheclassdirectly.Inthisexample,wedefinetwointerfaces,ClockConstructorfortheconstructorandClockInterfacefortheinstancemethods.Then,forconvenience,wedefineaconstructorfunctioncreateClockthatcreatesinstancesofthetypethatispassedtoit:

    interfaceClockConstructor{new(hour:number,minute:number):ClockInterface;}

    interfaceClockInterface{tick():void;}

    functioncreateClock(ctor:ClockConstructor,hour:number,minute:number):ClockInterface{returnnewctor(hour,minute);}

    classDigitalClockimplementsClockInterface{constructor(h:number,m:number){}tick(){console.log("beepbeep");}}

    classAnalogClockimplementsClockInterface{constructor(h:number,m:number){}tick(){console.log("ticktock");}}

    letdigital=createClock(DigitalClock,12,17);letanalog=createClock(AnalogClock,7,32);

    BecausecreateClock'sfirstparameterisoftypeClockConstructor,increateClock(AnalogClock,7,32),itchecksthatAnalogClockhasthecorrectconstructorsignature.

    Anothersimplewayistouseclassexpressions:

    interfaceClockConstructor{

  • new(hour:number,minute:number):ClockInterface;}

    interfaceClockInterface{tick():void;}

    constClock:ClockConstructor=classClockimplementsClockInterface{constructor(h:number,m:number){}tick(){console.log("beepbeep");}};

    letclock=newClock(12,17);clock.tick();

    ExtendingInterfaces

    Likeclasses,interfacescanextendeachother.Thisallowsyoutocopythemembersofoneinterfaceintoanother,whichgivesyoumoreflexibilityinhowyouseparateyourinterfacesintoreusablecomponents.

    interfaceShape{color:string;}

    interfaceSquareextendsShape{sideLength:number;}

    letsquare={}asSquare;square.color="blue";square.sideLength=10;

    Aninterfacecanextendmultipleinterfaces,creatingacombinationofalloftheinterfaces.

    interfaceShape{color:string;}

    interfacePenStroke{penWidth:number;

  • }

    interfaceSquareextendsShape,PenStroke{sideLength:number;}

    letsquare={}asSquare;square.color="blue";square.sideLength=10;square.penWidth=5.0;

    HybridTypes

    Aswementionedearlier,interfacescandescribetherichtypespresentinrealworldJavaScript.BecauseofJavaScript'sdynamicandflexiblenature,youmayoccasionallyencounteranobjectthatworksasacombinationofsomeofthetypesdescribedabove.

    Onesuchexampleisanobjectthatactsasbothafunctionandanobject,withadditionalproperties:

    interfaceCounter{(start:number):string;interval:number;reset():void;}

    functiongetCounter():Counter{letcounter=function(start:number){}asCounter;counter.interval=123;counter.reset=function(){};returncounter;}

    letc=getCounter();c(10);c.reset();c.interval=5.0;

    Wheninteractingwith3rd-partyJavaScript,youmayneedtousepatternsliketheabovetofullydescribetheshapeofthetype.

  • InterfacesExtendingClasses

    Whenaninterfacetypeextendsaclasstypeitinheritsthemembersoftheclassbutnottheirimplementations.Itisasiftheinterfacehaddeclaredallofthemembersoftheclasswithoutprovidinganimplementation.Interfacesinheriteventheprivateandprotectedmembersofabaseclass.Thismeansthatwhenyoucreateaninterfacethatextendsaclasswithprivateorprotectedmembers,thatinterfacetypecanonlybeimplementedbythatclassorasubclassofit.

    Thisisusefulwhenyouhavealargeinheritancehierarchy,butwanttospecifythatyourcodeworkswithonlysubclassesthathavecertainproperties.Thesubclassesdon'thavetoberelatedbesidesinheritingfromthebaseclass.Forexample:

    classControl{privatestate:any;}

    interfaceSelectableControlextendsControl{select():void;}

    classButtonextendsControlimplementsSelectableControl{select(){}}

    classTextBoxextendsControl{select(){}}

    classImageControlimplementsSelectableControl{

    Class'ImageControl'incorrectlyimplementsinterface'SelectableControl'.Typeshaveseparatedeclarationsofaprivateproperty'state'.privatestate:any;select(){}}

    Intheaboveexample,SelectableControlcontainsallofthemembersofControl,includingtheprivatestateproperty.SincestateisaprivatememberitisonlypossiblefordescendantsofControltoimplementSelectableControl.ThisisbecauseonlydescendantsofControlwillhaveastateprivatememberthatoriginatesinthesamedeclaration,whichisarequirementforprivatememberstobecompatible.

  • WithintheControlclassitispossibletoaccessthestateprivatememberthroughaninstanceofSelectableControl.Effectively,aSelectableControlactslikeaControlthatisknowntohaveaselectmethod.TheButtonandTextBoxclassesaresubtypesofSelectableControl(becausetheybothinheritfromControlandhaveaselectmethod).TheImageControlclasshasit'sownstateprivatememberratherthanextendingControl,soitcannotimplementSelectableControl.

  • FunctionsFunctionsarethefundamentalbuildingblockofanyapplicationinJavaScript.They'rehowyoubuilduplayersofabstraction,mimickingclasses,informationhiding,andmodules.InTypeScript,whilethereareclasses,namespaces,andmodules,functionsstillplaythekeyroleindescribinghowtodothings.TypeScriptalsoaddssomenewcapabilitiestothestandardJavaScriptfunctionstomakethemeasiertoworkwith.

    Functions

    Tobegin,justasinJavaScript,TypeScriptfunctionscanbecreatedbothasanamedfunctionorasananonymousfunction.Thisallowsyoutochoosethemostappropriateapproachforyourapplication,whetheryou'rebuildingalistoffunctionsinanAPIoraone-offfunctiontohandofftoanotherfunction.

    ToquicklyrecapwhatthesetwoapproacheslooklikeinJavaScript:

    //Namedfunctionfunctionadd(x,y){returnx+y;}

    //AnonymousfunctionletmyAdd=function(x,y){returnx+y;};

    JustasinJavaScript,functionscanrefertovariablesoutsideofthefunctionbody.Whentheydoso,they'resaidtocapturethesevariables.Whileunderstandinghowthisworks(andthetrade-offswhenusingthistechnique)isoutsideofthescopeofthisarticle,havingafirmunderstandinghowthismechanicworksisanimportantpieceofworkingwithJavaScriptandTypeScript.

    letz=100;

    https://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFAigBymAtngCYYCuAdsvAPb0HoNOuiZVUAUADwA0oAJ4BKUAG8CoULDzRaseqEGgA1OIDcBAL4EiYAIL1WY8s1qQ6jaCzbYlocmJN9QAXjtc1Q0UkZOQUlFTUNbTE9fR0gAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDZ7SgBeoAvKAIwAMdA3AQegK4B2y8A9h6JgAmggCo8AWgAoAHgBpQATwCUoAN4FQoWCTax+00AGpFR8swC+QAhttps://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAQwCaoBQA8BciwgC2ARgKYBOANIgJ54EkUCU9RZ5iA3gFCKLmkoIckiyIA1LQDc3AL7duAG0GJCNAILpEAXkShIsBImytGVWqfYt8bCl179Bw0ROlypQAhttps://www.typescriptlang.org/play/#code/DYUwLgBAtgngggEwQLggCgB6oHYFcoBGIATgDQQw75HECUEAvAHwR6EmMQBmu2AxmACWAe2zoAUBAhZW1EqUkUq7YuNrKaEAN6Li4XMTEYIAagoBucQF9zQAhttps://www.typescriptlang.org/play/#code/DYUwLgBAtgngggEwQLggCgEYEMDOIBqWwAriKgHbFQYgBOANBAJbkDGtIUI5YFVNtAJQQAvAD4IlanVEQAZsTZgmAe3LoAUBAgAPPtIZaIMfQI2DTMgN5GOYYrXU6IAamMBuDQF93QAhttps://www.typescriptlang.org/play/#code/PTAEBUAsFNQBwIYCcEFtoBdpIM6gOQAe+oCAdgCYECeJkCAbrBjKBtXLGQK6oBG2AFAAbTKFTUAghSoBeUADNuZAMYYAlgHsyoABSEAXKB79sAGlDUjJgUgCU13rdABvQaFBJM3JDsKgAaksAbkEAX1DBEHEpGVB6PBZYJWFhRWU1LR12ThExCWkKACYjXT4EHGgANQRhbmhHUyQLdVUvdDIMRts7UFkAPmMnbD701Q1tPUILal63Dy8MHz9AkPDgoAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYMBYBQAzAVwDsBjAFwEs5jQAjQygGwBMA5AQwFtIAKfSknKceqROWiViAcwA0oJh3EjIYiVOkBKUAG9coUNEjlC0WgKErQAalAAiezYVLh3SAG5cAX1y4mxw0hEQiZyAEZQAF56RlYVXjsAITg6O013UBBQGHhoeXI4OFB8SAB3UAAHDmg3chhEPwCjYNC0KJjmdjcE5NT5OwBBFm5EO36AZWgAOjSMrJyEfMLQLg5iAE9K6tr6xvJAlvIAZnaGTviklLH7IZHZzLAOAAt5ACtCcUNKaSfyIAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYMBYBQAzAVwDsBjAFwEs5jQAjQygGwBMA5AQwFtIAKfSknKceqROWiViAcwA0oJh3EjIAfjESp0gJSgA3rlChK+UL0XLukXdEjlC0WgKErQAalAAiL+4VLhVgDchqCQTIiQoLb2jqDOljzBAL64uEx2UZCIhEzkAIygALz0jKwqvJ4AQnB0ntqBoCCgAO4IANaIoKQIthRMAJ6gxHDNaRm22bloRSXM7FYV1bXyngCCLNyInisAytAAdHUNTTDw0PLkcHCgXBzEgwAOHNBW5DCIY+SZk+QAzDMMOblKo1bZedabI6NMAcAAW8gAVoRxFFKNJYeQgAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYMBYBQAzAVwDsBjAFwEs5jQAjQygGwBMA5AQwFtIAKfSknKceqROWiViAcwA0oJh3EjIoALygARAGUulcgAtNASlABvXKFDRI5QtFoChK0AGotH94uXdIAblwAX1xcJltrSERCJnIARnV6RlYVXk0AITg6Ez9QEFAAdwQAa0RQUgQbCiYAT1BiOHz5GzsHUvTM0F19I1DwmyiYtASGZnZfVIys+RIWSAFiSBZjHLzxZiYC4sR5DiZEOAiW4jbJzr1DTV7yCIHyAGZhpLGeCczNeU0AQRZuRHetbTQAB02VyYBg8Gg8nIcAOXA4xFqAAcONBfOQYIgrjdouRsI9Ril2lMtN9fqC8hwDPIAFaEcTWSjSAzkIAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYMBYBQAzAVwDsBjAFwEs5jQAjQygGwBMA5AQwFtIAKfSknKceoALygARAHVmTSQBpQTDomHdIqNdErEA5gEpQAb1yhQ0SOULRaAoSMigA1FLeuVaxwG5cAX1xcJisLSERCJnIARnF6RlZHXkkAITg6SQNvUBBQGHhoJXI4OFB8SAB3UAAHDmgNchhEIJDLcMi0WIZmdg0k1PSlSQBBFm5ERSkAZWgAOgysnLyEQuLQLg5iAE9q2vrG5vJQtvIAZk74np4+tInh0a5xzOywOABrDm2NllDrW0QpfqgEZjSQHI4RcjYc7dRIkFiQATESAsQbAh7zZ6gN4fUBfH42Yj-GRyIH3cZAAhttps://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAIxDANgEwHIEMC2ApgBTAwBOAzlHkQFyLXkxgDmANIgHQ-mHUB5YLUIMmLVgG0AugEpEAbwBQiRHyghySMlRoFCiANSIARKaNr+UISK4ArOC2JmTsgNxKAvkqUB6X4iE+AAO6HAAnoSEIogA7hjoKAYmAFJwlITBABaIAMoEIISJADIgELiUiACyuBAA0iwAXjCEJkrohFCBIWGR0fqIALwoaFgizmkZ2SacJvn4hegzpqXllMsmNfVNLa5uQAhttps://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAIxDANgEwHIEMC2ApgBTAwBOAzlHkQFyLXkxgDmANIgHQ-mHUB5YLUIMmLVgG0AugEpEAbwBQiRHyghySMlRoFCiANSIARKaNr+UISK4ArOC2JmTsgNxKAvkqXpCUFDQsEQAxcAZSMH0xKGY2Th4uPmoYuKk5RABeAD5GWIkswIwcfTcgAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDZ7SgAmeiA1qALygDeBookArvNJGgNoBEACzyZYXPgBpQfSAAdMFSBKmJsbAEaLJfMvEwBbAPYA7MooC645qEQjTaAIKxYmAJ4AKAKwAmAJSWWiLDC0HgAwrYACkhUeLBo6GxGyPDGoG4+jFYsQdBssEYYicmp6Zks5aDEpDLReGThsGR0oACymNACAHTo2AYGsG5tHZ3OJgZ6pQBUoN4+ANxZ5VWgNdR1AMocpPRDXT19A6sx9bagYACMAMzzBIvZJHkFDKxbaB3wkJ3snJA8RxtbCzWWxof4nRqgACkoCuoAAvgsKgirHDLMiiCRgY0omtYM0KNROoFgmFIrUBjdlmCGk16DZseT0gsCDhYtA3Hx6WQ0HxQABqFa1cFkImnAW8gzoKT8wVrYVfLbzIAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDZ7SgAmeiA1qALygDeBookArvNJGgNoBEACzyZYXPgBpQfSAAdMFSBKmJsbAEaLJfMvEwBbAPYA7MooC645qEQjTaAIKxYmAJ4AKAKwAmAJSWWiLDC0HgAwrYACkhUeLBo6GxGyPDGoG4+jFYsIKAAcgDyACoAomjQQqDY8EZ4oGp42AYA7qDwkKBGzaCYRt1OXQlJ0ClGkjiNTdUA5qBs7dAG1pgy0GxBoADk5W0boAhTAqRCQVl7JGu96XQAfJks95UkoDLReGThsGR0oACymOUAOnQjQMsDcf0BzhMBj0VwAVKBvD4ANynFjEUgvahvADKHFI9AhAiBILBWJi71soDAAEYAMwoghos6rWC9BisfFlARtAHsTiQHjk3H4ixLT5oYWUz6gACkoHpoAAvqiHiqrErLOqiE8bJ8otjYN8KNQAYFgmFIq8wYyMc9XtKvvQ9WQDTEbaiCDhYtA3HwXWg+KAANT27GOs1U0NBgzoKQhsMUj5kPn4lFAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMJygE2QbwFDLIDOArsGAFzFhSgDmA3AcghplSCQLYBG0TAXzx5QkWIhQARCAgDWuZqXJEqRGvQDaAXSaFWWFck69o23SygQ4kdFgAKwOdAAUYABbBD0uQEoqzn2QAXgA+NDZBYQAbCDBkTBlZKm95IIVCJTBDDQAiNysoLJyAGmQcogAHOASiErKEKJIeWtKczGA4LgB7EExarWLmfT6qAEEoKDgAT2cAVgAmH0HCAHoV5AA5AHkAFQBRKh385BgSEAQwYB6jLoB3ZAgADwqox3IoqeIKmWAYYAgiMh3NZkMoWHAojEUFwSGpkHxkF0YECpt9kCkhpZrBBbJgHE4oFRTudLtdXB4vIlAvhCIRLGASFAQMgAsEwjTaYQYnEKo5ZBBMLjgsgALLWNwAOhgUS6XSgzjF7glk16XS4rIAVMgFj5zJzucheU5MABlMhxNKKyXS2Xyo38wVsZDrACMAGZdcJOXTYozmThiOaqO5PBLMkQNPaBWbyANwVgqFHHVhkABSZDu5ACPVZ8wCQbZ6KxeN4vnQYUJOQShBYmxsfH8+Weg1JoVpYYNlyevAQ6BgZw5YZUHLIADUhrLycw1ad45HSLKY4nxtxYfNuqAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgKoEkCiAbCBbCcZAbwChlk4ATKgYW2AQGsAZYAZ0hGgAoB7EAgbMAXMh5gAFhzEA3PsCoAaZBDGZZhMAEpkAXgB8yeYu1yFVANykAvkAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFAgR6ywD2skaATAMwAsArAfAHbSlaJ6gCqASQCi2PAFs8HUAG8CoUJgAmigMLYkAawAy8GJNIAKcm0TrEGtAegALXWgBu5eIoA0oPGiH3J0AJSgAXgA+UEdnXwcnRQBuAgBfVg4uTB5QLx8ZOVAJSEhMAHMPUBgENnzYhMU8U0xYXkRjGFAAV3gRcR80QXaJDljiAFohxGboIYGCGtzQAAlMNkVRWEz5dnRyNBL2cqzjNU0AISUrW2pZ+cXSNyL0jn9ZeXlicnIAB0g3ZvxFUAADG10v1A1lIeAAdC1INtQADIKBEDhsAAjFIaUAAd3IzWwP0QsEwkGsCmgoFgzQ48AkWXksLBa3IgXcYJyeUKsXkCQSBFEJKJAVAbDw6POCyWBl8sVaPR8YKUqjM2l0nEFsAM1jBewVR0UEtAxFIFFgAEIgAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDwB20esWieoAqgJICi2eAtnqaAN4GiiYAm-AMLYkAawAy8GO3IAKAPbFEoxGLRzoAC2loAbgvj8ANKDxoGe9tACUoALwA+UAaM39h-gG4CAXyKk5JTUltZcPKBskJCYAObmoDAIxLE+-vx4Kpiw1IhKMKAArvBMrNZo9KVspD4goAC0jYiF0I31BFnRoAASmMT8zLDhvCToCmhJJKkRSiLiAOIKCvyaOpAeRqYJoaR23Ly8dYh9AOTQRfigAAba0legWuTUAEaZmIWX8NAnkKAK6KBoABPAAO1Fc-AAhBFeHliJAFMwAHTYBSxOQAIhU4jwUIxNh8vH8-gIzHOWgcoGIeAA7j0+gN5ASCMUqtYkQJhKpJNIyNTYHItEjZtzFssCUAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDwB20esWieoAqgJICi2eAtnqaAN4GiiYAm-AMLYkAawAy8GO3IAKAPbFEoxGLRzoAC2loAbgvj8ANKDxoGe9tACUoALwA+UAaM39h-gG4CAXyKk5JTUltZcPKBskJCYAObmoDAIxLE+-vx4Kpiw1IhKMKAArvBMrNZo9KVspD4goAC0jYiF0I31BFnRoAASmMT8zLDhvCToCmhJJKkRSiLiAOIKCvwOoHIJoaR2TsO8oNrSAHSjCqt4h1Ex8T68vmlAAhttps://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFDZ7SiQCu80koAvKANoBEAFnprNUwDShOQAHTABM8kHn0TZyAI3G8mw+JgC2AewB2w8QF0A3AQLpyG5PE2gBSANYBhDsIAUADzSYNATwCUbz6ADeBKCgIKC2bIjWoNBqZHh4oPDooADueADksAkparDW8BoA5qlULKDuoGoyAFZ4yMAcsJgeQSFgSWRqvNBsHqCFmABuCeQ0PQmikeVaqRnY2JY20WygiA6tHY7QHgJ4asnOdPRMVbXITF4BrcHEpFaReML2sMJ0oACymD0AdOjYarlHJ8fk0tGoVI5LgAqUDOb7EIo9LwGYLBLLQciwDSLB5PBwo0AAX1aoQA8uNYCl4PhQNVRqRbss8CocVFxqt1sE8LgEpttrt9rCjnwNOQVDI8LALldUaBGfdrI8AMqUUj0YEsX7-QGHMAARgAzMjrqB0Zjsf4yKq0BQqJAGArlaqdLw1i80IcAKSgQ1EgnE4lEEigFQeAAidSi9AYrUtttQfCUqk02gkbuEaAATETuLGrVQ0PwhKJ5Bz3T6AAw5vPxwtsDhcV0ONAAFmr+kM8psj2ewj1b1DEciDpsvccg8jXg7OEl0EcTHThdAAGpWT2HHrvumV3xKskmDvHXiXpv48ag3du8fhNn6Aqx3qAKzGmeceeL3ero+9zNbhw7g9BQPL8rx-b4zz0IAhttps://www.typescriptlang.org/play/#code/DYUwLgBAzgrglmKEC8EDaAiAFiAhgJ0QwBoIMoAHXAExChLIGNgYAje0jauXAWwHsAdtXoBdANwAoSQDMYgxmDhCIFOIwDWAYQLUAFAA8AXBADe0eGBNQw+OIIDm4iI10nBMXqxD4IAXzRRAEp3T298KTkFJRU1TR18fWMIDy8fELMLBGtbeycXNxSwn39I+UVlQVV1bV1DE1xBAE8MxqazSQgIAHpuiC0cTQgwfmgQEAg4GQgAdxAAcnwJmf58DTzZhCwIRoh+VgArEEVugnxcJs6evqnoflIwHHaHXAA3CZgkR4naIcbqWYLYDAapDb4FRJXW56MBNCggfjTAwoVAYfZHRQYIIdLpdUCQOIaEDUBIA1AAWVwjwAdDJgPxVnpKTTzsJ+Lw9NiAFQQAzU0COR5BKS4iBLMAwfBVQnE0ki-xXXoQADy33wMzgUAmB0+kHxwxwvFBGgNE1ckK6IGAWsm0xhcIRSJRZFS4SxONx+pl1AAypYUBBmVhafTGci+gBGADMwquXXFkqq5lg2SyiDQ3r9CFEpHN1BMyIApBBo6Urn5JBXJPreE0ACLHE2oNBXZOWExcHgCYQcCH5iAAJn8xFbaY7lBodAYeZMEYADMPRymrGQcAQiLnCgAWRcSaRemqy3QRgO1huaDM1Ul6M+NoJ73CgQh6DAzsgQADUxqPiQj1Lzn7voi75ft6pJ-susbVuA34kroQ6oIS14RgArLGj4+GAL5vhggFgfB-66IBuHAbhoGHnBiQDtSkHiEAA

  • functionaddToZ(x,y){returnx+y+z;}

    FunctionTypes

    Typingthefunction

    Let'saddtypestooursimpleexamplesfromearlier:

    functionadd(x:number,y:number):number{returnx+y;}

    letmyAdd=function(x:number,y:number):number{returnx+y;};

    Wecanaddtypestoeachoftheparametersandthentothefunctionitselftoaddareturntype.TypeScriptcanfigurethereturntypeoutbylookingatthereturnstatements,sowecanalsooptionallyleavethisoffinmanycases.

    Writingthefunctiontype

    Nowthatwe'vetypedthefunction,let'swritethefulltypeofthefunctionoutbylookingateachpieceofthefunctiontype.

    letmyAdd:(x:number,y:number)=>number=function(x:number,y:number):number{returnx+y;};

    Afunction'stypehasthesametwoparts:thetypeoftheargumentsandthereturntype.Whenwritingoutthewholefunctiontype,bothpartsarerequired.

  • returntype.Whenwritingoutthewholefunctiontype,bothpartsarerequired.Wewriteouttheparametertypesjustlikeaparameterlist,givingeachparameteranameandatype.Thisnameisjusttohelpwithreadability.Wecouldhaveinsteadwritten:

    letmyAdd:(baseValue:number,increment:number)=>number=function(x:number,y:number):number{returnx+y;};

    Aslongastheparametertypeslineup,it'sconsideredavalidtypeforthefunction,regardlessofthenamesyougivetheparametersinthefunctiontype.

    Thesecondpartisthereturntype.Wemakeitclearwhichisthereturntypebyusinganarrow(=>)betweentheparametersandthereturntype.Asmentionedbefore,thisisarequiredpartofthefunctiontype,soifthefunctiondoesn'treturnavalue,youwouldusevoidinsteadofleavingitoff.

    Ofnote,onlytheparametersandthereturntypemakeupthefunctiontype.Capturedvariablesarenotreflectedinthetype.Ineffect,capturedvariablesarepartofthe"hiddenstate"ofanyfunctionanddonotmakeupitsAPI.

    Inferringthetypes

    Inplayingwiththeexample,youmaynoticethattheTypeScriptcompilercanfigureoutthetypeevenifyouonlyhavetypesononesideoftheequation:

    //Theparameters'x'and'y'havethetypenumberletmyAdd=function(x:number,y:number):number{returnx+y;};

    //myAddhasthefullfunctiontypeletmyAdd2:(baseValue:number,increment:number)=>number=functionreturnx+y;};

    Thisiscalled"contextualtyping",aformoftypeinference.Thishelpscutdownontheamountofefforttokeepyourprogramtyped.

  • ontheamountofefforttokeepyourprogramtyped.

    OptionalandDefaultParameters

    InTypeScript,everyparameterisassumedtoberequiredbythefunction.Thisdoesn'tmeanthatitcan'tbegivennullorundefined,butrather,whenthefunctioniscalled,thecompilerwillcheckthattheuserhasprovidedavalueforeachparameter.Thecompileralsoassumesthattheseparametersaretheonlyparametersthatwillbepassedtothefunction.Inshort,thenumberofargumentsgiventoafunctionhastomatchthenumberofparametersthefunctionexpects.

    functionbuildName(firstName:string,lastName:string){returnfirstName+""+lastName;}

    letresult1=buildName("Bob");//error,toofewparameters

    Expected2arguments,butgot1.letresult2=buildName("Bob","Adams","Sr.");//error,toomanyparameters

    Expected2arguments,butgot3.letresult3=buildName("Bob","Adams");//ah,justright

    InJavaScript,everyparameterisoptional,andusersmayleavethemoffastheyseefit.Whentheydo,theirvalueisundefined.WecangetthisfunctionalityinTypeScriptbyaddinga?totheendofparameterswewanttobeoptional.Forexample,let'ssaywewantthelastnameparameterfromabovetobeoptional:

    functionbuildName(firstName:string,lastName?:string){if(lastName)returnfirstName+""+lastName;elsereturnfirstName;}

    letresult1=buildName("Bob");//workscorrectlynowletresult2=buildName("Bob","Adams","Sr.");//error,toomanyparameters

    Expected1-2arguments,butgot3.letresult3=buildName("Bob","Adams");//ah,justright

    Anyoptionalparametersmustfollowrequiredparameters.Hadwewantedtomakethefirstnameoptional,ratherthanthelastname,wewouldneedtochangetheorderofparametersinthefunction,puttingthefirstnamelastinthelist.

  • InTypeScript,wecanalsosetavaluethataparameterwillbeassignediftheuserdoesnotprovideone,oriftheuserpassesundefinedinitsplace.Thesearecalleddefault-initializedparameters.Let'stakethepreviousexampleanddefaultthelastnameto"Smith".

    functionbuildName(firstName:string,lastName="Smith"){returnfirstName+""+lastName;}

    letresult1=buildName("Bob");//workscorrectlynow,returns"BobSmith"letresult2=buildName("Bob",undefined);//stillworks,alsoreturns"BobSmith"letresult3=buildName("Bob","Adams","Sr.");//error,toomanyparameters

    Expected1-2arguments,butgot3.letresult4=buildName("Bob","Adams");//ah,justright

    Default-initializedparametersthatcomeafterallrequiredparametersaretreatedasoptional,andjustlikeoptionalparameters,canbeomittedwhencallingtheirrespectivefunction.Thismeansoptionalparametersandtrailingdefaultparameterswillsharecommonalityintheirtypes,soboth

    functionbuildName(firstName:string,lastName?:string){//...}

    and

    functionbuildName(firstName:string,lastName="Smith"){//...}

    sharethesametype(firstName:string,lastName?:string)=>string.ThedefaultvalueoflastNamedisappearsinthetype,onlyleavingbehindthefactthattheparameterisoptional.

    Unlikeplainoptionalparameters,default-initializedparametersdon'tneedtooccurafterrequiredparameters.Ifadefault-initializedparametercomesbeforearequiredparameter,usersneedtoexplicitlypassundefinedtogetthedefaultinitializedvalue.Forexample,wecouldwriteourlastexamplewithonlyadefaultinitializeronfirstName:

    functionbuildName(firstName="Will",lastName:string){returnfirstName+""+lastName;}

  • letresult1=buildName("Bob");//error,toofewparameters

    Expected2arguments,butgot1.letresult2=buildName("Bob","Adams","Sr.");//error,toomanyparameters

    Expected2arguments,butgot3.letresult3=buildName("Bob","Adams");//okayandreturns"BobAdams"letresult4=buildName(undefined,"Adams");//okayandreturns"WillAdams"

    RestParameters

    Required,optional,anddefaultparametersallhaveonethingincommon:theytalkaboutoneparameteratatime.Sometimes,youwanttoworkwithmultipleparametersasagroup,oryoumaynotknowhowmanyparametersafunctionwillultimatelytake.InJavaScript,youcanworkwiththeargumentsdirectlyusingtheargumentsvariablethatisvisibleinsideeveryfunctionbody.

    InTypeScript,youcangathertheseargumentstogetherintoavariable:

    functionbuildName(firstName:string,...restOfName:string[]){returnfirstName+""+restOfName.join("");}

    //employeeNamewillbe"JosephSamuelLucasMacKinzie"letemployeeName=buildName("Joseph","Samuel","Lucas","MacKinzie");

    Restparametersaretreatedasaboundlessnumberofoptionalparameters.Whenpassingargumentsforarestparameter,youcanuseasmanyasyouwant;youcanevenpassnone.Thecompilerwillbuildanarrayoftheargumentspassedinwiththenamegivenaftertheellipsis(...),allowingyoutouseitinyourfunction.

    Theellipsisisalsousedinthetypeofthefunctionwithrestparameters:

    functionbuildName(firstName:string,...restOfName:string[]){returnfirstName+""+restOfName.join("");}

    letbuildNameFun:(fname:string,...rest:string[])=>string=buildName

  • this

    LearninghowtousethisinJavaScriptissomethingofariteofpassage.SinceTypeScriptisasupersetofJavaScript,TypeScriptdevelopersalsoneedtolearnhowtousethisandhowtospotwhenit'snotbeingusedcorrectly.Fortunately,TypeScriptletsyoucatchincorrectusesofthiswithacoupleoftechniques.IfyouneedtolearnhowthisworksinJavaScript,though,firstreadYehudaKatz'sUnderstandingJavaScriptFunctionInvocationand"this".Yehuda'sarticleexplainstheinnerworkingsofthisverywell,sowe'lljustcoverthebasicshere.

    thisandarrowfunctions

    InJavaScript,thisisavariablethat'ssetwhenafunctioniscalled.Thismakesitaverypowerfulandflexiblefeature,butitcomesatthecostofalwayshavingtoknowaboutthecontextthatafunctionisexecutingin.Thisisnotoriouslyconfusing,especiallywhenreturningafunctionorpassingafunctionasanargument.

    Let'slookatanexample:

    letdeck={suits:["hearts","spades","clubs","diamonds"],cards:Array(52),createCardPicker:function(){returnfunction(){letpickedCard=Math.floor(Math.random()*52);letpickedSuit=Math.floor(pickedCard/13);

    return{suit:this.suits[pickedSuit],card:pickedCard%13};};},};

    letcardPicker=deck.createCardPicker();letpickedCard=cardPicker();

    alert("card:"+pickedCard.card+"of"+pickedCard.suit);

    NoticethatcreateCardPickerisafunctionthatitselfreturnsafunction.Ifwetriedtoruntheexample,wewouldgetanerrorinsteadoftheexpectedalertbox.

    http://yehudakatz.com/2011/08/11/understanding-javascript-function-invocation-and-this/

  • ThisisbecausethethisbeingusedinthefunctioncreatedbycreateCardPickerwillbesettowindowinsteadofourdeckobject.That'sbecausewecallcardPicker()onitsown.Atop-levelnon-methodsyntaxcalllikethiswillusewindowforthis.(Note:understrictmode,thiswillbeundefinedratherthanwindow).

    Wecanfixthisbymakingsurethefunctionisboundtothecorrectthisbeforewereturnthefunctiontobeusedlater.Thisway,regardlessofhowit'slaterused,itwillstillbeabletoseetheoriginaldeckobject.Todothis,wechangethefunctionexpressiontousetheECMAScript6arrowsyntax.Arrowfunctionscapturethethiswherethefunctioniscreatedratherthanwhereitisinvoked:

    letdeck={suits:["hearts","spades","clubs","diamonds"],cards:Array(52),createCardPicker:function(){//NOTE:thelinebelowisnowanarrowfunction,allowingustocapture'this'rightherereturn()=>{letpickedCard=Math.floor(Math.random()*52);letpickedSuit=Math.floor(pickedCard/13);

    return{suit:this.suits[pickedSuit],card:pickedCard%13};};},};

    letcardPicker=deck.createCardPicker();letpickedCard=cardPicker();

    alert("card:"+pickedCard.card+"of"+pickedCard.suit);

    Evenbetter,TypeScriptwillwarnyouwhenyoumakethismistakeifyoupassthe--noImplicitThisflagtothecompiler.Itwillpointoutthatthisinthis.suits[pickedSuit]isoftypeany.

    thisparameters

    Unfortunately,thetypeofthis.suits[pickedSuit]isstillany.That'sbecausethiscomesfromthefunctionexpressioninsidetheobjectliteral.Tofixthis,youcanprovideanexplicitthisparameter.thisparametersarefakeparametersthat

  • comefirstintheparameterlistofafunction:

    functionf(this:void){//makesure`this`isunusableinthisstandalonefunction}

    Let'saddacoupleofinterfacestoourexampleabove,CardandDeck,tomakethetypesclearerandeasiertoreuse:

    interfaceCard{suit:string;card:number;}

    interfaceDeck{suits:string[];cards:number[];createCardPicker(this:Deck):()=>Card;}

    letdeck:Deck={suits:["hearts","spades","clubs","diamonds"],cards:Array(52),//NOTE:ThefunctionnowexplicitlyspecifiesthatitscalleemustbeoftypeDeckcreateCardPicker:function(this:Deck){return()=>{letpickedCard=Math.floor(Math.random()*52);letpickedSuit=Math.floor(pickedCard/13);

    return{suit:this.suits[pickedSuit],card:pickedCard%13};};},};

    letcardPicker=deck.createCardPicker();letpickedCard=cardPicker();

    alert("card:"+pickedCard.card+"of"+pickedCard.suit);

    NowTypeScriptknowsthatcreateCardPickerexpectstobecalledonaDeckobject.ThatmeansthatthisisoftypeDecknow,notany,so--noImplicitThiswillnotcauseanyerrors.

    thisparametersincallbacks

  • Youcanalsorunintoerrorswiththisincallbacks,whenyoupassfunctionstoalibrarythatwilllatercallthem.Becausethelibrarythatcallsyourcallbackwillcallitlikeanormalfunction,thiswillbeundefined.Withsomeworkyoucanusethisparameterstopreventerrorswithcallbackstoo.First,thelibraryauthorneedstoannotatethecallbacktypewiththis:

    interfaceUIElement{addClickListener(onclick:(this:void,e:Event)=>void):void;}

    this:voidmeansthataddClickListenerexpectsonclicktobeafunctionthatdoesnotrequireathistype.Second,annotateyourcallingcodewiththis:

    classHandler{info:string;onClickBad(this:Handler,e:Event){//oops,used`this`here.usingthiscallbackwouldcrashatruntimethis.info=e.message;}}

    leth=newHandler();uiElement.addClickListener(h.onClickBad);//error!

    Argumentoftype'(this:Handler,e:Event)=>void'isnotassignabletoparameteroftype'(this:void,e:Event)=>void'.The'this'typesofeachsignatureareincompatible.Type'void'isnotassignabletotype'Handler'.

    Withthisannotated,youmakeitexplicitthatonClickBadmustbecalledonaninstanceofHandler.ThenTypeScriptwilldetectthataddClickListenerrequiresafunctionthathasthis:void.Tofixtheerror,changethetypeofthis:

    classHandler{info:string;onClickGood(this:void,e:Event){//can'tuse`this`herebecauseit'softypevoid!console.log("clicked!");}}

    leth=newHandler();uiElement.addClickListener(h.onClickGood);

    BecauseonClickGoodspecifiesitsthistypeasvoid,itislegaltopasstoaddClickListener.Ofcourse,thisalsomeansthatitcan'tusethis.info.Ifyou

  • wantboththenyou'llhavetouseanarrowfunction:

    classHandler{info:string;onClickGood=(e:Event)=>{this.info=e.message;};}

    Thisworksbecausearrowfunctionsusetheouterthis,soyoucanalwayspassthemtosomethingthatexpectsthis:void.ThedownsideisthatonearrowfunctioniscreatedperobjectoftypeHandler.Methods,ontheotherhand,areonlycreatedonceandattachedtoHandler'sprototype.TheyaresharedbetweenallobjectsoftypeHandler.

    Overloads

    JavaScriptisinherentlyaverydynamiclanguage.It'snotuncommonforasingleJavaScriptfunctiontoreturndifferenttypesofobjectsbasedontheshapeoftheargumentspassedin.

    letsuits=["hearts","spades","clubs","diamonds"];

    functionpickCard(x:any):any{//Checktoseeifwe'reworkingwithanobject/array//ifso,theygaveusthedeckandwe'llpickthecardif(typeofx=="object"){letpickedCard=Math.floor(Math.random()*x.length);returnpickedCard;}//Otherwisejustletthempickthecardelseif(typeofx=="number"){letpickedSuit=Math.floor(x/13);return{suit:suits[pickedSuit],card:x%13};}}

    letmyDeck=[{suit:"diamonds",card:2},{suit:"spades",card:10},{suit:"hearts",card:4},];

  • letpickedCard1=myDeck[pickCard(myDeck)];alert("card:"+pickedCard1.card+"of"+pickedCard1.suit);

    letpickedCard2=pickCard(15);alert("card:"+pickedCard2.card+"of"+pickedCard2.suit);

    Here,thepickCardfunctionwillreturntwodifferentthingsbasedonwhattheuserhaspassedin.Iftheuserspassesinanobjectthatrepresentsthedeck,thefunctionwillpickthecard.Iftheuserpicksthecard,wetellthemwhichcardthey'vepicked.Buthowdowedescribethistothetypesystem?

    Theansweristosupplymultiplefunctiontypesforthesamefunctionasalistofoverloads.Thislistiswhatthecompilerwillusetoresolvefunctioncalls.Let'screatealistofoverloadsthatdescribewhatourpickCardacceptsandwhatitreturns.

    letsuits=["hearts","spades","clubs","diamonds"];

    functionpickCard(x:{suit:string;card:number}[]):number;functionpickCard(x:number):{suit:string;card:number};functionpickCard(x:any):any{//Checktoseeifwe'reworkingwithanobject/array//ifso,theygaveusthedeckandwe'llpickthecardif(typeofx=="object"){letpickedCard=Math.floor(Math.random()*x.length);returnpickedCard;}//Otherwisejustletthempickthecardelseif(typeofx=="number"){letpickedSuit=Math.floor(x/13);return{suit:suits[pickedSuit],card:x%13};}}

    letmyDeck=[{suit:"diamonds",card:2},{suit:"spades",card:10},{suit:"hearts",card:4},];

    letpickedCard1=myDeck[pickCard(myDeck)];alert("card:"+pickedCard1.card+"of"+pickedCard1.suit);

    letpickedCard2=pickCard(15);alert("card:"+pickedCard2.card+"of"+pickedCard2.suit);

  • Withthischange,theoverloadsnowgiveustypecheckedcallstothepickCardfunction.

    Inorderforthecompilertopickthecorrecttypecheck,itfollowsasimilarprocesstotheunderlyingJavaScript.Itlooksattheoverloadlistand,proceedingwiththefirstoverload,attemptstocallthefunctionwiththeprovidedparameters.Ifitfindsamatch,itpicksthisoverloadasthecorrectoverload.Forthisreason,it'scustomarytoorderoverloadsfrommostspecifictoleastspecific.

    NotethatthefunctionpickCard(x):anypieceisnotpartoftheoverloadlist,soitonlyhastwooverloads:onethattakesanobjectandonethattakesanumber.CallingpickCardwithanyotherparametertypeswouldcauseanerror.

  • LiteralTypesAliteralisamoreconcretesub-typeofacollectivetype.Whatthismeansisthat"HelloWorld"isastring,butastringisnot"HelloWorld"insidethetypesystem.

    TherearethreesetsofliteraltypesavailableinTypeScripttoday:strings,numbers,andbooleans;byusingliteraltypesyoucanallowanexactvaluewhichastring,number,orbooleanmusthave.

    LiteralNarrowing

    Whenyoudeclareavariableviavarorlet,youaretellingthecompilerthatthereisthechancethatthisvariablewillchangeitscontents.Incontrast,usingconsttodeclareavariablewillinformTypeScriptthatthisobjectwillneverchange.

    //We'remakingaguaranteethatthisvariable//helloWorldwillneverchange,byusingconst.

    //So,TypeScriptsetsthetypetobe"HelloWorld",notstringconsthelloWorld="HelloWorld";

    //Ontheotherhand,aletcanchange,andsothecompilerdeclaresitastringlethiWorld="HiWorld";

    Theprocessofgoingfromaninfinitenumberofpotentialcases(thereareaninfinitenumberofpossiblestringvalues)toasmaller,finitenumberofpotentialcase(inhelloWorld'scase:1)iscallednarrowing.

    StringLiteralTypes

    Inpracticestringliteraltypescombinenicelywithuniontypes,typeguards,andtypealiases.Youcanusethesefeaturestogethertogetenum-likebehaviorwithstrings.

    https://www.typescriptlang.org/play/#code/PTAEHUFMHICdNAWwIYGsCWA7A5qZpsBXZWZTAF0gXIAtlzRb0BnUANxPWQCMAbSAFAhQNSL14B7cBNi8AJqADu6caEyQ2kWKADGdHJAA0obgE9QhZllw6JmZuQB0AoWADKE4wBVTAB0huOrDovgzMkOSstNR+1BImCABEABJikhAy8onGmBJh5ME4Arb2DKLiUpkKALygKWnx0rJyiQDcLsIA8piMoqB5otr6csb4-Aw6ZLr62EZ4mArM8dG6Eoi+KlqgcpA6vCSQrOgM+A6F2ALjIuhN8qC1KegZzW1AAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAC4CeADpKAKICGiAlgHYDmoAvKAESQ2QC0D7oAD4cuiXnACuBAcM7c+9HpOkBuPHgDGAGxqJQAVQCSFLZAC2kegVABvPKFBV6tM1QKQAFABMAHqnoSZgBGMAA0oF5E-oEh0OGiDIyo1HRMAJS29g6gtABmoB4JTKwsbHJiCuwZdtnZIKAAdE1ZDgC+oJBaYjn5hTSJJWWi4lJVmbXtnd15BUXMpUPyDEqj1S2gk13kNbWg9YYEAOR6JHCIdEGmoAQAFm6giHAWcPTkGpJaXqDQXBo31zdaIh1g56kEiDlGPQEAMiJJoNdSJA9LdJIwbg11q0stjsXhTNYglICC9WKBXgB3AzGUwWKweNJqIkEEn0BpOFxuTwABnCvJES3oVSZxJe7OcrncHn5-PYEleNCIwqAAhttps://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABAJzgGzQERhApgCgEoAuRARkQB9EAmKxAZnoBZ6BWegNkQG8AoRClxQQyJPgCyAQygALAHTA0cOMkkyFyKWAAmcALZFEAKkSdCiANTkLUgM7l6dak2qtqHapwDcfAL58fBAIdlBCdiBoYQC8KOhYOASE3kAhttps://www.typescriptlang.org/play/#code/PQKhAIGECcFMEMAusDO57gLbwA7gMawB2ycAJuouADYD2+w1S4IwAUGbPk3OAGYBXIvkQBLWkXApYiATgCyuABT4JfUQHMAXOEU5IazQEodAN1qiyAbjbBg4ALRP8AxE4dtRJWND7xCurgGROoa4ADebOA0RNrgRAKYAEY+NtFMiDoJyalR4GLUsADKogBesDoAHOAAPuAAjABsteAAzABMNgC+bGzSsgrK4TFxDgDsrQB0AJytAKztACztADQ0SDqLAAyTE1uN9WsFxWUVDc1dRlZAAhttps://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgGpwDbACZzMAexAGUBXBJAZ0uQG8AoZZYS9LbALmTClIgG5GyKBDiUiXEKQwZBAX3r1QkWIhRsceQiABicYBlIi6Qlhs7J4GSgKEixE5JR6gA5vMVgAngAd1mTXwiACUISmkwZABeNADcIJJyKhoAH1j2LSI9AyMBIA

  • strings.

    typeEasing="ease-in"|"ease-out"|"ease-in-out";

    classUIElement{animate(dx:number,dy:number,easing:Easing){if(easing==="ease-in"){//...}elseif(easing==="ease-out"){}elseif(easing==="ease-in-out"){}else{//It'spossiblethatsomeonecouldreachthis//byignoringyourtypesthough.}}}

    letbutton=newUIElement();button.animate(0,0,"ease-in");button.animate(0,0,"uneasy");

    Argumentoftype'"uneasy"'isnotassignabletoparameteroftype'Easing'.

    Youcanpassanyofthethreeallowedstrings,butanyotherstringwillgivetheerror

    Argumentoftype'"uneasy"'isnotassignabletoparameteroftype'"ease-in"|"ease-out"|"ease-in-out"'

    Stringliteraltypescanbeusedinthesamewaytodistinguishoverloads:

    functioncreateElement(tagName:"img"):HTMLImageElement;functioncreateElement(tagName:"input"):HTMLInputElement;//...moreoverloads...functioncreateElement(tagName:string):Element{//...codegoeshere...}

    NumericLiteralTypes

    TypeScriptalsohasnumericliteraltypes,whichactthesameasthestringliteralsabove.

    functionrollDice():1|2|3|4|5|6{

  • return(Math.floor(Math.random()*6)+1)as1|2|3|4|5|6;}

    constresult=rollDice();

    Acommoncasefortheiruseisfordescribingconfigvalues:

    interfaceMapConfig{lng:number;lat:number;tileSize:8|16|32;}

    setupMap({lng:-73.935242,lat:40.73061,tileSize:16});

    BooleanLiteralTypes

    TypeScriptalsohasbooleanliteraltypes.Youmightusethesetoconstrainobjectvalueswhosepropertiesareinterrelated.

    interfaceValidationSuccess{isValid:true;reason:null;}

    interfaceValidationFailure{isValid:false;reason:string;}

    typeValidationResult=ValidationSuccess|ValidationFailure;

  • UnionsandIntersectionTypesSofar,thehandbookhascoveredtypeswhichareatomicobjects.However,asyoumodelmoretypesyoufindyourselflookingfortoolswhichletyoucomposeorcombineexistingtypesinsteadofcreatingthemfromscratch.

    IntersectionandUniontypesareoneofthewaysinwhichyoucancomposetypes.

    UnionTypes

    Occasionally,you'llrunintoalibrarythatexpectsaparametertobeeitheranumberorastring.Forinstance,takethefollowingfunction:

    /***Takesastringandadds"padding"totheleft.*If'padding'isastring,then'padding'isappendedtotheleftside.*If'padding'isanumber,thenthatnumberofspacesisaddedtotheleftside.*/functionpadLeft(value:string,padding:any){if(typeofpadding==="number"){returnArray(padding+1).join("")+value;}if(typeofpadding==="string"){returnpadding+value;}thrownewError(`Expectedstringornumber,got'${typeofpadding}'.`}

    padLeft("Helloworld",4);//returns"Helloworld"

    TheproblemwithpadLeftintheaboveexampleisthatitspaddingparameteristypedasany.Thatmeansthatwecancallitwithanargumentthat'sneitheranumbernorastring,butTypeScriptwillbeokaywithit.

    //passesatcompiletime,failsatruntime.letindentedString=padLeft("Helloworld",true);

    Intraditionalobject-orientedcode,wemightabstractoverthetwotypesby

    https://www.typescriptlang.org/play/#code/PQKhCgAIUgVBDA1gUwM6XpVAXATgSwDsBzDQgEw3PPQCIAHeao42ybAe3YAtlIAbZADNsAOigwAkkMgByRsxKzI+dJhwESAGh7JCcheRbLVGevT3lklTroHDsWfFfHRI0g0yNKVayIQBXAFsAI2RcHWxefSj4R0DQ8MgOGVRGAGM0XyorGy4ovkERJxcJYHAhAMJ07HwOfQUAGQcACgA3eH4A5AAuLDwWHUMWPvhCAE8ASkgAbygVGRbscYsUyGGSSABeHchaBLDcWmm5yDPIXGRsANx9AEFcXHhxlo3SAGpIAEZJ0QArDhEFpsY6QT4dLrIADc8wAvvN8ItlqsZG9trtaBoWKDTudLtdbusvCwwZAId0YWd4WcorgOAB3fzIRkAUUeHFwLQABiyAB4WGrWfqaUgc-zBQ46YgcRyyAAkM2RyDWb1hslEXMmMPh4CarVoAAlkPx+Fx6Rz+ORaDoACxayDAYAXK43Qh0c6QI0ms0Wq1AAhttps://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwAcpgAZERDACgDcoJkQAueAZwxi1QHMAaQ44Jy7MoqAJ4BKZmw7cA3ACgA9EvgBaDWGQYNa5aqIsWIFvCgZ4YHAFsCWCAmzWQfRFHunz8GGicgAdAoOFpygqBggwADK7ELwALz8pORUAEQAEiAQEDjwAO44MBDAqXzsDBJyQAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUMAFSF6iGgAqAhgNaSKhWiIAu0AlgHYDmjnAJo378GAIgAOVYV26jQLOPIAWkUABtIAMxYA6UuQCSm0AHJJ0nidDsGTVhx4AaZZE6nz-GVZuNx41-yQggou6loszOyBemSgRu5SnpbWtqCcAK4AtgBGMM4sKm4FVBEZOTCgcMaIkgDG9ClCgcGKBaoa2pHR+sB4mumctSzscG7mADLhABQAblRq6ZCo9jLOHjLLbDKgAD5pWbnQAJSgAN6koCCgOjd4AL54eBoRXIGcLEEAyls8oAC8oAm01EAAlIGo1IoAO4INT8UT5aCLI4AbiAAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYME4BQuBLAOwBcYAzAQwGNJQAhA6AE1AG9dRRyAbATwAUASlQA3OAWYBuTqB6U+AUQDmyxMLETpuAL75iZaFVqgAYgUQALdrMQB3AgFsNocZJld5S1epGutMnq4zJDU8tB05ACuRNQkBHBEoMqQJADKjpQ8PAAKqS7mVqAAPgxM2rg8qaAADtUAvMmpGVm5+UIydSQAdF4qasIyuCCgAPJE-KCUopQE8gBGVaDEoIl0cOSgJJZ0JHZwtXCIiASLu3x1iLhd3fZOg0Ahttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYME4BQAXATwAdJQA5SfAdwQGsAZOAQwBMBLAOwHMBlfZvjIBeUAG9coUIgFDUAIgA2LDj3kBuXAF9NBEmUo16AMWbtFkVv0Ejxk6bMgKAZmYusN9gMZxWT0JwArgC2AEYwmjq4eqQUVLTQdLyBXl6QiIjWQqCiElIyNgqIKWkZnlLQ6cRwnIj+eVKg+Oz4Fqgy0Fzcmo2grIHQguw1qEFhEfb5IcHM0ITt+J08PaBRUSCgALTbXoH425sxBvH0WSL2AD5xRolMbF1nl9cJdKbmlo9SV4YvyanpmUcumcgU4XmaNVAym43BgAAoCnJnqdHABKBZLbh2KQbABK7G4AAt8AE4NRQAAVfS8LydYgk1hwdKkkl0Thk0DUQnsLyE0BwZxNQlkfCEyqQewbapCTjNZiKJr6RAOGygHyBRSsUDhAB00RxYApcy6TTgoGY-wy5tAxHgpGgRE53N5oHYiE4AHISYhCbNLJKwBb4Fb5QqiKRldRzArBm6yMxOKAYPBoPZEZAdT4-LoDaAAEKEaRR-C8k2Q9MAGkp1Np7HpaoTAVm8HJorIoOGnADfTJia4at8ZGcynJCflhEQbrTxZdCMcOvTqOxjS8zDqoCUKi68mQk0alXwA0T8gAIr3lPceDrr+UV2uyPJXO8PLvermKcLFbFgoEZNrjjcrxuB8jigMKlQVnuuaIGaFqlJOPBCmQAAGWaQMhoDOOwkCaq6yqIMwzgSm+oAHkeoDIQAorACCgAAJGI6aZoOWg9tQnAXqo3DISsUiruu8jFJaiA7lBpFUORyFnuxnGWPRjHzpUiDVLUGbNK0kCsZs8lMUpKl1Au0yzIQWg8fYWjaEAAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYBsWBQAXATwAdJQA5SfAdwQGsAZOAQwBMBLAOwHMBlfZvjIBeUAG9QiAUNQAiADYsOPWaAC+AbgIkylGvQBizdvMit+gkeMnTIcgGbHTrWRtABjOKzuhOAVwBbACMYdS0iUgoqWmg6Xj93d0hERAshUFExXFAbSzlEBKSU12zQaGTiOE5EHyycnPx2fFNUKWgubi160FY-aEF2KtR-YJgu+oKAgOZoQlb8dp5xzVwVkFAAWi33P3wtje1IvRi6A3gAgGFmdwALMzSrOtyZUFl7c4B9d2u7kpz2VjzRadUrlRCVao+Y70eKJZKpWwAbVkYIhNVkAF0tCtDrpojDbBlSgAfKL6WJMNgdB4ksknIwme62WnQ2KwooIyws-GxM5wS4-JmWLS4ex+TjuRpVUCKbjcGAAChQdIJlgAlOJSohqE1bqAlQA6KTqzXdb41V6KKkqZClbrlfB9TiWpQdMqQACOfmS+D+9XNZDeTjMslt3RyDqdoAABo5GaxQDr8DcPF4yAASMSIA2ebxqaPjHIB14FOHFMPhyPQZ2ybhwfDu8FVdHLVZAAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYBsWBQAXATwAdJQA5SfAdwQGsAZOAQwBMBLAOwHMBlfZvjIBeUAG9QiAUNQAiADYsOPWaAC+AbgIkylGvQBizdvMit+gkeMnTIcgGbHTrWRtABjOKzuhOAVwBbACMYdS0iUgoqWmg6Xj93d0hERAshUFEJKUs5RASklNVNbUi9GLoDeACAYWZ3AAszNKss2wcqgH13OsairRLdaPpmjNxQUAAfKP1YpjYuPlsxyenyoxMmpfGpsuH85NStld3Yyrgans3LfpBQAFoH9z98B7vcez9Od3x2OE5QRTcbgwAAUKFWw1sAEpUFJoAtxMtENR2PgGqAwQA6bJCKGI8bjbqIMgKJQLWTIZYE0DQKh+aD-UnzHg0yAARz8yXwripHmYxNAskcGxclOp41p+Hp-wABsLnKAUfh6h4vGQACRiRCYzzeNQyrTUokkvKJA4U3kSukMwXcOD4VmIYh-Yk88ZqXBqIAhttps://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAC4CeADpKAHKQEDuCA1gDJwCGAJgJYB2A5gMoEWBcgF5QAb1CJBw1ACIANq0685oAL4BuQqXJVaDAGIsOCyGwFDREqTMjyAZibNs5m0AGM4be6C4BXAFsAIxgNbWIySmo6aHo+fw8PSERES2FQMUlpK3lEROTUtS0dKP1Y+kN4QIBhFg8AC3N062y7R2qAfQ96puLtUr0YhhbMvFBQAB9ogzjmdm5+O3GpmYrjU2blienykYKUtO3VvbiquFrerattEFAAWkePfwJH+7wHfy4PAg44LlALFSMAIVAAbjAABQAD1QXEgEOgAEo4QiwuIVgQGvAaH5ILiAKKwBCQuQAVXh0LIP3MoDgwQAVpAfvJQABqUDQpHadR4D5fH5-AFKHg8KEoNYjOwo2zQRYSFaIGgcAiNUCQxAAOhywiRComEx6iHIimUizkyBWBtA0Go-mgANNC14NsgAEd-CkCG4rZ4gSanJtXJbrRNbQR7QCAAaBlygZVYzzecgAEnEWq8PnUUe01qNJvySUOFt9YbtDtAch4cAIrsQJH+xp91p8Tn8CgIIdD4cjgOB0FBaOgGu5K156iAA

  • creatingahierarchyoftypes.Whilethisismuchmoreexplicit,it'salsoalittlebitoverkill.OneofthenicethingsabouttheoriginalversionofpadLeftwasthatwewereabletojustpassinprimitives.Thatmeantthatusagewassimpleandconcise.Thisnewapproachalsowouldn'thelpifwewerejusttryingtouseafunctionthatalreadyexistselsewhere.

    Insteadofany,wecanuseauniontypeforthepaddingparameter:

    /***Takesastringandadds"padding"totheleft.*If'padding'isastring,then'padding'isappendedtotheleftside.*If'padding'isanumber,thenthatnumberofspacesisaddedtotheleftside.*/functionpadLeft(value:string,padding:string|number){//...}

    letindentedString=padLeft("Helloworld",true);

    Argumentoftype'boolean'isnotassignabletoparameteroftype'string|number'.

    Auniontypedescribesavaluethatcanbeoneofseveraltypes.Weusetheverticalbar(|)toseparateeachtype,sonumber|string|booleanisthetypeofavaluethatcanbeanumber,astring,oraboolean.

    UnionswithCommonFields

    Ifwehaveavaluethatisauniontype,wecanonlyaccessmembersthatarecommontoalltypesintheunion.

    interfaceBird{fly():void;layEggs():void;}

    interfaceFish{swim():void;layEggs():void;}

    declarefunctiongetSmallPet():Fish|Bird;

  • letpet=getSmallPet();pet.layEggs();

    //Onlyavailableinoneofthetwopossibletypespet.swim();

    Property'swim'doesnotexistontype'Bird|Fish'.Property'swim'doesnotexistontype'Bird'.

    Uniontypescanbeabittrickyhere,butitjusttakesabitofintuitiontogetusedto.IfavaluehasthetypeA|B,weonlyknowforcertainthatithasmembersthatbothAandBhave.Inthisexample,Birdhasamembernamedfly.Wecan'tbesurewhetheravariabletypedasBird|Fishhasaflymethod.IfthevariableisreallyaFishatruntime,thencallingpet.fly()willfail.

    DiscriminatingUnions

    AcommontechniqueforworkingwithunionsistohaveasinglefieldwhichusesliteraltypeswhichyoucanusetoletTypeScriptnarrowdownthepossiblecurrenttype.Forexample,we'regoingtocreateaunionofthreetypeswhichhaveasinglesharedfield.

    typeNetworkLoadingState={state:"loading";};typeNetworkFailedState={state:"failed";code:number;};typeNetworkSuccessState={state:"success";response:{title:string;duration:number;summary:string;};};//Createatypewhichrepresentsonlyoneoftheabovetypes//butyouaren'tsurewhichitisyet.typeNetworkState=|NetworkLoadingState|NetworkFailedState|NetworkSuccessState;

  • Alloftheabovetypeshaveafieldnamedstate,andthentheyalsohavetheirownfields:

    NetworkLoadingState NetworkFailedState NetworkSuccessState

    state state statecode response

    GiventhestatefieldiscommonineverytypeinsideNetworkState-itissafeforyourcodetoaccesswithoutanexistencecheck.

    Withstateasaliteraltype,youcancomparethevalueofstatetotheequivalentstringandTypeScriptwillknowwhichtypeiscurrentlybeingused.

    NetworkLoadingState NetworkFailedState NetworkSuccessState

    "loading" "failed" "success"

    Inthiscase,youcanuseaswitchstatementtonarrowdownwhichtypeisrepresentedatruntime:

    typeNetworkState=|NetworkLoadingState|NetworkFailedState|NetworkSuccessState;

    functionlogger(state:NetworkState):string{//RightnowTypeScriptdoesnotknowwhichofthethree//potentialtypesstatecouldbe.

    //Tryingtoaccessapropertywhichisn'tshared//acrossalltypeswillraiseanerrorstate.code;

    Property'code'doesnotexistontype'NetworkState'.Property'code'doesnotexistontype'NetworkLoadingState'.

    //Byswitchingonstate,TypeScriptcannarrowtheunion//downincodeflowanalysisswitch(state.state){case"loading":return"Downloading...";case"failed"://ThetypemustbeNetworkFailedStatehere,//soaccessingthe`code`fieldissafereturn`Error${state.code}downloading`;

  • case"success":return`Downloaded${state.response.title}-${state.response.summary}}

    UnionExhaustivenesschecking

    Wewouldlikethecompilertotelluswhenwedon'tcoverallvariantsofthediscriminatedunion.Forexample,ifweaddNetworkFromCachedStatetoNetworkState,weneedtoupdateloggeraswell:

    typeNetworkFromCachedState={state:"from_cache";id:string;response:NetworkSuccessState["response"];};

    typeNetworkState=|NetworkLoadingState|NetworkFailedState|NetworkSuccessState|NetworkFromCachedState;

    functionlogger(s:NetworkState){switch(s.state){case"loading":return"loadingrequest";case"failed":return`failedwithcode${s.code}`;case"success":return"gotresponse";}}

    Therearetwowaystodothis.Thefirstistoturnon--strictNullChecksandspecifyareturntype: