These are chat archives for TypeStrong/atom-typescript

8th
Apr 2015
Matt Traynham
@mtraynham
Apr 08 2015 21:44 UTC
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 UTC
sure...
pretty sure. acan you give me a n example use?
Matt Traynham
@mtraynham
Apr 08 2015 21:47 UTC
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 UTC
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 UTC
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 UTC
thanks! been bashing my head against the desk for about 30 minutes :(
Michael
@michaelsg
Apr 08 2015 21:56 UTC
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 UTC
interesting
Michael
@michaelsg
Apr 08 2015 21:59 UTC
function takeXXX<U>(fn:FnCtor<U>) {

}

class AAA {}
class BBB {}
takeXXX(AAA)
takeXXX(BBB)
Matt Traynham
@mtraynham
Apr 08 2015 21:59 UTC
everything really is described by an interface
hmm you can't do instanceof with that though
Michael
@michaelsg
Apr 08 2015 22:01 UTC
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 UTC
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 UTC
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 UTC
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...