Repository navigation
How to handle this when this is a function #22285
Copy link
Copy link
Closed
Labels
Needs More InfoThe issue still hasn't been fully clarifiedThe issue still hasn't been fully clarified
Description
I have created this playground that shows the problem.
The code looks like this:
export interface Extender<A extends { new (name: string): A }> {
instance: (constructor: { new() }, methods?: {}) => void;
for: (value: any) => A;
symbol: Symbol;
}
export function extend<A extends { new(name: string) }>(
Class: A
): A & Extender<A> {
const name = Class.name;
const Extended = <A & Extender<A>>Class;
let symbol = Symbol(name);
Extended.instance = function(constructor, methods) {
constructor.prototype[symbol] = methods;
};
Extended.symbol = symbol;
Extended.for = function _for(value: any): A {
let i = value[symbol];
return i;
};
const properties = getOwnPropertyDescriptors(Class.prototype);
Object.keys(properties)
.filter(key => key != "constructor")
.forEach(key => {
Extended.prototype[key] = Extended.prototype[key].bind(Extended.for);
});
return Extended;
}
interface Interface<A> {
doSomething: (left: A, right: A) => A;
}
const Implementation = extend(class Implementation<A> implements Interface<A> {
doSomething(left: A, right: A) {
let { doSomething } = this(left);
return doSomething(left, right);
}
});
const { doSomething } = Implementation.prototype;
Implementation.instance(Object, {
doSomething(o1, o2) {
let properties = Object.assign({}, propertiesOf(o1), propertiesOf(o2));
return Object.create(getPrototypeOf(o1), properties);
}
});
doSomething({o: 1}, {b: 2});
How do I handle this on line 44 of the playground
let { doSomething } = this(left);
the call to this will return the specific doSomething.
At the moment I get the error, this lacks a callable signature.
If I add the false this param like this:
doSomething(this: (a: A) => Implementation<A>, left: A, right: A) {
And if I then export the function
export {doSomething} = Implementation.prototype;
And I then try to use the function:
doSomething({o: 1}, {b: 2}); I get the error:
The 'this' context of type 'void' is not assignable to method's 'this' of type '(a: any) => Implementation'.
I realise this is quite contrived but is this too contrived for typescript?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Needs More InfoThe issue still hasn't been fully clarifiedThe issue still hasn't been fully clarified
Activity
dagda1 commentedon Mar 2, 2018
Andy (Andrewkraft) (@Andy-MS)
Ok so here is a jsfiddle of plain js and here is the code:
Class.foris what is is what gets called viathisin this codeThis will return the correct
adddependant if it is aStringor aNumber.This is the code that makes
thisan alias toClass.forSo back to the typescript example:
it would be:
So is this too exotic for typescript to recognise or can I somehow indicate that the
thisin{ add }has this bound by the call in extend with the lineClass.prototype[key] = Class.prototype[key].bind(Class.for)dagda1 commentedon Mar 3, 2018
This is really great but one thing, typescript does currently not support a symbol as an indexer:
So the only way is to give the member
anyas its typeOr is there another way?
dagda1 commentedon Mar 3, 2018
Andy (Andrewkraft) (@Andy-MS) this has been extremely helpful. I'm going to close the issue but is it possible to explain this commented line:
Why is it not just T that is the generic argument?
dagda1 commentedon Mar 5, 2018
Andy (Andrewkraft) (@Andy-MS) one problem with this is approach is that it expects the first argument to be the type argument, i.e.
but what if the type in question is not the first argument in question. Generic types do not exist at runtime in typescript as I've no idea what that would compile to.
I guess I would need to pass something into the
instancefunction to indicate what where to get the type from?