UNPKG

14.4 kBTypeScriptView Raw
1/**
2 * @license
3 * Copyright Google LLC All Rights Reserved.
4 *
5 * Use of this source code is governed by an MIT-style license that can be
6 * found in the LICENSE file at https://angular.io/license
7 */
8import { AbsoluteSourceSpan, BoundTarget, DirectiveMeta, ParseSourceSpan, SchemaMetadata } from '@angular/compiler';
9import ts from 'typescript';
10import { ErrorCode } from '../../diagnostics';
11import { Reference } from '../../imports';
12import { ClassPropertyMapping, DirectiveTypeCheckMeta, HostDirectiveMeta, InputMapping } from '../../metadata';
13import { ClassDeclaration } from '../../reflection';
14/**
15 * Extension of `DirectiveMeta` that includes additional information required to type-check the
16 * usage of a particular directive.
17 */
18export interface TypeCheckableDirectiveMeta extends DirectiveMeta, DirectiveTypeCheckMeta {
19 ref: Reference<ClassDeclaration>;
20 queries: string[];
21 inputs: ClassPropertyMapping<InputMapping>;
22 outputs: ClassPropertyMapping;
23 isStandalone: boolean;
24 hostDirectives: HostDirectiveMeta[] | null;
25 decorator: ts.Decorator | null;
26}
27export type TemplateId = string & {
28 __brand: 'TemplateId';
29};
30/**
31 * A `ts.Diagnostic` with additional information about the diagnostic related to template
32 * type-checking.
33 */
34export interface TemplateDiagnostic extends ts.Diagnostic {
35 /**
36 * The component with the template that resulted in this diagnostic.
37 */
38 componentFile: ts.SourceFile;
39 /**
40 * The template id of the component that resulted in this diagnostic.
41 */
42 templateId: TemplateId;
43}
44/**
45 * A `TemplateDiagnostic` with a specific error code.
46 */
47export type NgTemplateDiagnostic<T extends ErrorCode> = TemplateDiagnostic & {
48 __ngCode: T;
49};
50/**
51 * Metadata required in addition to a component class in order to generate a type check block (TCB)
52 * for that component.
53 */
54export interface TypeCheckBlockMetadata {
55 /**
56 * A unique identifier for the class which gave rise to this TCB.
57 *
58 * This can be used to map errors back to the `ts.ClassDeclaration` for the component.
59 */
60 id: TemplateId;
61 /**
62 * Semantic information about the template of the component.
63 */
64 boundTarget: BoundTarget<TypeCheckableDirectiveMeta>;
65 pipes: Map<string, Reference<ClassDeclaration<ts.ClassDeclaration>>>;
66 /**
67 * Schemas that apply to this template.
68 */
69 schemas: SchemaMetadata[];
70 isStandalone: boolean;
71}
72export interface TypeCtorMetadata {
73 /**
74 * The name of the requested type constructor function.
75 */
76 fnName: string;
77 /**
78 * Whether to generate a body for the function or not.
79 */
80 body: boolean;
81 /**
82 * Input, output, and query field names in the type which should be included as constructor input.
83 */
84 fields: {
85 inputs: string[];
86 outputs: string[];
87 queries: string[];
88 };
89 /**
90 * `Set` of field names which have type coercion enabled.
91 */
92 coercedInputFields: Set<string>;
93}
94export interface TypeCheckingConfig {
95 /**
96 * Whether to check the left-hand side type of binding operations.
97 *
98 * For example, if this is `false` then the expression `[input]="expr"` will have `expr` type-
99 * checked, but not the assignment of the resulting type to the `input` property of whichever
100 * directive or component is receiving the binding. If set to `true`, both sides of the assignment
101 * are checked.
102 *
103 * This flag only affects bindings to components/directives. Bindings to the DOM are checked if
104 * `checkTypeOfDomBindings` is set.
105 */
106 checkTypeOfInputBindings: boolean;
107 /**
108 * Whether to honor the access modifiers on input bindings for the component/directive.
109 *
110 * If a template binding attempts to assign to an input that is private/protected/readonly,
111 * this will produce errors when enabled but will not when disabled.
112 */
113 honorAccessModifiersForInputBindings: boolean;
114 /**
115 * Whether to use strict null types for input bindings for directives.
116 *
117 * If this is `true`, applications that are compiled with TypeScript's `strictNullChecks` enabled
118 * will produce type errors for bindings which can evaluate to `undefined` or `null` where the
119 * inputs's type does not include `undefined` or `null` in its type. If set to `false`, all
120 * binding expressions are wrapped in a non-null assertion operator to effectively disable strict
121 * null checks. This may be particularly useful when the directive is from a library that is not
122 * compiled with `strictNullChecks` enabled.
123 *
124 * If `checkTypeOfInputBindings` is set to `false`, this flag has no effect.
125 */
126 strictNullInputBindings: boolean;
127 /**
128 * Whether to check text attributes that happen to be consumed by a directive or component.
129 *
130 * For example, in a template containing `<input matInput disabled>` the `disabled` attribute ends
131 * up being consumed as an input with type `boolean` by the `matInput` directive. At runtime, the
132 * input will be set to the attribute's string value, which is an empty string for attributes
133 * without a value, so with this flag set to `true`, an error would be reported. If set to
134 * `false`, text attributes will never report an error.
135 *
136 * Note that if `checkTypeOfInputBindings` is set to `false`, this flag has no effect.
137 */
138 checkTypeOfAttributes: boolean;
139 /**
140 * Whether to check the left-hand side type of binding operations to DOM properties.
141 *
142 * As `checkTypeOfBindings`, but only applies to bindings to DOM properties.
143 *
144 * This does not affect the use of the `DomSchemaChecker` to validate the template against the DOM
145 * schema. Rather, this flag is an experimental, not yet complete feature which uses the
146 * lib.dom.d.ts DOM typings in TypeScript to validate that DOM bindings are of the correct type
147 * for assignability to the underlying DOM element properties.
148 */
149 checkTypeOfDomBindings: boolean;
150 /**
151 * Whether to infer the type of the `$event` variable in event bindings for directive outputs or
152 * animation events.
153 *
154 * If this is `true`, the type of `$event` will be inferred based on the generic type of
155 * `EventEmitter`/`Subject` of the output. If set to `false`, the `$event` variable will be of
156 * type `any`.
157 */
158 checkTypeOfOutputEvents: boolean;
159 /**
160 * Whether to infer the type of the `$event` variable in event bindings for animations.
161 *
162 * If this is `true`, the type of `$event` will be `AnimationEvent` from `@angular/animations`.
163 * If set to `false`, the `$event` variable will be of type `any`.
164 */
165 checkTypeOfAnimationEvents: boolean;
166 /**
167 * Whether to infer the type of the `$event` variable in event bindings to DOM events.
168 *
169 * If this is `true`, the type of `$event` will be inferred based on TypeScript's
170 * `HTMLElementEventMap`, with a fallback to the native `Event` type. If set to `false`, the
171 * `$event` variable will be of type `any`.
172 */
173 checkTypeOfDomEvents: boolean;
174 /**
175 * Whether to infer the type of local references to DOM elements.
176 *
177 * If this is `true`, the type of a `#ref` variable on a DOM node in the template will be
178 * determined by the type of `document.createElement` for the given DOM node type. If set to
179 * `false`, the type of `ref` for DOM nodes will be `any`.
180 */
181 checkTypeOfDomReferences: boolean;
182 /**
183 * Whether to infer the type of local references.
184 *
185 * If this is `true`, the type of a `#ref` variable that points to a directive or `TemplateRef` in
186 * the template will be inferred correctly. If set to `false`, the type of `ref` for will be
187 * `any`.
188 */
189 checkTypeOfNonDomReferences: boolean;
190 /**
191 * Whether to adjust the output of the TCB to ensure compatibility with the `TemplateTypeChecker`.
192 *
193 * The statements generated in the TCB are optimized for performance and producing diagnostics.
194 * These optimizations can result in generating a TCB that does not have all the information
195 * needed by the `TemplateTypeChecker` for retrieving `Symbol`s. For example, as an optimization,
196 * the TCB will not generate variable declaration statements for directives that have no
197 * references, inputs, or outputs. However, the `TemplateTypeChecker` always needs these
198 * statements to be present in order to provide `ts.Symbol`s and `ts.Type`s for the directives.
199 *
200 * When set to `false`, enables TCB optimizations for template diagnostics.
201 * When set to `true`, ensures all information required by `TemplateTypeChecker` to
202 * retrieve symbols for template nodes is available in the TCB.
203 */
204 enableTemplateTypeChecker: boolean;
205 /**
206 * Whether to include type information from pipes in the type-checking operation.
207 *
208 * If this is `true`, then the pipe's type signature for `transform()` will be used to check the
209 * usage of the pipe. If this is `false`, then the result of applying a pipe will be `any`, and
210 * the types of the pipe's value and arguments will not be matched against the `transform()`
211 * method.
212 */
213 checkTypeOfPipes: boolean;
214 /**
215 * Whether to narrow the types of template contexts.
216 */
217 applyTemplateContextGuards: boolean;
218 /**
219 * Whether to use a strict type for null-safe navigation operations.
220 *
221 * If this is `false`, then the return type of `a?.b` or `a?()` will be `any`. If set to `true`,
222 * then the return type of `a?.b` for example will be the same as the type of the ternary
223 * expression `a != null ? a.b : a`.
224 */
225 strictSafeNavigationTypes: boolean;
226 /**
227 * Whether to descend into template bodies and check any bindings there.
228 */
229 checkTemplateBodies: boolean;
230 /**
231 * Whether to always apply DOM schema checks in template bodies, independently of the
232 * `checkTemplateBodies` setting.
233 */
234 alwaysCheckSchemaInTemplateBodies: boolean;
235 /**
236 * Whether to check resolvable queries.
237 *
238 * This is currently an unsupported feature.
239 */
240 checkQueries: false;
241 /**
242 * Whether to use any generic types of the context component.
243 *
244 * If this is `true`, then if the context component has generic types, those will be mirrored in
245 * the template type-checking context. If `false`, any generic type parameters of the context
246 * component will be set to `any` during type-checking.
247 */
248 useContextGenericType: boolean;
249 /**
250 * Whether or not to infer types for object and array literals in the template.
251 *
252 * If this is `true`, then the type of an object or an array literal in the template will be the
253 * same type that TypeScript would infer if the literal appeared in code. If `false`, then such
254 * literals are cast to `any` when declared.
255 */
256 strictLiteralTypes: boolean;
257 /**
258 * Whether to use inline type constructors.
259 *
260 * If this is `true`, create inline type constructors when required. For example, if a type
261 * constructor's parameters has private types, it cannot be created normally, so we inline it in
262 * the directives definition file.
263 *
264 * If false, do not create inline type constructors. Fall back to using `any` type for
265 * constructors that normally require inlining.
266 *
267 * This option requires the environment to support inlining. If the environment does not support
268 * inlining, this must be set to `false`.
269 */
270 useInlineTypeConstructors: boolean;
271 /**
272 * Whether or not to produce diagnostic suggestions in cases where the compiler could have
273 * inferred a better type for a construct, but was prevented from doing so by the current type
274 * checking configuration.
275 *
276 * For example, if the compiler could have used a template context guard to infer a better type
277 * for a structural directive's context and `let-` variables, but the user is in
278 * `fullTemplateTypeCheck` mode and such guards are therefore disabled.
279 *
280 * This mode is useful for clients like the Language Service which want to inform users of
281 * opportunities to improve their own developer experience.
282 */
283 suggestionsForSuboptimalTypeInference: boolean;
284}
285export type TemplateSourceMapping = DirectTemplateSourceMapping | IndirectTemplateSourceMapping | ExternalTemplateSourceMapping;
286/**
287 * A mapping to an inline template in a TS file.
288 *
289 * `ParseSourceSpan`s for this template should be accurate for direct reporting in a TS error
290 * message.
291 */
292export interface DirectTemplateSourceMapping {
293 type: 'direct';
294 node: ts.StringLiteral | ts.NoSubstitutionTemplateLiteral;
295}
296/**
297 * A mapping to a template which is still in a TS file, but where the node positions in any
298 * `ParseSourceSpan`s are not accurate for one reason or another.
299 *
300 * This can occur if the template expression was interpolated in a way where the compiler could not
301 * construct a contiguous mapping for the template string. The `node` refers to the `template`
302 * expression.
303 */
304export interface IndirectTemplateSourceMapping {
305 type: 'indirect';
306 componentClass: ClassDeclaration;
307 node: ts.Expression;
308 template: string;
309}
310/**
311 * A mapping to a template declared in an external HTML file, where node positions in
312 * `ParseSourceSpan`s represent accurate offsets into the external file.
313 *
314 * In this case, the given `node` refers to the `templateUrl` expression.
315 */
316export interface ExternalTemplateSourceMapping {
317 type: 'external';
318 componentClass: ClassDeclaration;
319 node: ts.Expression;
320 template: string;
321 templateUrl: string;
322}
323/**
324 * A mapping of a TCB template id to a span in the corresponding template source.
325 */
326export interface SourceLocation {
327 id: TemplateId;
328 span: AbsoluteSourceSpan;
329}
330/**
331 * A representation of all a node's template mapping information we know. Useful for producing
332 * diagnostics based on a TCB node or generally mapping from a TCB node back to a template location.
333 */
334export interface FullTemplateMapping {
335 sourceLocation: SourceLocation;
336 templateSourceMapping: TemplateSourceMapping;
337 span: ParseSourceSpan;
338}