TypeScript不提供函数名称

azz*_*azz 7 javascript reflection typescript

我有一些打字稿代码,我正在做一些我需要能够访问的元编程instance.func.name,但TypeScript省略了编译JS中的函数名.

打字稿:

class ClassName {
    // ... 
    func(): ReturnType {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

编译的JavaScript:

// ...
ClassName.prototype.func = function () {
    // ... 
};
Run Code Online (Sandbox Code Playgroud)

期望的JavaScript:

ClassName.prototype.func = function func() {
    // ...                          ^^^^
};
Run Code Online (Sandbox Code Playgroud)

是否存在我缺少的编译器选项,或者我可以在TypeScript中使用的关键字来实现此目的?

azz*_*azz 7

一个解决方案,我不会将其标记为已接受,因为它不提供name属性,但与任何其他标识符一起使用如下:

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

class ClassName {
    // ... 
    @named
    func(): ReturnType {
         // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

然后访问instance.func.functionName.


Mar*_*cka 7

由于function.namereadonly属性,因此无法使用TypeScript装饰器.

有一种hacky方式:

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

    }

    public func2() {

    }
}

let instance = new ClassName();

console.log("RESULT", instance.func['name']);
Run Code Online (Sandbox Code Playgroud)

但它并不完全是你要求的(即注意功能声明中缺少的原型).

编辑: TypeScript编译器不写函数名称,因为SyntaxKind.MethodDeclarationemitter.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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果你想弄脏手,那么你可以更新./node_modules/typescript/lib/typescript.js文件.只需添加最后一个条件:

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;
    }                                                        
}
Run Code Online (Sandbox Code Playgroud)

并运行它来测试更改:

$ node ./node_modules/typescript/lib/typescript.js hello.ts
Run Code Online (Sandbox Code Playgroud)