These are chat archives for TypeStrong/atom-typescript

8th
Apr 2015
Matt Traynham
@mtraynham
Apr 08 2015 21:44
Is there a way to pass a constructor to a function?
and have that function's parameter be generically typed (not any)?
Michael
@michaelsg
Apr 08 2015 21:47
sure...
pretty sure. acan you give me a n example use?
Matt Traynham
@mtraynham
Apr 08 2015 21:47
I'm trying to generically do an instanceof check.
As an example:
class Foo {
}
var testInstanceOf = 
    (constructor: any) => 
        (object: any) => 
            object instanceof constructor;
var f: Foo = new Foo();
testInstanceOf(Foo, f); // true
Oop,
Invoked the test function wrong
class Foo {
}
var testInstanceOf = 
    (constructor: any) => 
        (object: any) => 
            object instanceof constructor;
var f: Foo = new Foo();
testInstanceOf(Foo)(f); // true
constructor may be a reserved word, so no worries there. Just wondering what type is the parent to do checks like this
I tried using Object:
var testInstanceOf = 
    (constructor: Object) => 
        (object: any) => 
            object instanceof constructor;
But this throws an error
Matt Traynham
@mtraynham
Apr 08 2015 21:53
As some context, I'm trying to write a Factory Decorator, but I don't think decorators can be typed:
function FactoryDecorator(clazz: typeof Object, factory: (data: Object) => Object): PropertyDecorator {
    return (target: Object, propertyKey: string | symbol) => {
        let property: Object;
        Object.defineProperty(target, <string> propertyKey, {
            get(): Object {
                return property;
            },
            set(value: typeof clazz): any {
                return value ?
                    value instanceof clazz ? value : factory(value) :
                    value;
            }
        });
    };
}
so maybe it's useless
Michael
@michaelsg
Apr 08 2015 21:54
the type describing a constructor looks kinda odd. in TS you can descibe anything with an interface.
let me code it up. :-)
Matt Traynham
@mtraynham
Apr 08 2015 21:55
thanks! been bashing my head against the desk for about 30 minutes :(
Michael
@michaelsg
Apr 08 2015 21:56
Here's the basic definition of a class with a parameterless constructor.
interface FnCtor<T> {
  new: () => T
}
lemme check... ha!
better
interface FnCtor<T> {
  new(): T
}
Matt Traynham
@mtraynham
Apr 08 2015 21:59
interesting
Michael
@michaelsg
Apr 08 2015 21:59
function takeXXX<U>(fn:FnCtor<U>) {

}

class AAA {}
class BBB {}
takeXXX(AAA)
takeXXX(BBB)
Matt Traynham
@mtraynham
Apr 08 2015 21:59
everything really is described by an interface
hmm you can't do instanceof with that though
Michael
@michaelsg
Apr 08 2015 22:01
oops. interfaces have no runtime representation
even in TS, I do give in on making EVERYTHING have a type signature, and I do try hard. Things like decorators are pretty low level. That's when I thnk it's ok. to give in and accept the dreaded any.
so are you using the --emitDecoratorMetadata when you compile?
Matt Traynham
@mtraynham
Apr 08 2015 22:08
oh that's an interesting flag
so my goal is to simplify set/get calls using decorators
in some cases, I'll use a factory to create an object if it's not currently an instanceof a particular prototype
so as an example:
Michael
@michaelsg
Apr 08 2015 22:14
that might help you. Check out these:
The PR recently pulled into TS master (a couple days ago): Microsoft/TypeScript#2589
There's a link in there to here: https://github.com/rbuckton/ReflectDecorators
With that flag, the compiler emits a do-nothing pollyfill for the Reflect api (see above).
If you include the Reflect.js in your app before all else loads, the extra type info will get associated and your decorator can use the Reflect api to read it at runtime.
Not sure this is exactly what you need.
Matt Traynham
@mtraynham
Apr 08 2015 22:14
function FactoryParser(clazz: any, factory: (data: Object) => any): PropertyDecorator {
    return (target: Object, propertyKey: string) => {
        let property: Object;
        Object.defineProperty(target, propertyKey, {
            get(): Object {
                return property;
            },
            set(value: Object): void {
                if (value) {
                    if (!(value instanceof clazz)) {
                        property = factory(value);
                    }
                }
                property = value;
            }
        });
    };
}

class Bar { }
class Foo {
    @FactoryParser(Bar, (obj: any) => new Bar(obj))
    public bar: Bar;
}
It kind of sounds like it is...