function printGeneric < T > ( value ) { console . log ( `typeof T is : ${ typeof value }` ) ; console . log ( `value is : ${ value }` ) ; } printGeneric ( 1 ) ; printGeneric ( "test" ) ; printGeneric ( true ) ; printGeneric ( ( ) => { } ) ; printGeneric ( { id : 1 } ) ; printGeneric < string > ( "test" ) ; function usingTwoTypes < A , B > ( first , second ) { } usingTwoTypes < number , string > ( 1 , "test" ) ; usingTwoTypes ( 1 , "test" ) ; usingTwoTypes < boolean , boolean > ( true , false ) ; usingTwoTypes ( "first" , "second" ) ; interface IName { name : string ; print ( ) : void ; } interface INameDescr extends IName { descr : String ; } class Printer < T extends INameDescr > { print ( items ) { for ( let item of items ) { console . log ( `array item : ${ item . print }` ) ; } } } class Concatenator < T extends Array < string > | Array < number > > { public concatenateArray ( items ) { let returnString = "" ; for ( let i = 0 ; i < items . length ; i ++ ) { returnString += i > 0 ? "," : "" ; returnString += items [ i ] . toString ( ) ; } return returnString ; } } let concator = new Concatenator ( ) ; let concatResult = concator . concatenateArray ( [ "first" , "second" , "third" ] ) ; console . log ( `concatResult = ${ concatResult }` ) ; concatResult = concator . concatenateArray ( [ 1000 , 2000 , 3000 ] ) ; console . log ( `concatResult = ${ concatResult }` ) ; interface IPrintId { id : number ; print ( ) : void ; } interface IPrintName { name : string ; print ( ) : void ; } function useT < T extends IPrintId | IPrintName > ( item ) { item . print ( ) ; } function printProperty < T , K extends keyof T > ( object , key ) { let propertyValue = object [ key ] ; console . log ( `object[${ key }] = ${ propertyValue }` ) ; } let obj1 = { id : 1 , name : "myName" , print ( ) { console . log ( `${ this . id }` ) ; } } ; printProperty ( obj1 , "id" ) ; printProperty ( obj1 , "name" ) ; printProperty ( obj1 , "print" ) ; interface IPrint { print ( ) : void ; } interface ILogInterface < T extends IPrint > { logToConsole ( iPrintObj ) : void ; } class LogClass < T extends IPrint > implements ILogInterface < T > { logToConsole ( iPrintObj ) { iPrintObj . print ( ) ; } } let printObject = { print ( ) { console . log ( `printObject.print() called` ) ; } } ; let logClass = new LogClass ( ) ; logClass . logToConsole ( printObject ) ; class ClassA { id : number = 1 ; } class ClassB { } function createClassInstance < T > ( arg1 ) { return new arg1 ( ) ; } let classAInstance = createClassInstance ( ClassA ) ; console . log ( `${ JSON . stringify ( classAInstance ) }` ) ;