import "reflect-metadata" ; console . log ( "hello_ch04" ) ; function simpleDecorator ( constructor ) { console . log ( 'simpleDecorator called.' ) ; } @ simpleDecorator class ClassWithSimpleDecorator { } let instance_1 = new ClassWithSimpleDecorator ( ) ; let instance_2 = new ClassWithSimpleDecorator ( ) ; console . log ( `instance_1 : ${ instance_1 }` ) ; console . log ( `instance_2 : ${ instance_2 }` ) ; function secondDecorator ( constructor ) { console . log ( 'secondDecorator called.' ) ; } @ simpleDecorator @ secondDecorator class ClassWithMultipleDecorators { } function decoratorFactory ( name ) { return function ( constructor ) { console . log ( `decorator function called with : ${ name }` ) ; } ; } @ decoratorFactory ( 'testName' ) class ClassWithDecoratorFactory { } function classConstructorDec ( constructor ) { console . log ( `constructor : ${ constructor }` ) ; console . log ( `constructor.name : ${ ( < any > constructor ) . name }` ) ; constructor . prototype . testProperty = "testProperty_value" ; } @ classConstructorDec class ClassWithConstructor { } let classConstrInstance = new ClassWithConstructor ( ) ; console . log ( `classConstrInstance.testProperty : ` + `${ ( < any > classConstrInstance ) . testProperty }` ) ; function propertyDec ( target , propertyKey ) { if ( typeof ( target ) === 'function' ) { console . log ( `class name : ${ target . name }` ) ; } else { console . log ( `class name : ` + `${ target . constructor . name }` ) ; } console . log ( `propertyKey : ${ propertyKey }` ) ; } class ClassWithPropertyDec { @ propertyDec name : string ; } class StaticClassWithPropertyDec { @ propertyDec static name : string ; } function methodDec ( target , methodName , descriptor ? ) { console . log ( `target: ${ target }` ) ; console . log ( `methodName : ${ methodName }` ) ; console . log ( `target[methodName] : ${ target [ methodName ] }` ) ; } class ClassWithMethodDec { @ methodDec print ( output ) { console . log ( `ClassWithMethodDec.print` + `(${ output }) called.` ) ; } } function auditLogDec ( target , methodName , descriptor ? ) { let originalFunction = target [ methodName ] ; let auditFunction = function ( ) { console . log ( `auditLogDec : overide of ` + ` ${ methodName } called ` ) ; originalFunction . apply ( this , arguments ) ; } ; target [ methodName ] = auditFunction ; } class ClassWithAuditDec { @ auditLogDec print ( output ) { console . log ( `ClassWithMethodDec.print` + `(${ output }) called.` ) ; } } let auditClass = new ClassWithAuditDec ( ) ; auditClass . print ( "test" ) ; function parameterDec ( target , methodName , parameterIndex ) { console . log ( `target: ${ target }` ) ; console . log ( `methodName : ${ methodName }` ) ; console . log ( `parameterIndex : ${ parameterIndex }` ) ; } class ClassWithParamDec { print ( @ parameterDec value ) { } } import 'reflect-metadata' ; function metadataParameterDec ( target , methodName , parameterIndex ) { let designType = Reflect . getMetadata ( "design:type" , target , methodName ) ; console . log ( `designType: ${ designType }` ) ; let designParamTypes = Reflect . getMetadata ( "design:paramtypes" , target , methodName ) ; console . log ( `paramtypes : ${ designParamTypes }` ) ; let designReturnType = Reflect . getMetadata ( "design:returntype" , target , methodName ) ; console . log ( `returntypes : ${ designReturnType }` ) ; } class ClassWithMetaData { print ( @ metadataParameterDec id , name ) { return 1000 ; } } class Concatenator < T > { concatenateArray ( inputArray ) { let returnString = "" ; for ( let i = 0 ; i < inputArray . length ; i ++ ) { if ( i > 0 ) returnString += "," ; returnString += inputArray [ i ] . toString ( ) ; } return returnString ; } } var stringConcat = new Concatenator < string > ( ) ; var numberConcat = new Concatenator < number > ( ) ; let concatResult = stringConcat . concatenateArray ( [ "first" , "second" , "third" ] ) ; console . log ( concatResult ) ; var stringArray = [ "first" , "second" , "third" ] ; var numberArray = [ 1 , 2 , 3 ] ; var stringResult = stringConcat . concatenateArray ( stringArray ) ; var numberResult = numberConcat . concatenateArray ( numberArray ) ; class MyClass { private _name : string ; constructor ( arg1 ) { this . _name = arg1 + "_MyClass" ; } toString ( ) { return this . _name ; } } let myArray = [ new MyClass ( 1 ) , new MyClass ( 2 ) , new MyClass ( 3 ) ] ; let myArrayConcatentator = new Concatenator < MyClass > ( ) ; let myArrayResult = myArrayConcatentator . concatenateArray ( myArray ) ; console . log ( myArrayResult ) ; enum ClubHomeCountry { England , Germany } interface IFootballClub { getName ( ) : string ; getHomeCountry ( ) : ClubHomeCountry ; } abstract class FootballClub implements IFootballClub { protected _name : string ; protected _homeCountry : ClubHomeCountry ; getName ( ) { return this . _name ; } ; getHomeCountry ( ) { return this . _homeCountry ; } ; } class Liverpool extends FootballClub { constructor ( ) { super ( ) ; this . _name = "Liverpool F.C." ; this . _homeCountry = ClubHomeCountry . England ; } } class BorussiaDortmund extends FootballClub { constructor ( ) { super ( ) ; this . _name = "Borussia Dortmund" ; this . _homeCountry = ClubHomeCountry . Germany ; } } class FootballClubPrinter < T extends IFootballClub > implements IFootballClubPrinter < T > { print ( arg ) { console . log ( ` ${ arg . getName ( ) } is ` + `${ this . IsEnglishTeam ( arg ) }` + ` an English football team.` ) ; } IsEnglishTeam ( arg ) { if ( arg . getHomeCountry ( ) == ClubHomeCountry . England ) return "" ; else return "NOT" ; } } let clubInfo = new FootballClubPrinter ( ) ; clubInfo . print ( new Liverpool ( ) ) ; clubInfo . print ( new BorussiaDortmund ( ) ) ; interface IFootballClubPrinter < T extends IFootballClub > { print ( arg ) ; IsEnglishTeam ( arg ) ; } class FirstClass { id : number ; } class SecondClass { name : string ; } class GenericCreator < T > { create ( arg1 ) { return new arg1 ( ) ; } } var creator1 = new GenericCreator < FirstClass > ( ) ; var firstClass = creator1 . create ( FirstClass ) ; var creator2 = new GenericCreator < SecondClass > ( ) ; var secondClass = creator2 . create ( SecondClass ) ; function delayedResponseWithCallback ( callback ) { function delayedAfterTimeout ( ) { console . log ( `delayedAfterTimeout` ) ; callback ( ) ; } setTimeout ( delayedAfterTimeout , 1000 ) ; } function callDelayedAndWait ( ) { function afterWait ( ) { console . log ( `afterWait` ) ; } console . log ( `calling delayedResponseWithCallback` ) ; delayedResponseWithCallback ( afterWait ) ; console . log ( `after callng delayedResponseWithCallback` ) ; } callDelayedAndWait ( ) ; function fnDelayedPromise ( resolve , reject ) { function afterTimeout ( ) { resolve ( ) ; } setTimeout ( afterTimeout , 2000 ) ; } function delayedResponsePromise ( ) { return new Promise < void > ( fnDelayedPromise ) ; } function delayedPromise ( ) { return new Promise < void > ( ( resolve , reject ) => { function afterTimeout ( ) { resolve ( ) ; } setTimeout ( afterTimeout , 1000 ) ; } ) ; } function callDelayedPromise ( ) { console . log ( `calling delayedPromise` ) ; delayedPromise ( ) . then ( ( ) => { console . log ( `delayedPromise.then()` ) ; } ) ; } callDelayedPromise ( ) ; function errorPromise ( ) { return new Promise < void > ( ( resolve , reject ) => { reject ( ) ; } ) ; } function callErrorPromise ( ) { console . log ( `calling errorPromise` ) ; errorPromise ( ) . then ( ( ) => { console . log ( `no error.` ) ; } ) . catch ( ( ) => { console . log ( `an error occurred` ) ; } ) ; } callErrorPromise ( ) ; function invokeAsync ( success , error ) { } function standardCallback ( ) { function afterCallbackSuccess ( ) { } function afterCallbackError ( ) { } invokeAsync ( afterCallbackSuccess , afterCallbackError ) ; } function usingPromises ( ) { delayedPromise ( ) . then ( ( ) => { } ) . catch ( ( ) => { } ) ; } function delayedPromiseWithParam ( ) { return new Promise < string > ( ( resolve , reject ) => { function afterWait ( ) { resolve ( "resolved_within_promise" ) ; } setTimeout ( afterWait , 2000 ) ; } ) ; } function callPromiseWithParam ( ) { console . log ( `calling delayedPromiseWithParam` ) ; delayedPromiseWithParam ( ) . then ( ( message ) => { console . log ( `Promise.then() returned ${ message } ` ) ; } ) ; } callPromiseWithParam ( ) ; interface IPromiseMessage { message : string ; id : number ; } function promiseWithInterface ( ) { return new Promise < IPromiseMessage > ( ( resolve , reject ) => { resolve ( { message : "test" , id : 1 } ) ; } ) ; } function awaitDelayed ( ) { return new Promise < void > ( ( resolve , reject ) => { function afterWait ( ) { console . log ( `calling resolve` ) ; resolve ( ) ; } setTimeout ( afterWait , 1000 ) ; } ) ; } async function callAwaitDelayed ( ) { console . log ( `call awaitDelayed` ) ; await awaitDelayed ( ) ; console . log ( `after awaitDelayed` ) ; } callAwaitDelayed ( ) ; function awaitError ( ) { return new Promise < string > ( ( resolve , reject ) => { function afterWait ( ) { console . log ( `calling reject` ) ; reject ( "an error occurred" ) ; } setTimeout ( afterWait , 1000 ) ; } ) ; } async function callAwaitError ( ) { console . log ( `call awaitError` ) ; try { await awaitError ( ) ; } catch ( error ) { console . log ( `error returned : ${ error }` ) ; } console . log ( `after awaitDelayed` ) ; } callAwaitError ( ) ; function simplePromises ( ) { delayedPromise ( ) . then ( ( ) => { } ) . catch ( ( ) => { } ) ; } async function usingAsyncSyntax ( ) { try { await delayedPromise ( ) ; } catch ( error ) { } } function asyncWithMessage ( ) { return new Promise < string > ( ( resolve , reject ) => { function afterWait ( ) { resolve ( "resolve_message" ) ; } setTimeout ( afterWait , 1000 ) ; } ) ; } async function awaitMessage ( ) { console . log ( `calling asyncWithMessage` ) ; let message = await asyncWithMessage ( ) ; console . log ( `message returned: ${ message }` ) ; } awaitMessage ( ) ;