3

I found the following example in the Function.name documentation

const o = {
  foo(){}
};
o.foo.name; // "foo";

The problem in typescript (typed here):

    const o: { foo: () => void } = {
        foo: () => {
        }
    };
    o.foo.name;

comes when I want to retrieve o.foo.name, where I will get an error

TS2339 (property "name" does not exist)

How can I deal with it, keeping the object typing? I want to avoid having to cast the property "foo" like (<any>o.foo).name

PS: The use case is to keep the typing for further refactoring. For instance the following is safe to be refactored:

spyOn(o, (<any>o.foo).name)

While this one is not

spyOn(o, "foo")

PS 2: It seems retrieving function name could be problematic on ts: Get name of function in typescript

Flavien Volken
  • 19,196
  • 12
  • 100
  • 133
  • Your code works fine in the latest Typescript, are you posting the complete code ? maybe there is some other issue ? Or are you using a previous version of TS – Titian Cernicova-Dragomir Sep 08 '17 at 09:13
  • @TitianCernicova-Dragomir typescript 2.3.3 but using "target": "es5" into tsconfig.json, which might be the reason why the property name is considered as missing. – Flavien Volken Sep 08 '17 at 09:29

2 Answers2

2

Post ES2015, this:

const o: { foo: () => void } = {
    foo: () => { }
};
console.log(o.foo.name); 

should work just fine.

Check it in the Typescript Playground, and observe the produced JavaScript. You will see the common sections with the foo example you mentioned.

Here is the console, nice and clean:

enter image description here


Pre-ES2015, this wouldn't work and I think you would have to cast it, if targeting post-ES2015 is not an option.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
2

The problem is that this code only works for newer versions of Javascript. If you change the target on the typescript compiler settings to es2015 the problem goes away. If you target es5 the definitions for that version do not include the name property because it might not work on older Javascript runtimes.

If you are ok with targeting es2015, that is ok, if not you should come up with a different solution that works for es5.

If you are targeting an environment that supports this property but you don't yet trust the es2015 implementation for all features, you could just add the the Function interface the missing property. At the top level in one of your files you can redefine the Function interface, and this will be merged into the default definition, adding the extra property:

interface Function {
  /**
   * Returns the name of the function. Function names are read-only and can not be changed.
   */
  readonly name: string;
}
Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357