Typescript: no mapping for this

Created on 25 Nov 2016  路  12Comments  路  Source: microsoft/TypeScript

i want to extend the Object prototype by adding a method that returns a proxified version of any object

Object.defineProperty(Object.prototype, 'proxify, {
   get: function(this: any) {
       // creating a proxy for the darn object
   }
});
const data = {
    name: 'hey',
    value: 123
};
const proxy = data.proxify();
declare global {
   interface Object {
     proxify(): {
        [P in keyof this]: Proxied<this [p]>; // expected to work, actual: A 'this' type is available only in a non-static member of a class or interface.
     }
   }
}

what am i doing wrong?

Design Limitation

Most helpful comment

This is probably the same problem as https://github.com/Microsoft/TypeScript/issues/12349
and is not supported for now because of performance(I guess), reference https://github.com/Microsoft/TypeScript/pull/11929#issuecomment-261744874

All 12 comments

What are the definitions of T and Proxied?

The following works but may not be what you are trying to accomplish

Object.defineProperty(Object.prototype, 'proxify', {
  get: function (this: any) {
      // creating a proxy for the darn object
  }
});
const data = {
    name: 'hey',
    value: 123
};
const proxy = data.proxify();
declare global {

  interface Object {
    proxify(): {
      [P in keyof this]: Proxied<this[P]>;
    };
  }
}
export type Proxied<T> = {
  [P in keyof T]: Proxied<T[P]>;
};

For the sake of argument, isn't a proxy supposed to be transparent? 馃槢

it doesnt really matter what Proxified is, because it breakes at this in [P in keyof this]

dont remember anythhing about them having to look exactly like the original objects (although it wont hurt if they do)

afaict, the only thing proxy should do to be standing between your object and you

T should be read this, fixed

I was being somewhat facetious. Seriously though it does appear that mapping this works correctly.

haven't you seen 'this' type is available only in a non-static member of a class or interface anywhere?

I've seen it a number of times but only in type aliases and other contexts where this would not be available.

declare global {
  interface Object {
    proxify(): {
      [P in keyof this]: Proxied<this[P]>;
    };
  }
}

Doesn't give me that error.

say Proxified <T> = T what can you see wgen you type data.proxify ().? (whar does autocomplete suggest?)

This is what I see
image
which is definitely not what we want here.

Update
It seems that mapping the type of this loses properties added via refinements and annotations. In order to have name and value expanded into the mapping I ended up with

  interface Object {
    proxify<T>(this: T): {
      [P in keyof T]: Proxied<T[P]>
    };
  }

Which works but obviously doesn't map this.

This is probably the same problem as https://github.com/Microsoft/TypeScript/issues/12349
and is not supported for now because of performance(I guess), reference https://github.com/Microsoft/TypeScript/pull/11929#issuecomment-261744874

@HerringtonDarkholme Thanks for providing the clarifying context, it is very helpful. I had totally forgotten that you had already raised an issue requesting this behavior, and I didn't realize the implications, or consider this the same issue.
In #12349, you state the specific problem concisely in the first sentence

it seems this type is resolved too eagerly in parent class.

I suggest we move any further discussion (back) into #12349.

This is not the same as #12349. these are two different issues. the thing is internally, all objects get the apparent members of Object, but it is not that they extend object. there is no distinction if there are no this types, but it breaks if this types are defined on Object since these signatures or properties will not be instantiated with the type of the object you are using.
and yes, the concern is performance. since augmenting Object is not that common scenario.

Was this page helpful?
0 / 5 - 0 ratings