interface Chan < Env , Protocol > { env_and_protocol : [ Env , Protocol ] ; } class Eps implements HasDual { readonly tag : 'Eps' = 'Eps' ; readonly dual ! : Eps ; } abstract class Send < A , Protocol > implements HasDual { readonly dual ! : Recv < A , Dual < Protocol > > ; readonly tag : 'Send' = 'Send' ; } abstract class Recv < A , Protocol > implements HasDual { readonly dual ! : Send < A , Dual < Protocol > > ; readonly tag : 'Recv' = 'Recv' ; } interface HasDual { dual : HasDual ; } type ExtractProtocol < C > = C extends Chan < infer _ , infer P > ? P : never ; type ExtractEnv < C > = C extends Chan < infer E , infer _ > ? E : never ; type Dual < X > = X extends Send < infer A , infer P > ? Recv < A , P extends HasDual ? P [ 'dual' ] : never > : X extends Recv < infer A , infer P > ? Send < A , P extends HasDual ? P [ 'dual' ] : never > : X extends Eps ? Eps : never ; declare const connect ; declare const srv ; declare const cli ; declare const cli2 ; connect ( srv , cli ) ; connect ( cli , srv ) ; connect ( srv , cli2 ) ; connect ( srv , srv ) ; connect ( cli , cli ) ;