Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SUGGESTION] Extracting generic type argument #17479

Closed
npenin opened this issue Jul 28, 2017 · 10 comments
Closed

[SUGGESTION] Extracting generic type argument #17479

npenin opened this issue Jul 28, 2017 · 10 comments
Labels
Duplicate An existing issue was already created

Comments

@npenin
Copy link

npenin commented Jul 28, 2017

The purpose would be to have a class defining some metadata and enriching types on the fly would expose its generic type arguments to be implemented

TypeScript Version: 2.4.0 / nightly (2.5.0-dev.201xxxxx)

Code

class Metadata<T>
{
   constructor()
   {
   }

   public enrich<U>(thing:U):Metadata<T&U>
   {
        //do anything relevant from `thing` like storing its keys
        return <any>this;
   }
}

var meta=new Metadata().enrich({add:true, remove:true})

class Impl implements meta.T
{
/// here add and remove are enforced to be implemented by the typescript compiler
}
@aluanhaddad
Copy link
Contributor

I think mixins may be what you are after.

@npenin
Copy link
Author

npenin commented Jul 30, 2017

Actually, mixins are not powerful enough. Maybe I have over simplified the example :

type Proxy<T, U> = {
    [P in keyof T]: U;
};

class A
{
}

class Metadata<T>
{
   constructor()
   {
   }

   public enrich<TIn>(): <TImpl>(impl: TImpl):Metadata<T&Proxy<U,  (this: T, p: TIn) => void>
   {
        //do anything relevant from `thing` like storing its keys
        return <any>this;
   }
}

var meta=new Metadata().enrich<A>()({add:true, remove:true});

class Impl implements meta.T
{
/// here add and remove are enforced to be implemented by the typescript compiler and both of the methods take an instance of A as a single parameter
}

class MetadataUser
{
      public metadata:meta.T;
}

@mhegazy
Copy link
Contributor

mhegazy commented Aug 25, 2017

the enrich signature you listed makes little sense to me. but seems that you want enrich to return an interaction of Meta and Proxy of some input type parameters. not sure why that is sufficient.

@mhegazy mhegazy added the Needs More Info The issue still hasn't been fully clarified label Aug 25, 2017
@npenin
Copy link
Author

npenin commented Aug 26, 2017

I have oversimplified my example. The purpose would be to have a way to describe multiple types in a row. The actual Meta in my code have more than 4 generic types to define Client and Server two way services. The goal is to have something like WCF in .NET: having an interface to implement and have the networking hidden from a user perpective. Then, from the client interface, I add a way to call the server by building a server proxy, which has almost the same method that the server, but with different parameters and return type (like promised original return type). The same way, from the server, I can build a client proxy from the Meta information. Currently when I want to instanciate a client or a server, I worked around the lack of this feature by having something like the following. In the below sample, I assume Meta has 2 generic types instead of 1.

createServer<TServer, TClient>(meta:Meta<TServer, TClient>, impl:TServer):TServer & {$proxy:()=>TClient}
{
    //Here goes the code to actually build the server from the type definition
}

Does it make sense ?

@mhegazy
Copy link
Contributor

mhegazy commented Aug 29, 2017

and why is intersection types not sufficient?

@npenin
Copy link
Author

npenin commented Aug 30, 2017

for many reasons:

  • it would need to have so much code duplication
  • the ability to describe types programmatically also gives the oportunity to build some documentation or wsdl equivalent
  • above, I have shown the createServer method, I also have the createClient method, where it gives me the possibility to build client with the signature expected by the server, and the other way around, I can build a server proxy with the meta information I have.

To me, the createServer and createClient are against the typescript principle, as the expected goal would be to have classes instead of functions building an objectlike instance :

var meta=new Metadata().serverMethod({add:true, remove:true})
var meta=new Metadata().clientMethod({notify:true})

class MyServer implements meta.TServer
{
}

Another option, without introducing new syntax, but I don't know if it could work, would be to leverage decorators:

var meta=new Metadata().serverMethod({add:true, remove:true})
var meta=new Metadata().clientMethod({notify:true})

@meta.Server
export class MyServer
{
}

Unfortunately, with this option, I guess intellisense (from vscode), would hardly find out the missing methods, and propose implementation of them. There is also some unknown about exporting such classes: would the exported class be the one coded or the one returned by the meta.Server decorator method ?

@kitsonk
Copy link
Contributor

kitsonk commented Aug 30, 2017

Refs #2900 (ambient decorators) but there was a long discussion at #4490 where mixins finally solved our last challenge with it.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 5, 2017

looks like you are looking for dependent types: #17588

@mhegazy mhegazy added Duplicate An existing issue was already created and removed Needs More Info The issue still hasn't been fully clarified labels Sep 5, 2017
@npenin
Copy link
Author

npenin commented Sep 6, 2017

exactly, if the dependent types could be public/exported, then it would perfectly suits my needs.

@mhegazy
Copy link
Contributor

mhegazy commented Sep 20, 2017

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

@mhegazy mhegazy closed this as completed Sep 20, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants