TypeScript missing function name

I have typescript code and am doing metaprogramming where I need to have access to instance.func.name , however typescript omits the function name in compiled JS.

TypeScript:

 class ClassName { // ... func(): ReturnType { // ... } } 

Compiled JavaScript:

 // ... ClassName.prototype.func = function () { // ... }; 

Required JavaScript:

 ClassName.prototype.func = function func() { // ... ^^^^ }; 

Is there a compiler that I don't have, or a keyword that I can use in typescript to execute this?

+6
source share
2 answers

You cannot use TypeScript decorators because function.name is readonly .

There is a hacker way :

 class ClassName { // ... public func = function test() { } public func2() { } } let instance = new ClassName(); console.log("RESULT", instance.func['name']); 

but this is not exactly what you are asking for (i.e., note the missing prototype in the function declaration).

Edit: The TypeScript compiler does not write the function name because there is no processing for SyntaxKind.MethodDeclaration in emitter.ts :

 function shouldEmitFunctionName(node: FunctionLikeDeclaration) { if (node.kind === SyntaxKind.FunctionExpression) { // Emit name if one is present return !!node.name; } if (node.kind === SyntaxKind.FunctionDeclaration) { // Emit name if one is present, or emit generated name in down-level case (for export default case) return !!node.name || languageVersion < ScriptTarget.ES6; } } 

If you want your hands to be dirty, you can update the ./node_modules/typescript/lib/typescript.js file. Just add the last condition:

 function shouldEmitFunctionName(node) { if (node.kind === 173 /* FunctionExpression */) { // Emit name if one is present return !!node.name; } if (node.kind === 213 /* FunctionDeclaration */) { // Emit name if one is present, or emit generated name in down-level case (for export default case) return !!node.name || languageVersion < 2 /* ES6 */; } // MODIFIED if (node.kind === 143 /* MethodDeclaration */) { return true; } } 

and run this to check the change:

 $ node ./node_modules/typescript/lib/typescript.js hello.ts 
+6
source

The solution, which I will not mark as accepted, because it does not provide the name property, but works with any other identifier:

 function named(target: any, key: string) { target[key].functionName = key; } class ClassName { // ... @named func(): ReturnType { // ... } } 

Then select instance.func.functionName .

+5
source

All Articles