angular-cn/aio/dist/generated/docs/guide/aot-metadata-errors.json

5 lines
23 KiB
JSON

{
"id": "guide/aot-metadata-errors",
"title": "AOT metadata errors",
"contents": "\n\n\n<div class=\"github-links\">\n <a href=\"https://github.com/angular/angular/edit/master/aio/content/guide/aot-metadata-errors.md?message=docs%3A%20describe%20your%20change...\" aria-label=\"Suggest Edits\" title=\"Suggest Edits\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">mode_edit</i></a>\n</div>\n\n\n<div class=\"content\">\n <h1 id=\"aot-metadata-errors\">AOT metadata errors<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#aot-metadata-errors\"><i class=\"material-icons\">link</i></a></h1>\n<p>The following are metadata errors you may encounter, with explanations and suggested corrections.</p>\n<p><a href=\"guide/aot-metadata-errors#expression-form-not-supported\">Expression form not supported</a><br>\n<a href=\"guide/aot-metadata-errors#reference-to-a-local-symbol\">Reference to a local (non-exported) symbol</a><br>\n<a href=\"guide/aot-metadata-errors#only-initialized-variables\">Only initialized variables and constants</a><br>\n<a href=\"guide/aot-metadata-errors#reference-to-a-non-exported-class\">Reference to a non-exported class</a><br>\n<a href=\"guide/aot-metadata-errors#reference-to-a-non-exported-function\">Reference to a non-exported function</a><br>\n<a href=\"guide/aot-metadata-errors#function-calls-not-supported\">Function calls are not supported</a><br>\n<a href=\"guide/aot-metadata-errors#destructured-variable-not-supported\">Destructured variable or constant not supported</a><br>\n<a href=\"guide/aot-metadata-errors#could-not-resolve-type\">Could not resolve type</a><br>\n<a href=\"guide/aot-metadata-errors#name-expected\">Name expected</a><br>\n<a href=\"guide/aot-metadata-errors#unsupported-enum-member-name\">Unsupported enum member name</a><br>\n<a href=\"guide/aot-metadata-errors#tagged-template-expressions-not-supported\">Tagged template expressions are not supported</a><br>\n<a href=\"guide/aot-metadata-errors#symbol-reference-expected\">Symbol reference expected</a><br></p>\n<a id=\"expression-form-not-supported\"></a>\n<h2 id=\"expression-form-not-supported\">Expression form not supported<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#expression-form-not-supported\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>The compiler encountered an expression it didn't understand while evaluating Angular metadata.</em></p>\n</div>\n<p>Language features outside of the compiler's <a href=\"guide/aot-compiler#expression-syntax\">restricted expression syntax</a>\ncan produce this error, as seen in the following example:</p>\n<code-example language=\"ts\">\n// ERROR\nexport class Fooish { ... }\n...\nconst prop = typeof Fooish; // typeof is not valid in metadata\n ...\n // bracket notation is not valid in metadata\n { provide: 'token', useValue: { [prop]: 'value' } };\n ...\n</code-example>\n<p>You can use <code>typeof</code> and bracket notation in normal application code.\nYou just can't use those features within expressions that define Angular metadata.</p>\n<p>Avoid this error by sticking to the compiler's <a href=\"guide/aot-compiler#expression-syntax\">restricted expression syntax</a>\nwhen writing Angular metadata\nand be wary of new or unusual TypeScript features.</p>\n<a id=\"reference-to-a-local-symbol\"></a>\n<h2 id=\"reference-to-a-local-non-exported-symbol\">Reference to a local (non-exported) symbol<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#reference-to-a-local-non-exported-symbol\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Reference to a local (non-exported) symbol 'symbol name'. Consider exporting the symbol.</em></p>\n</div>\n<p>The compiler encountered a referenced to a locally defined symbol that either wasn't exported or wasn't initialized.</p>\n<p>Here's a <code>provider</code> example of the problem.</p>\n<code-example language=\"ts\">\n// ERROR\nlet foo: number; // neither exported nor initialized\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'my-component',\n template: ... ,\n providers: [\n { provide: Foo, useValue: foo }\n ]\n})\nexport class MyComponent {}\n</code-example>\n<p>The compiler generates the component factory, which includes the <code>useValue</code> provider code, in a separate module. <em>That</em> factory module can't reach back to <em>this</em> source module to access the local (non-exported) <code>foo</code> variable.</p>\n<p>You could fix the problem by initializing <code>foo</code>.</p>\n<code-example language=\"ts\">\nlet foo = 42; // initialized\n</code-example>\n<p>The compiler will <a href=\"guide/aot-compiler#code-folding\">fold</a> the expression into the provider as if you had written this.</p>\n<code-example language=\"ts\">\n providers: [\n { provide: Foo, useValue: 42 }\n ]\n</code-example>\n<p>Alternatively, you can fix it by exporting <code>foo</code> with the expectation that <code>foo</code> will be assigned at runtime when you actually know its value.</p>\n<code-example language=\"ts\">\n// CORRECTED\nexport let foo: number; // exported\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'my-component',\n template: ... ,\n providers: [\n { provide: Foo, useValue: foo }\n ]\n})\nexport class MyComponent {}\n</code-example>\n<p>Adding <code>export</code> often works for variables referenced in metadata such as <code>providers</code> and <code>animations</code> because the compiler can generate <em>references</em> to the exported variables in these expressions. It doesn't need the <em>values</em> of those variables.</p>\n<p>Adding <code>export</code> doesn't work when the compiler needs the <em>actual value</em>\nin order to generate code.\nFor example, it doesn't work for the <code>template</code> property.</p>\n<code-example language=\"ts\">\n// ERROR\nexport let someTemplate: string; // exported but not initialized\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'my-component',\n template: someTemplate\n})\nexport class MyComponent {}\n</code-example>\n<p>The compiler needs the value of the <code>template</code> property <em>right now</em> to generate the component factory.\nThe variable reference alone is insufficient.\nPrefixing the declaration with <code>export</code> merely produces a new error, \"<a href=\"guide/aot-metadata-errors#only-initialized-variables\"><code>Only initialized variables and constants can be referenced</code></a>\".</p>\n<a id=\"only-initialized-variables\"></a>\n<h2 id=\"only-initialized-variables-and-constants\">Only initialized variables and constants<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#only-initialized-variables-and-constants\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Only initialized variables and constants can be referenced because the value of this variable is needed by the template compiler.</em></p>\n</div>\n<p>The compiler found a reference to an exported variable or static field that wasn't initialized.\nIt needs the value of that variable to generate code.</p>\n<p>The following example tries to set the component's <code>template</code> property to the value of\nthe exported <code>someTemplate</code> variable which is declared but <em>unassigned</em>.</p>\n<code-example language=\"ts\">\n// ERROR\nexport let someTemplate: string;\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'my-component',\n template: someTemplate\n})\nexport class MyComponent {}\n</code-example>\n<p>You'd also get this error if you imported <code>someTemplate</code> from some other module and neglected to initialize it there.</p>\n<code-example language=\"ts\">\n// ERROR - not initialized there either\nimport { someTemplate } from './config';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'my-component',\n template: someTemplate\n})\nexport class MyComponent {}\n</code-example>\n<p>The compiler cannot wait until runtime to get the template information.\nIt must statically derive the value of the <code>someTemplate</code> variable from the source code\nso that it can generate the component factory, which includes\ninstructions for building the element based on the template.</p>\n<p>To correct this error, provide the initial value of the variable in an initializer clause <em>on the same line</em>.</p>\n<code-example language=\"ts\">\n// CORRECTED\nexport let someTemplate = '&#x3C;h1>Greetings from Angular&#x3C;/h1>';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'my-component',\n template: someTemplate\n})\nexport class MyComponent {}\n</code-example>\n<a id=\"reference-to-a-non-exported-class\"></a>\n<h2 id=\"reference-to-a-non-exported-class\">Reference to a non-exported class<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#reference-to-a-non-exported-class\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Reference to a non-exported class <class name=\"\">. Consider exporting the class.</class></em></p>\n</div>\n<p>Metadata referenced a class that wasn't exported.</p>\n<p>For example, you may have defined a class and used it as an injection token in a providers array\nbut neglected to export that class.</p>\n<code-example language=\"ts\">\n// ERROR\nabstract class MyStrategy { }\n\n ...\n providers: [\n { provide: MyStrategy, useValue: ... }\n ]\n ...\n</code-example>\n<p>Angular generates a class factory in a separate module and that\nfactory <a href=\"guide/aot-compiler#exported-symbols\">can only access exported classes</a>.\nTo correct this error, export the referenced class.</p>\n<code-example language=\"ts\">\n// CORRECTED\nexport abstract class MyStrategy { }\n\n ...\n providers: [\n { provide: MyStrategy, useValue: ... }\n ]\n ...\n</code-example>\n<a id=\"reference-to-a-non-exported-function\"></a>\n<h2 id=\"reference-to-a-non-exported-function\">Reference to a non-exported function<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#reference-to-a-non-exported-function\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Metadata referenced a function that wasn't exported.</em></p>\n</div>\n<p>For example, you may have set a providers <code>useFactory</code> property to a locally defined function that you neglected to export.</p>\n<code-example language=\"ts\">\n// ERROR\nfunction myStrategy() { ... }\n\n ...\n providers: [\n { provide: MyStrategy, useFactory: myStrategy }\n ]\n ...\n</code-example>\n<p>Angular generates a class factory in a separate module and that\nfactory <a href=\"guide/aot-compiler#exported-symbols\">can only access exported functions</a>.\nTo correct this error, export the function.</p>\n<code-example language=\"ts\">\n// CORRECTED\nexport function myStrategy() { ... }\n\n ...\n providers: [\n { provide: MyStrategy, useFactory: myStrategy }\n ]\n ...\n</code-example>\n<a id=\"function-calls-not-supported\"></a>\n<h2 id=\"function-calls-are-not-supported\">Function calls are not supported<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#function-calls-are-not-supported\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function.</em></p>\n</div>\n<p>The compiler does not currently support <a href=\"guide/aot-compiler#function-expression\">function expressions or lambda functions</a>.\nFor example, you cannot set a provider's <code>useFactory</code> to an anonymous function or arrow function like this.</p>\n<code-example language=\"ts\">\n// ERROR\n ...\n providers: [\n { provide: MyStrategy, useFactory: function() { ... } },\n { provide: OtherStrategy, useFactory: () => { ... } }\n ]\n ...\n</code-example>\n<p>You also get this error if you call a function or method in a provider's <code>useValue</code>.</p>\n<code-example language=\"ts\">\n// ERROR\nimport { calculateValue } from './utilities';\n\n ...\n providers: [\n { provide: SomeValue, useValue: calculateValue() }\n ]\n ...\n</code-example>\n<p>To correct this error, export a function from the module and refer to the function in a <code>useFactory</code> provider instead.</p>\n<code-example language=\"ts\">\n// CORRECTED\nimport { calculateValue } from './utilities';\n\nexport function myStrategy() { ... }\nexport function otherStrategy() { ... }\nexport function someValueFactory() {\n return calculateValue();\n}\n ...\n providers: [\n { provide: MyStrategy, useFactory: myStrategy },\n { provide: OtherStrategy, useFactory: otherStrategy },\n { provide: SomeValue, useFactory: someValueFactory }\n ]\n ...\n</code-example>\n<a id=\"destructured-variable-not-supported\"></a>\n<h2 id=\"destructured-variable-or-constant-not-supported\">Destructured variable or constant not supported<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#destructured-variable-or-constant-not-supported\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Referencing an exported destructured variable or constant is not supported by the template compiler. Consider simplifying this to avoid destructuring.</em></p>\n</div>\n<p>The compiler does not support references to variables assigned by <a href=\"https://www.typescriptlang.org/docs/handbook/variable-declarations.html#destructuring\">destructuring</a>.</p>\n<p>For example, you cannot write something like this:</p>\n<code-example language=\"ts\">\n// ERROR\nimport { configuration } from './configuration';\n\n// destructured assignment to foo and bar\nconst {foo, bar} = configuration;\n ...\n providers: [\n {provide: Foo, useValue: foo},\n {provide: Bar, useValue: bar},\n ]\n ...\n</code-example>\n<p>To correct this error, refer to non-destructured values.</p>\n<code-example language=\"ts\">\n// CORRECTED\nimport { configuration } from './configuration';\n ...\n providers: [\n {provide: Foo, useValue: configuration.foo},\n {provide: Bar, useValue: configuration.bar},\n ]\n ...\n</code-example>\n<a id=\"could-not-resolve-type\"></a>\n<h2 id=\"could-not-resolve-type\">Could not resolve type<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#could-not-resolve-type\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>The compiler encountered a type and can't determine which module exports that type.</em></p>\n</div>\n<p>This can happen if you refer to an ambient type.\nFor example, the <code>Window</code> type is an ambient type declared in the global <code>.d.ts</code> file.</p>\n<p>You'll get an error if you reference it in the component constructor,\nwhich the compiler must statically analyze.</p>\n<code-example language=\"ts\">\n// ERROR\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({ })\nexport class MyComponent {\n constructor (private win: Window) { ... }\n}\n</code-example>\n<p>TypeScript understands ambient types so you don't import them.\nThe Angular compiler does not understand a type that you neglect to export or import.</p>\n<p>In this case, the compiler doesn't understand how to inject something with the <code>Window</code> token.</p>\n<p>Do not refer to ambient types in metadata expressions.</p>\n<p>If you must inject an instance of an ambient type,\nyou can finesse the problem in four steps:</p>\n<ol>\n<li>Create an injection token for an instance of the ambient type.</li>\n<li>Create a factory function that returns that instance.</li>\n<li>Add a <code>useFactory</code> provider with that factory function.</li>\n<li>Use <code>@<a href=\"api/core/Inject\" class=\"code-anchor\">Inject</a></code> to inject the instance.</li>\n</ol>\n<p>Here's an illustrative example.</p>\n<code-example language=\"ts\">\n// CORRECTED\nimport { <a href=\"api/core/Inject\" class=\"code-anchor\">Inject</a> } from '@angular/core';\n\nexport const WINDOW = new <a href=\"api/core/InjectionToken\" class=\"code-anchor\">InjectionToken</a>('Window');\nexport function _window() { return window; }\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n ...\n providers: [\n { provide: WINDOW, useFactory: _window }\n ]\n})\nexport class MyComponent {\n constructor (@<a href=\"api/core/Inject\" class=\"code-anchor\">Inject</a>(WINDOW) private win: Window) { ... }\n}\n</code-example>\n<p>The <code>Window</code> type in the constructor is no longer a problem for the compiler because it\nuses the <code>@<a href=\"api/core/Inject\" class=\"code-anchor\">Inject</a>(WINDOW)</code> to generate the injection code.</p>\n<p>Angular does something similar with the <code><a href=\"api/common/DOCUMENT\" class=\"code-anchor\">DOCUMENT</a></code> token so you can inject the browser's <code>document</code> object (or an abstraction of it, depending upon the platform in which the application runs).</p>\n<code-example language=\"ts\">\nimport { <a href=\"api/core/Inject\" class=\"code-anchor\">Inject</a> } from '@angular/core';\nimport { <a href=\"api/common/DOCUMENT\" class=\"code-anchor\">DOCUMENT</a> } from '@angular/common';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({ ... })\nexport class MyComponent {\n constructor (@<a href=\"api/core/Inject\" class=\"code-anchor\">Inject</a>(<a href=\"api/common/DOCUMENT\" class=\"code-anchor\">DOCUMENT</a>) private doc: Document) { ... }\n}\n</code-example>\n<a id=\"name-expected\"></a>\n<h2 id=\"name-expected\">Name expected<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#name-expected\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>The compiler expected a name in an expression it was evaluating.</em></p>\n</div>\n<p>This can happen if you use a number as a property name as in the following example.</p>\n<code-example language=\"ts\">\n// ERROR\nprovider: [{ provide: Foo, useValue: { 0: 'test' } }]\n</code-example>\n<p>Change the name of the property to something non-numeric.</p>\n<code-example language=\"ts\">\n// CORRECTED\nprovider: [{ provide: Foo, useValue: { '0': 'test' } }]\n</code-example>\n<a id=\"unsupported-enum-member-name\"></a>\n<h2 id=\"unsupported-enum-member-name\">Unsupported enum member name<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#unsupported-enum-member-name\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Angular couldn't determine the value of the <a href=\"https://www.typescriptlang.org/docs/handbook/enums.html\">enum member</a> that you referenced in metadata.</em></p>\n</div>\n<p>The compiler can understand simple enum values but not complex values such as those derived from computed properties.</p>\n<code-example language=\"ts\">\n// ERROR\nenum Colors {\n Red = 1,\n White,\n Blue = \"Blue\".length // computed\n}\n\n ...\n providers: [\n { provide: BaseColor, useValue: Colors.White } // ok\n { provide: DangerColor, useValue: Colors.Red } // ok\n { provide: StrongColor, useValue: Colors.Blue } // bad\n ]\n ...\n</code-example>\n<p>Avoid referring to enums with complicated initializers or computed properties.</p>\n<a id=\"tagged-template-expressions-not-supported\"></a>\n<h2 id=\"tagged-template-expressions-are-not-supported\">Tagged template expressions are not supported<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#tagged-template-expressions-are-not-supported\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>Tagged template expressions are not supported in metadata.</em></p>\n</div>\n<p>The compiler encountered a JavaScript ES2015 <a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals\">tagged template expression</a> such as the following.</p>\n<code-example language=\"ts\">\n// ERROR\nconst expression = 'funky';\nconst raw = String.raw`A tagged template ${expression} string`;\n ...\n template: '&#x3C;div>' + raw + '&#x3C;/div>'\n ...\n</code-example>\n<p><a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw\"><code>String.raw()</code></a>\nis a <em>tag function</em> native to JavaScript ES2015.</p>\n<p>The AOT compiler does not support tagged template expressions; avoid them in metadata expressions.</p>\n<a id=\"symbol-reference-expected\"></a>\n<h2 id=\"symbol-reference-expected\">Symbol reference expected<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/aot-metadata-errors#symbol-reference-expected\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p><em>The compiler expected a reference to a symbol at the location specified in the error message.</em></p>\n</div>\n<p>This error can occur if you use an expression in the <code>extends</code> clause of a class.</p>\n<!--\n\nChuck: After reviewing your PR comment I'm still at a loss. See [comment there](https://github.com/angular/angular/pull/17712#discussion_r132025495).\n\n-->\n\n \n</div>\n\n<!-- links to this doc:\n - guide/aot-compiler\n-->\n<!-- links from this doc:\n - api/common/DOCUMENT\n - api/core/Component\n - api/core/Inject\n - api/core/InjectionToken\n - guide/aot-compiler#code-folding\n - guide/aot-compiler#exported-symbols\n - guide/aot-compiler#expression-syntax\n - guide/aot-compiler#function-expression\n - guide/aot-metadata-errors#aot-metadata-errors\n - guide/aot-metadata-errors#could-not-resolve-type\n - guide/aot-metadata-errors#destructured-variable-not-supported\n - guide/aot-metadata-errors#destructured-variable-or-constant-not-supported\n - guide/aot-metadata-errors#expression-form-not-supported\n - guide/aot-metadata-errors#function-calls-are-not-supported\n - guide/aot-metadata-errors#function-calls-not-supported\n - guide/aot-metadata-errors#name-expected\n - guide/aot-metadata-errors#only-initialized-variables\n - guide/aot-metadata-errors#only-initialized-variables-and-constants\n - guide/aot-metadata-errors#reference-to-a-local-non-exported-symbol\n - guide/aot-metadata-errors#reference-to-a-local-symbol\n - guide/aot-metadata-errors#reference-to-a-non-exported-class\n - guide/aot-metadata-errors#reference-to-a-non-exported-function\n - guide/aot-metadata-errors#symbol-reference-expected\n - guide/aot-metadata-errors#tagged-template-expressions-are-not-supported\n - guide/aot-metadata-errors#tagged-template-expressions-not-supported\n - guide/aot-metadata-errors#unsupported-enum-member-name\n - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/raw\n - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_template_literals\n - https://github.com/angular/angular/edit/master/aio/content/guide/aot-metadata-errors.md?message=docs%3A%20describe%20your%20change...\n - https://www.typescriptlang.org/docs/handbook/enums.html\n - https://www.typescriptlang.org/docs/handbook/variable-declarations.html#destructuring\n-->"
}