namespace VisitorWithVariant { class Variant < T1 , T2 , T3 > { readonly value : T1 | T2 | T3 ; readonly index : number ; private constructor ( value , index ) { this . value = value ; this . index = index ; } static make1 < T1 , T2 , T3 > ( value ) { return new Variant < T1 , T2 , T3 > ( value , 0 ) ; } static make2 < T1 , T2 , T3 > ( value ) { return new Variant < T1 , T2 , T3 > ( value , 1 ) ; } static make3 < T1 , T2 , T3 > ( value ) { return new Variant < T1 , T2 , T3 > ( value , 2 ) ; } } function visit < T1 , T2 , T3 > ( variant , func1 , func2 , func3 ) { switch ( variant . index ) { case 0 : func1 ( < T1 > variant . value ) ; break ; case 1 : func2 ( < T2 > variant . value ) ; break ; case 2 : func3 ( < T3 > variant . value ) ; break ; default : throw new Error ( ) ; } } class Renderer { renderPanel ( panel ) { } renderLabel ( label ) { } renderButton ( button ) { } } class XmlSerializer { serializePanel ( panel ) { } serializeLabel ( label ) { } serializeButton ( button ) { } } class Panel { } class Label { } class Button { } let widget = Variant . make1 ( new Panel ( ) ) ; let serializer = new XmlSerializer ( ) ; visit ( widget , ( panel ) => serializer . serializePanel ( panel ) , ( label ) => serializer . serializeLabel ( label ) , ( button ) => serializer . serializeButton ( button ) ) ; }