Typescript: How to create interface based off of enum - node.js

I have an enum EEndpoints that maps to string addresses of local nodes. I want to create an interface/hard-coded object based off of this enum. This is my idea:
export enum EEndpoints
{
MY_REMOTE_NODE = "MY_REMOTE_NODE",
}
export interface EndpointAddresses
{
PublisherAddress: string,
RequestAddress: string,
}
export interface EndpointAddressList
{
for (key in EEndpoints)
{
[key] = EndpointAddresses;
}
}
In my code I would then be required to define a constant that implements EndpointAddressList:
const RemoteNodeEndpoints: EndpointAddressList =
{
MY_REMOTE_NODE: {
PublisherAddress: "tcp://127.0.0.1:3000",
RequestAddress: "tcp://127.0.0.1:3001",
},
}
Alternatively, it would also be nice to define an interface that itself implements EndpointAddressList, i.e:
interface ImplementedEndpointAddressList
{
MY_REMOTE_NODE: {
PublisherAddress: "tcp://127.0.0.1:3000",
RequestAddress: "tcp://127.0.0.1:3001",
},
}
I'm also open to feedback if using an enum as the basis for properties in an interface is an anti-pattern. However, it does seem like a useful tool for me to centrally define a set of hard-coded endpoints and then have compile time checks that I have configured the sub-properties of those endpoints.

Related

How can I create an enum from an interface in Typescript

I am building a backend using Parse Server written in Typescript. Parse uses "magic strings" in many places and I am trying to avoid them.
For example, if I have a Parse Class named Item and it has an attribute color, I would get the property the following way: myItem.get('color').
I am hoping to make this type safe and use an enum for color instead of the string itself. I already have an interface defined for all attributes of Item like so:
import { Attributes, Object } from 'parse'
export interface ItemAttributes extends Attributes {
color: string
size: number
enabled: boolean
}
export class Item extends Object<ItemAttributes> {
constructor (data?: Partial<ItemAttributes>) {
super('Item', data as ItemAttributes)
}
}
Is there a way to generate an enum from the ItemAttributes interface in Typescript without having to create a new enum for every Parse Class like so?
export enum ItemKeys {
color = 'color'
size = 'size'
enabled = 'enabled'
}
As a result I am hoping to be able to use my new enum in the Parse getter like this:
myItem.get(ItemKeys.color)

Casting Dynamic to an other class

I would like to know if that's possible to cast a Dynamic to an other class (partially or totally)
For example, this code breaks :
class Test {
public function new() {}
public var id: String;
}
class Main {
public static function main() {
var x:Dynamic = JsonParser.parse("{\"id\":\"sdfkjsdflk\"}");
var t:Test = cast(x, Test);
}
}
with the following message
Class cast error
However, my "Test" class has an "id" field like the dynamic object. (That's an example, my use case is more complexe than that ^^)
So, I don't understand how to get an object from my Dynamic one.
This isn't exactly casting a dynamic to a class instance but may accomplish the same thing:
create an empty instance of the class with Type.createEmptyInstance
set all of the fields from the Dynamic object on the new class instance using Reflect
Example:
import haxe.Json;
class Test {
public function new() {}
public var id: String;
}
class Main {
public static function main() {
var x:Dynamic = Json.parse("{\"id\":\"sdfkjsdflk\"}");
var t:Test = Type.createEmptyInstance(Test);
for (field in Type.getInstanceFields(Test))
if (Reflect.hasField(x, field))
Reflect.setProperty(t, field, Reflect.getProperty(x, field));
trace(t.id);
}
}
You could use typedef
typedef Test = {
public var id: String;
}
class Main {
public static function main() {
var t:Test = JsonParser.parse("{\"id\":\"sdfkjsdflk\"}");
}
}
Json.parse returns anonymous structure(implementation platform dependent), typed as Dynamic. There isn't a single chance to cast it to anything but Dynamic, unless Json.parse returns Int, Float or String, which some parsers permit, but which isn't actually permitted by JSON specification.
That is this way because, the operation of casting doesn't check what fields some object have. Operation of casting only checks if the object is an instance of class you are casting to. Obviously, anonymous structure can't be an instance of any class(inside haxe abstractions at least).
However, the right way to perform the thing you seem to be trying to perform is the way stated by #Ben Morris, in his answer.

Groovy - can a method defined in an Interface have default values?

If the following is entered in Eclipse/STS (with groovy):
interface iFaceWithAnIssue {
def thisIsFine(a,b,c)
def thisHasProblems(alpha='va')
}
The only line that complains is the one trying to use a default value. I can not tell from the codehaus site if this is supported or not.
The IDE error is:
Groovy:Cannot specify default value for method parameter
So this makes me think it is not supported. As there will be multiple implementations, I wanted to use an interface here. I don't really need the default value in the interface, but there is an error trying to fulfill the interface contract if the implementation class then tries to default this argument. Is there any way?
No, you cannot.
When you define a default value, Groovy actually creates multiple methods in your class, so for example:
class Test {
void something( a=false ) {
println a
}
}
Actually creates
public void something(java.lang.Object a) {
this.println(a)
}
and
public void something() {
this.something(((false) as java.lang.Object))
}
This can't be done as it stands in Interfaces.
You could do:
interface iFaceWithAnIssue {
def thisHasProblems()
def thisHasProblems(alpha)
}
Then
class Test implements iFaceWithAnIssue {
// This covers both Inteface methods
def thisHasProblems(alpha='va') {
// do something
}
}

looking for a proper way to implement my generic factory

I'm struggling with implementing a factory object. Here's the context :
I've in a project a custom store. In order to read/write records, I've written this code in a POCO model/separated repository:
public class Id { /* skip for clarity*/} // My custom ID representation
public interface IId
{
Id Id { get; set; }
}
public interface IGenericRepository<T> where T : IId
{
T Get(Id objectID);
void Save(T #object);
}
public interface IContext
{
TRepository GetRepository<T, TRepository>()
where TRepository : IGenericRepository<T>
where T:IId;
IGenericRepository<T> GetRepository<T>()
where T:IId;
}
My IContext interface defines two kind of repositories.
The former is for standard objects with only get/save methods, the later allows me to define specifics methods for specific kind of objects. For example :
public interface IWebServiceLogRepository : IGenericRepository<WebServiceLog>
{
ICollection<WebServiceLog> GetOpenLogs(Id objectID);
}
And it the consuming code I can do one of this :
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID); --> specific operation
Because most of objects repository are limited to get and save operations, I've written a generic repository :
public class BaseRepository<T> : IGenericRepository<T>
where T : IId, new()
{
public virtual T Get(Id objectID){ /* provider specific */ }
public void Save(T #object) { /* provider specific */ }
}
and, for custom ones, I simply inherits the base repository :
internal class WebServiceLogRepository: BaseRepository<WebServiceLog>, IWebServiceLogRepository
{
public ICollection<WebServiceLog> GetByOpenLogsByRecordID(Id objectID)
{
/* provider specific */
}
}
Everything above is ok (at least I think it's ok). I'm now struggling to implement the MyContext class. I'm using MEF in my project for other purposes. But because MEF doesn't support (yet) generic exports, I did not find a way to reach my goal.
My context class is looking like by now :
[Export(typeof(IContext))]
public class UpdateContext : IContext
{
private System.Collections.Generic.Dictionary<Type, object> m_Implementations;
public UpdateContext()
{
m_Implementations = new System.Collections.Generic.Dictionary<Type, object>();
}
public TRepository GetRepository<T, TRepository>()
where T : IId
where TRepository : IGenericRepository<T>
{
var tType = typeof(T);
if (!m_Implementations.ContainsKey(tType))
{
/* this code is neither working nor elegant for me */
var resultType = AppDomain.CurrentDomain.GetAssemblies().SelectMany(
(a) => a.GetTypes()
).Where((t)=>t.GetInterfaces().Contains(typeof(TRepository))).Single();
var result = (TRepository)resultType.InvokeMember("new", System.Reflection.BindingFlags.CreateInstance, null, null, new object[] { this });
m_Implementations.Add(tType, result);
}
return (TRepository)m_Implementations[tType];
}
public IGenericRepository<T> GetRepository<T>() where T : IId
{
return GetRepository<T, IGenericRepository<T>>();
}
}
I'd appreciate a bit of help to unpuzzle my mind with this quite common scenario
Not sure if I've understood you correctly, but I think you're perhaps over complicating things. To begin with, make sure you've designed your code independent of any factory or Dependency Injection framework or composition framework.
For starters lets look at what you want your calling code to look like, this is what you said:
MyContext.GetRepository<Customer>().Get(myID); --> standard get
MyContext.GetRepository<WebServiceLog, IWebServiceLogRepository>().GetOpenLogs(myID);
You don't have to agree with my naming choices below, but it indicates what I undertand from your code, you can tell me if I'm wrong. Now, I feel like the calling would be simpler like this:
RepositoryFactory.New<IRepository<Customer>>().Get(myId);
RepositoryFactory.New<IWebServiceLogRepository>().GetOpenLogs(myId);
Line 1:
Because the type here is IRepository it's clear what the return type is, and what the T type is for the base IRepository.
Line 2:
The return type here from the factory is IWebServiceLogRepository. Here you don'y need to specify the entity type, your interface logically already implements IRepository. There's no need to specify this again.
So your interface for these would look like this:
public interface IRepository<T>
{
T Get(object Id);
T Save(T object);
}
public interface IWebServiceLogRepository: IRepository<WebServiceLog>
{
List<WebServiceLog> GetOpenLogs(object Id);
}
Now I think the implementations and factory code for this would be simpler as the factory only has to know about a single type. On line 1 the type is IRepository, and in line 2, IWebServiceLogRepository.
Try that, and try rewriting your code to simply find classes that implement those types and instantiating them.
Lastly, in terms of MEF, you could carry on using that, but Castle Windsor would really make things much simpler for you, as it lets you concentrate on your architecture and code design, and its very very simple to use. You only ever reference Castle in your app startup code. The rest of your code is simply designed using the Dependency Injection pattern, which is framework agnostic.
If some of this isn't clear, let me know if you'd like me to update this answer with the implementation code of your repositories too.
UPDATE
and here's the code which resolves the implementations. You were making it a bit harder for yourself by not using the Activator class.
If you use Activator and use only one Generic parameter as I've done in the method below, you should be ok. Note the code's a bit rough but you get the idea:
public static T GetThing<T>()
{
List<Type> assemblyTypes = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes()).ToList();
Type interfaceType = typeof(T);
if(interfaceType.IsGenericType)
{
var gens = interfaceType.GetGenericArguments();
List<Type> narrowed = assemblyTypes.Where(p => p.IsGenericType && !p.IsInterface).ToList();
var implementations = new List<Type>();
narrowed.ForEach(t=>
{
try
{
var imp = t.MakeGenericType(gens);
if(interfaceType.IsAssignableFrom(imp))
{
implementations.Add(imp);
}
}catch
{
}
});
return (T)Activator.CreateInstance(implementations.First());
}
else
{
List<Type> implementations = assemblyTypes.Where(p => interfaceType.IsAssignableFrom(p) && !p.IsInterface).ToList();
return (T)Activator.CreateInstance(implementations.First());
}
}

Use interface to convert collection of objects with extensions and lambdas

I have some objects like user, address and so on, and Im converting them to business objects using extension methods:
public static UserModel ToPresentationForm(this User pUser)
{
return new UserModel
{
...
map data
...
};
}
Also I need to convert strongly typed collections and usually I have the following code:
public static List<UserModel> ToPresentationForm(this List<User> pUserColl)
{
return pUserColl.Select(x => x.ToPresentationForm()).ToList();
}
I was thinking, what if I add some interface, like IPresentationForms and will be able to use it, to write method like
public static List<T> ToPresentationForm(this List<IPresentationForms> pTemplate)
{
return pUserColl.Select(x => x.ToPresentationForm()).ToList();
}
Not sure how to provide parameter to method type to make it generic. So the actual question is, how to do that.
P.S. Im using C# 4.0
Unfortunately since there is likely no relationship between User and UserModel, there is no way to create an interface to do what you want.
On the other hand, let's say that User and UserModel both implement the IUser interface. Then you could have an interface like this:
interface IPresentationForms<T>
{
T ToPresentationForm();
}
And you could define User like this:
class User: IUser, IPresentationForms<IUser>
{
public IUser ToPresentationForm()
{
return new UserModel(...);
}
.... // implement IUser
}
That could enable you to define ToPresentationForm something like this:
public static List<T> ToPresentationForm<T>(this IEnumerable<T> pTemplate)
where T : IPresentationForms<T>
{
return pTemplate.Select(x => x.ToPresentationForm()).ToList();
}
That's a lot of work to do to avoid a few extra methods.

Resources