Skip to content

Method decorators break with compilerOptions specified #28874

@mrk3767

Description

@mrk3767

Behaviour seems to be different when compilerOptions are included vs not included for decorators. This causes method decorators not to function as expected.

TypeScript Version: 3.2.0-dev.201xxxxx

#!/usr/bin/env node
var ts = require("typescript")
var fs = require("fs")
const shell = require('shelljs')

const original = `
    function logMethod(target, key, descriptor) {
    
        let originalMethod: () => any
        if (descriptor === undefined) {
            descriptor = Object.getOwnPropertyDescriptor(target, key)
        }
        originalMethod = descriptor.value
    
        // editing the descriptor/value parameter
        descriptor.value = function(...args: any[]) {
            console.log('Decorated method ' + key + ' logged with args:[' + args + '}]')
            const result = originalMethod.apply(this, args)
            return result
        }
    
        //Object.defineProperty(target, key, descriptor)
        // return edited descriptor as opposed to overwriting the descriptor
        return descriptor
    }
    
    export class Example {
        @logMethod
        public calc(x: number, y: number): number {
            return x + y;
        }
    }
    
    var main = function () {
        new Example().calc(5, 4);
        console.log("Finished running example");
    }()
`

const fail = (source) => {
    return ts.transpileModule(source, {compilerOptions: {}}).outputText
}

const pass = (s) => {
    return ts.transpileModule(s, {}).outputText
}

(async function () {
    let transpiledWrong, transpiledRight
    await new Promise((resolve, reject) => {
        let filesWritten = 0
        let checkFile = (err) => {
            if( ++filesWritten >= 2 )
                err ? console.log(err) : console.log("file written")
                resolve()
        }

        fs.writeFile('fail.js', transpiledWrong = fail(original), (err) => {
            checkFile(err)
        })
        fs.writeFile('pass.js', transpiledRight = pass(original), (err) => {
            checkFile(err)
        })

    })

    console.log(`
    When transpiled with an empty object passed in for the config, a null is added to the __descriptor() call below

===== Begin file out =====

${transpiledRight}
===== End file out =====

    The expected output is
        
        Decorated method calc logged with args:[5,4}]
        Finished running example
          
    The actual output follows  

${shell.exec('node ./pass.js')}

    When transpiled with an object containing compilerOptions (with or without options) is passed in for the config, a null is missing from the __descriptor() call below

===== Begin file out =====

${transpiledWrong}
===== End file out =====

    The expected output is
        
        Decorated method calc logged with args:[5,4}]
        Finished running example
          
    The actual output follows  

${shell.exec('node ./fail.js')}
    `)
})()

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptDomain: APIRelates to the public API for TypeScript

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions