TypeScript Javascript patterns - meteor

I am busy creating a meteor.d.ts to support my Typescript developments on the Meteor.js platform. Current status can be found here
With that said, I am having issues abstracting two typical javascript patterns.
The first one Template.myTemplate.events(eventMap), where myTemplate can be dynamically created by the user.
Second, the ability to map this to a different interface. Meteor uses the pattern a lot. For instance, when calling Meteor.methods(..methods..), the methods are given access to this.isSimulation() which is not visible anywhere else.
Kind of difficult to explain, so a look at the meteor documentation may help
Any idea how to declare these two patterns?
Thank you.

MyTemplate solution
Provide two interfaces to the user. One that he can use to add new templates to Template. Another to allow him to specify the features of a Template:
interface ITemplate{
}
interface ITemplateStatic{
events:Function;
}
declare var Template:ITemplate;
// the user's code:
interface ITemplate{
myTemplate:ITemplateStatic;
}
Template.myTemplate.events({});
This solution
To answer your second question about this. The only way to do that is to expose the signatures as an interface. It is then the responsibility of the typescript user to get the proper type if he needs it. There is no way to implicity specify the type of this inside a function.
declare module meteor{
interface IMethod{
// A simple sample
isSimulation:boolean;
}
}
declare var Meteor;
// the user experience
Meteor.methods({
foo: function (arg1, arg2) {
var item:meteor.IMethod = this;
console.log(item.isSimulation); // now the signature is enforced
return "some return value";
}
});
Ofcourse I leave the naming convention up to you :)

Related

Differences between different methods of Symfony service collection

For those of you that are familiar with the building of the Symfony container, do you know what is the differences (if any) between
Tagged service Collector using a Compiler pass
Tagged service Collector using the supported shortcut
Service Locator especially, one that collects services by tags
Specifically, I am wondering about whether these methods differ on making these collected services available sooner or later in the container build process. Also I am wondering about the ‘laziness’ of any of them.
It can certainly be confusing when trying to understand the differences. Keep in mind that the latter two approaches are fairly new. The documentation has not quite caught up. You might actually consider making a new project and doing some experimenting.
Approach 1 is basically an "old school" style. You have:
class MyCollector {
private $handlers = [];
public function addHandler(MyHandler $hamdler) {
$handlers[] = $handler;
# compiler pass
$myCollectorDefinition->addMethodCall('addHandler', [new Reference($handlerServiceId)]);
So basically the container will instantiate MyCollector then explicitly call addHandler for each handler service. In doing so, the handler services will be instantiated unless you do some proxy stuff. So no lazy creation.
The second approach provides a somewhat similar capability but uses an iterable object instead of a plain php array:
class MyCollection {
public function __construct(iterable $handlers)
# services.yaml
App\MyCollection:
arguments:
- !tagged_iterator my.handler
One nice thing about this approach is that the iterable actually ends up connecting to the container via closures and will only instantiate individual handlers when they are actually accessed. So lazy handler creation. Also, there are some variations on how you can specify the key.
I might point out that typically you auto-tag your individual handlers with:
# services.yaml
services:
_instanceof:
App\MyHandlerInterface:
tags: ['my.handler']
So no compiler pass needed.
The third approach is basically the same as the second except that handler services can be accessed individually by an index. This is useful when you need one out of all the possible services. And of course the service selected is only created when you ask for it.
class MyCollection {
public function __construct(ServiceLocator $locator) {
$this->locator = $locator;
}
public function doSomething($handlerKey) {
/** #var MyHandlerInterface $handler */
$handler = $serviceLocator->get($handlerKey);
# services.yaml
App\MyCollection:
arguments: [!tagged_locator { tag: 'app.handler', index_by: 'key' }]
I should point out that in all these cases, the code does not actually know the class of your handler service. Hence the var comment to keep the IDE happy.
There is another approach which I like in which you make your own ServiceLocator and then specify the type of object being located. No need for a var comment. Something like:
class MyHandlerLocator extends ServiceLocator
{
public function get($id) : MyHandlerInterface
{
return parent::get($id);
}
}
The only way I have been able to get this approach to work is a compiler pass. I won't post the code here as it is somewhat outside the scope of the question. But in exchange for a few lines of pass code you get a nice clean custom locator which can also pick up handlers from other bundles.

How to get from JavaScript to TypeScript in ASP.Net MVC?

For obvious reasons we want to start with TS instead of JS in our project.
The problem we occurred are the variables who are set in the MVC Views which are set by the Model of the given View.
E.g. tes.cshtml:
#model Testmodel
<script>
var test = {};
var test.myProp = #Model.Testproperty;
<script>
Now in my test.ts I got an error when I try to get the test-variable because my TypeScript file doesn't know it.
Do I have a architecture miss-conception here? Or is there a trick to do that?
To be honest we have around 100 variables set and / or created in RazorViews, most likely a lot of Ressource-Variables from our resx files we would need e.g. in a java-script alert!
You can create definitions file and put all your global declarations there. For example:
declare interface SampleInterface{
myProp:string;
myFunc(someParameter:string):void;
}
declare var test:SampleInterface;
declare var someFunc: () => number;
More info on writing declaration files here.
One way is to attach to Window all your variables or even all your resource variables and after that you can create something like a helper in typescript where you can parse Window.Variables and Window.ResxVariables for your need.
Server-side you will need two dictionaries Variables and ResxVariables which can be statics in your base controller.
Then you will need two methods that will facilitate adding variables to these dictionaries
Variables.Add("Timezone", "GMT+2");
And
ResxVariables.Add("ExitAlert", "Please stay more");
These two methods will be accessible in your controller actions and you will have the possibility to add model properties too.
Then you will need a HtmlHelper that will help you render those dictionaries as objects attached to Window.
You will need to also support clearing those dictionaries when you render a new page or depends on your need.
When i used something like this, we had two dictionaries GlobalVariables and PageVariables. Global wasn't cleared when we render a new page, but PageVariables was.

Meteor: How to point a template prototype at another template?

I have a feeling that it must be possible to point to template helpers from one template to another. Does anyone know how to do this?
I see in the console that I have access to the Template I want: i.e. Template.Users_edit_page.
And it looks like there is a __helpers object with all the templates defined (Template.Users_edit_page.__helpers).
How can I do something along the lines of:
Template.User_form.prototype.helpers = Template.Users_edit_page.helpers__
and then ideally any helper called from the User_form template (which is a child of the Users_edit_page) would run the Users_edit_page template helper
While I fully encourage digging into the internals of a framework to better understand what it is doing, directly linking into implementation details like this (e.g. *.__helpers) is generally not a good idea, as framework developers may change implementation details breaking your code.
When you use the public APIs you can expect less breaking changes, and advanced notice before that happens (e.g., APIs marked for future deprecation).
As I mentioned in your other question the most flexible approach to sharing helpers across templates is with Template.registerHelper.
However if you need something more targeted you can define your functions as standalone javascript functions:
passwordSecure = function(password) {
return password.length > 8;
};
validEmail = function(email) {
return email.contains('#');
};
Then include them as helpers in all the templates you want them in like this:
Template.User_form.helpers({
'passwordSecure': passwordSecure,
'validEmail': validEmail,
});

What is the proper way to inject (via constructor) different types that implement that same interface?

For example, let's say I have an interface 'IFeed' and two concrete types ('Feed1' and 'Feed2') that implement this interface. Now let's say I have a 'FeedManager' type that takes multiple parameters that will get resolved dynamically, two of which are of type 'IFeed' and I'd like both concrete type to be injected via constructor injection, not via manual resolve (I only use resolve once at the composition root). I have a feeling that I should be using a factory but I wanted to see what the proper way of doing this might be. Many thanks in advance.
If you want ALL implementations of IFeed, you can use array syntax in your constructor and then nothing special is needed at type registration time.
container.RegisterType<IFeedManager, FeedManager>();
container.RegisterType<IFeed, FeedA>("FeedA"); // The name doesn't matter
container.RegisterType<IFeed, FeedB>("FeedB"); // The name doesn't matter
Then the manager constructor...
public FeedManager(IFeed[] feeds) {...}
or if you want to add a little flare for calling the constructor directly...
public FeedManager(params IFeed[] feeds) {...}
Assuming you want to determine the actual concrete instances at runtime, you need to use named type registrations and then tell unity which one you want. So, use a factory method to construct the types required and pass those in as parameter overrides. Unity will use the overrides and resolve any remaining dependencies.
// register the types using named registrations
container.RegisterType<IFeedManager,FeedManager>()
container.RegisterType<IFeed, Feed1>("Feed1")
container.RegisterType<IFeed, Feed2>("Feed2")
Assuming your feed manager has the following named constructor parameters
class FeedManager : IFeedManager
{
public FeedManager (IFeed Feed1, IFeed Feed2, string someOtherDependency)
{
}
}
and create your feed manager:
static IFeedManager CreateFeedManager()
{
ParameterOverride feed1 = new ParameterOverride("Feed1"
,_container.Resolve<IFeed>("feed1"));
ParameterOverride feed2 = new DependencyOverride("Feed2"
,_container.Resolve<IFeed>("feed2"));
IFeedManager = _container.Resolve<IFeedManager>(feed1,feed2)
return IFeedManager;
}
Obviously this is overly simplified, but you you insert your own logic to determine which instance is to be resolved and then injected for each of the IFeed instances required by the FeedManager.
With Unity you would do this like so:
container.RegisterType<IFeed, Feed1>("Feed1");
container.RegisterType<IFeed, Feed2>("Feed2");
container.RegisterType<FeedManager>(new InjectionConstructor(new ResolvedParameter<IFeed>("Feed1"),
new ResolvedParameter<IFeed>("Feed2")));
This has now configured Unity so that when it needs to resolve a FeedManager, it will resolve Feed1 for the first parameter and Feed2 for the second parameter.

SimpleIoc (mvvmlight) - how to automatically register all classes implementing a particular interface

Using SimpleIoc I want to automatically register all classes that implement a particular interface. I couldn't see a method on SimpleIoc's container to do this automatically so I put a some code together to iterate through the types to be registered. Unfortunately the code's not happy (see the commented line).
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(typeof(IFoo).IsAssignableFrom);
foreach (var type in types.Where(x=>x.IsClass))
{
container.Register<IFoo, type>(); //this line won't compile as type can't be resolved by the compiler
}
I realise there are less elegant ways of registering classes (such as just hard coding "container.Register" to register each class to the interface) but I'd like to be able to add new implementations without having to keep updating the ioc installer code. It would also be useful, at some point, for me to be able to register classes in other assemblies using the same method.
Any idea what I have to change to make this build (or is there a simpler/more elegant way to do this)?
UPDATE fex posted this comment:
"you can always iterate over types (like you do in your question) and create it with reflection (in your factory class) - (IFoo)Activator.CreateInstance(type); - in fact that's how service locators / ioc containers do it internally (in simplify)."
I've now updated my code to the following which works, with one caveat (the implementations must have a parameterless constructor, and dependencies must therefore be satisfied by the factory that I'm then using to serve up instances implementing IFoo). I've included the factory registration too for info.
Updated code:
// Get the types that implement IFoo...
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(typeof(IFoo).IsAssignableFrom);
// Register these types and use reflection to instantiate each instance...
foreach (var type in types.Where(x=>x.IsClass))
{
var t = type;
container.Register(() => (IFoo)Activator.CreateInstance(t), t.ToString());
}
// Inject all registered instances of IFoo into IFooFactory when it's instantiated.
// Note that instances of IFoo must have their own dependencies satisfied via the
// factory at runtime before being served by the factory.
container.Register<IFooFactory>(
() => new FooFactory(container.GetAllInstances<IFoo>()));

Resources