'this'在TypeScript Property Decorator中未定义

men*_*e23 7 javascript properties this decorator typescript

我正在尝试理解TypeScript装饰器(特别是属性),并根据我看到的一些示例提出了以下代码:

decorator.ts

export function logProperty(target: any, key: string) {

  let val = this[key];

  const getter = () => {
    console.log(`Get: ${key} => ${val}`);
    return val;
  };

  const setter = (newVal) => {
    console.log(`Set: ${key} => ${newVal}`);
    val = newVal;
  };

  if (delete this[key]) {
    Object.defineProperty(target, key, {
      get: getter,
      set: setter,
      enumerable: true,
      configurable: true
    });
  }
}
Run Code Online (Sandbox Code Playgroud)

main.ts

import { logProperty } from './decorators';

class Person {
  @logProperty
  firstName: string;

  @logProperty
  lastName: string;

  constructor(firstName: string, lastName: string) {
    this.firstName = firstName;
    this.lastName = lastName;
  }
}

const foo = new Person('Foo', 'Bar');
Run Code Online (Sandbox Code Playgroud)

我的问题是当我尝试运行时,我得到:

TypeError:无法读取未定义的属性"firstName"

似乎价值this未定义.我错过了什么?

作为参考,我tsconfig.json有:

"target": "es5"
"experimentalDecorators": true
"strict": false
Run Code Online (Sandbox Code Playgroud)

更新8/27 似乎只有在装饰器位于不同的.ts文件中时才会出现此问题.如果将装饰器放在另一个文件中并从另一个文件导入,则会发生错误.但是,将它们全部放在同一个文件中不会导致问题.我只是误解了如何this解释?

CJ *_*ies 1

长话短说:我不确定为什么 OP 的配置不起作用;现在看起来效果很好。请参阅下面的一些暴力测试。

\n\n

猜测

\n\n

我想知道你是否以某种方式发现了错误tsconfig。我查看了您的存储库tsconfig,它看起来是正确的。是否有其他配置文件感染这些运行的可能性?我发现那里没有自动化测试

\n\n

测试

\n\n

我今天遇到了类似的问题,并使用 OP 作为蓝图进行了快速测试。从官方文档中提取了编译器选项提取了编译器选项。

\n\n

decorators.ts

\n\n\n\n
export function logProperty(target: any, key: string) {\n\n    let val = this[key];\n\n    const getter = () => {\n        console.log(`Get: ${key} => ${val}`);\n        return val;\n    };\n\n    const setter = (newVal) => {\n        console.log(`Set: ${key} => ${newVal}`);\n        val = newVal;\n    };\n\n    if (delete this[key]) {\n        Object.defineProperty(target, key, {\n            get: getter,\n            set: setter,\n            enumerable: true,\n            configurable: true\n        });\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

main.ts

\n\n\n\n
import { logProperty } from \'./decorators\';\n\nclass Person {\n    @logProperty\n    firstName: string;\n\n    @logProperty\n    lastName: string;\n\n    constructor(firstName: string, lastName: string) {\n        this.firstName = firstName;\n        this.lastName = lastName;\n    }\n}\n\nconst foo = new Person(\'Foo\', \'Bar\');\n\nfunction logProperty2(target: any, key: string) {\n\n    let val = this[key];\n\n    const getter = () => {\n        console.log(`Get: ${key} => ${val}`);\n        return val;\n    };\n\n    const setter = (newVal) => {\n        console.log(`Set: ${key} => ${newVal}`);\n        val = newVal;\n    };\n\n    if (delete this[key]) {\n        Object.defineProperty(target, key, {\n            get: getter,\n            set: setter,\n            enumerable: true,\n            configurable: true\n        });\n    }\n}\n\nclass Person2 {\n    @logProperty2\n    firstName: string;\n\n    @logProperty2\n    lastName: string;\n\n    constructor(firstName: string, lastName: string) {\n        this.firstName = firstName;\n        this.lastName = lastName;\n    }\n}\n\nconst foo2 = new Person2(\'Foo\', \'Bar\');\n
Run Code Online (Sandbox Code Playgroud)\n\n

index.ts

\n\n\n\n
import * as assert from "assert";\nimport * as shelljs from "shelljs";\n\nconst MODULE_GENERATION = [\n    "CommonJS",\n    "AMD",\n    "System",\n    "UMD",\n    "ES6",\n    "ES2015",\n    "ESNext",\n];\n\nconst TARGETS = [\n    "ES5",\n    "ES2015",\n    "ES2016",\n    "ES2017"\n]\n\nshelljs.exec("tsc --target \'ES5\' --module \'None\' --strict main.ts", { silent: true });\nassert.ok(shelljs.error());\nshelljs.exec("tsc --target \'ES5\' --module \'None\' main.ts", { silent: true });\nassert.ok(shelljs.error());\n\nfor (const moduleGeneration of MODULE_GENERATION) {\n    console.log(`Testing module generation: ${moduleGeneration}`);\n    for (const target of TARGETS) {\n        console.log(`  Building for ${target}`);\n        for (const strict of [true, false]) {\n            console.log(`    Strict mode: ${strict ? \'en\' : \'dis\'}abled`)\n            const command = (\n                `tsc` +\n                ` --module \'${moduleGeneration}\'` +\n                ` --experimentalDecorators` +\n                ` --target \'${target}\'` +\n                ` ${strict ? "--strict" : ""}` +\n                ` main.ts`\n            );\n            const output = shelljs.exec(\n                command,\n                { silent: true },\n            );\n            let symbol;\n            if (strict) {\n                assert.ok(shelljs.error());\n                symbol = \'\xe2\x9c\x96\'\n            } else {\n                assert.strictEqual(0, output.code);\n                symbol = \'\xe2\x9c\x93\'\n            }\n            console.log(`      ${symbol} ${command}`);\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果

\n\n

您可以看到Travis 上的完整构建。

\n\n
Testing module generation: CommonJS\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'CommonJS\' --experimentalDecorators --target \'ES2017\'  main.ts\nTesting module generation: AMD\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'AMD\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'AMD\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'AMD\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'AMD\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'AMD\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'AMD\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'AMD\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'AMD\' --experimentalDecorators --target \'ES2017\'  main.ts\nTesting module generation: System\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'System\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'System\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'System\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'System\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'System\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'System\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'System\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'System\' --experimentalDecorators --target \'ES2017\'  main.ts\nTesting module generation: UMD\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'UMD\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'UMD\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'UMD\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'UMD\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'UMD\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'UMD\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'UMD\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'UMD\' --experimentalDecorators --target \'ES2017\'  main.ts\nTesting module generation: ES6\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES6\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES6\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES6\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES6\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES6\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES6\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES6\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES6\' --experimentalDecorators --target \'ES2017\'  main.ts\nTesting module generation: ES2015\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES2015\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES2015\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES2015\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES2015\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES2015\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES2015\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ES2015\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ES2015\' --experimentalDecorators --target \'ES2017\'  main.ts\nTesting module generation: ESNext\n  Building for ES5\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ESNext\' --experimentalDecorators --target \'ES5\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ESNext\' --experimentalDecorators --target \'ES5\'  main.ts\n  Building for ES2015\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ESNext\' --experimentalDecorators --target \'ES2015\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ESNext\' --experimentalDecorators --target \'ES2015\'  main.ts\n  Building for ES2016\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ESNext\' --experimentalDecorators --target \'ES2016\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ESNext\' --experimentalDecorators --target \'ES2016\'  main.ts\n  Building for ES2017\n    Strict mode: enabled\n      \xe2\x9c\x96 tsc --module \'ESNext\' --experimentalDecorators --target \'ES2017\' --strict main.ts\n    Strict mode: disabled\n      \xe2\x9c\x93 tsc --module \'ESNext\' --experimentalDecorators --target \'ES2017\'  main.ts\n
Run Code Online (Sandbox Code Playgroud)\n\n

坚硬的tsconfig

\n\n

根据这些结果,看起来这是可以的tsconfig

\n\n\n\n
{\n  "compilerOptions": {\n    "target": "es5",\n    "module": "<not None>",\n    "experimentalDecorators": true,\n    "strict": false\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

最后的注释

\n\n\n