2015-11-11 6 views
6

Ho un codice dattiloscritto e sto eseguendo alcune metaprogrammazione in cui devo essere in grado di accedere a instance.func.name, tuttavia TypeScript omette il nome della funzione nel JS compilato.TypeScript non fornisce il nome della funzione

dattiloscritto:

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

Compilato JavaScript:

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

desiderata JavaScript:

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

C'è un'opzione del compilatore mi manca, o una parola chiave che posso utilizzare in TypeScript per realizzare questo?

risposta

5

Una soluzione, una volta che non è contrassegnare come accettata, perché non fornisce la proprietà name, ma funziona con qualsiasi altro mezzo identificativo è il seguente:

function named(target: any, key: string) { 
    target[key].functionName = key; 
} 

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

quindi accedere instance.func.functionName .

+0

abbastanza intelligente – robsonrosa

6

Non è possibile utilizzare decoratori TypeScript perché function.name è readonly property.

C'è un hacky way:

class ClassName { 
    // ... 
    public func = function test() { 

    } 

    public func2() { 

    } 
} 

let instance = new ClassName(); 

console.log("RESULT", instance.func['name']); 

ma non è esattamente quello che chiedete (cioè nota il prototipo mancante nella dichiarazione di funzione).

Edit: dattiloscritto compilatore non scrivere il nome della funzione, perché non v'è alcun trattamento per 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; 
    } 
} 

Se si vuole sporcarsi le mani, quindi è possibile aggiornare ./node_modules/typescript/lib/typescript.js file. Basta aggiungere l'ultima condizione:

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; 
    }               
} 

ed eseguire questo per testare il cambiamento: soluzione

$ node ./node_modules/typescript/lib/typescript.js hello.ts 
+0

Sì, vicino ma non del tutto (manca proto). Non sapevo che TypeScript supportava invece le proprietà ES2016. Maneggevole. – azz

+0

Ho scavato ancora un po '. Si prega di consultare l'aggiornamento. –

+0

Bella scoperta, avere un upvote. Ho comunque bisogno di inserire TypeScript per questo progetto. :( – azz