# The Template Type Checking Engine
The `typecheck` package is concerned with template type-checking, the process by which the compiler determines and understands the TypeScript types of constructs within component templates. It's used to perform actual type checking of templates (similarly to how TypeScript checks code for type errors). It also provides the `TemplateTypeChecker` API which is a conceptual analogue to TypeScript's own `ts.TypeChecker`, exposing various semantic details about template types to consumers such as the Angular Language Service.
The template type-checking engine is complex, as TypeScript itself is not very pluggable when it comes to the type system. The main algorithm for template type-checking is as follows:
1. The input `ts.Program` is analyzed, and information about directives/pipes as well as candidate templates is collected.
2. Each candidate template is converted into a "type-check block", or TCB, a TypeScript function that semantically describes the operations in the template as well as their types.
3. A derivative `ts.Program` is created from the user's input program from step 1, plus the newly generated TCBs.
4. TypeScript is asked to produce diagnostics for the TCBs, which arise from type errors within the template.
5. TCB diagnostics are converted to template diagnostics and reported to the user.
This algorithm relies extensively on TypeScript's ability to rapidly type check incremental changes in a `ts.Program` for its performance characteristics. Much of its design is optimized to ensure TypeScript has to do the minimum incremental work to check the new `ts.Program`.
## Type Check Blocks
To understand and check the types of various operations and structures within templates, the `typecheck` system maps them to TypeScript code, encoding them in such a way as to express the intent of the operation within the type system.
TCBs are not ever emitted, nor are they referenced from any other code (they're unused code as far as TypeScript is concerned). Their _runtime_ effect is therefore unimportant. What matters is that they express to TypeScript the type relationships of directives, bindings, and other entities in the template. Type errors within TCBs translate directly to type errors in the original template.
### Theory
Given a component `SomeCmp`, its TCB takes the form of a function:
```typescript
function tcb(this: SomeCmp): void {
// TCB code
}
```
Encoding the TCB as a function serves two purposes:
1. It provides a lexical scope in which to declare variables without fear of collisions.
2. It provides a convenient location (the parameter list) to declare the component context.
The component context is the theoretical component instance associated with the template. Expressions within the template often refer to properties of this component.
For example, if `SomeCmp`'s template has an interpolation expression `{{foo.bar}}`, this suggests that `SomeCmp` has a property `foo`, and that `foo` itself is an object with a property `bar` (or in a type sense, that the type of `SomeCmp.foo` has a property `bar`).
Such a binding is expressed in the TCB function, using the `this` parameter as the component instance:
```typescript
function tcb(this: SomeCmp): void {
'' + this.foo.bar;
}
```
If `SomeCmp` does not have a `foo` property, then TypeScript will produce a type error/diagnostic for the expression `this.foo`. If `this.foo` does exist, but is not of a type that has a `bar` property, then TypeScript will catch that too. By mapping the template expression `{{foo.bar}}` to TypeScript code, the compiler has captured its _intent_ in the TCB in a way that TypeScript can validate.
#### Types of template declarations
Not only can a template consume properties declared from its component, but various structures within a template can also be considered "declarations" which have types of their own. For example, the template:
```html
<input #name>
{{name.value}}
```
declares a single `<input>` element with a local ref `#name`, meaning that within this template `name` refers to the `<input>` element. The `{{name.value}}` interpolation is reading the `value` property of this element.
Within the TCB, the `<input>` element is treated as a declaration, and the compiler leverages the powerful type inference of `document.createElement`:
```typescript
function tcb(this: SomeCmp): void {
var _t1 = document.createElement('input');
'' + _t1.value;
}
```
The `_t1` variable represents the instance of the `<input>` element within the template. This statement will never be executed, but its initialization expression is used to infer a correct type of `_t1` (`HTMLInputElement`), using the `document.createElement` typings that TypeScript provides.
By knowing the type of this element, the expression involving the `name` local ref can be translated into the TCB as `_t1.value`. TypeScript will then validate that `_t1` has a `value` property (really, that the `HTMLInputElement` type has a `value` property).
#### Directive types
Just like with HTML elements, directives present on elements within the template (including those directives which are components) are treated as declarations as well. Consider the template:
```html
<other-cmp [foo]="bar"></other-cmp>
```
The TCB for this template looks like:
```typescript
function tcb(this: SomeCmp): void {
var _t1: OtherCmp = null!;
_t1.foo = this.bar;
}
```
Since `<other-cmp>` is a component, the TCB declares `_t1` to be of that component's type. This allows for the binding `[foo]="bar"` to be expressed in TypeScript as `_t1.foo = this.bar` - an assignment to `OtherCmp`'s `@Input` for `foo` of the `bar` property from the template's context. TypeScript can then type check this operation and produce diagnostics if the type of `this.bar` is not assignable to the `_t1.foo` property which backs the `@Input`.
#### Generic directives & type constructors
The above declaration of `_t1` using the component's type only works when the directive/component class is not generic. If `OtherCmp` were declared as:
```typescript
export class OtherCmp<T> {
...
}
```
then the compiler could not write
```typescript
var _t1: OtherCmp<?> = ...;
```
without picking a value for the generic type parameter `T` of `OtherCmp`. How should the compiler know what type the user intended for this component instance?
Ordinarily, for a plain TypeScript class such as `Set<T>`, the generic type parameters of an instance are determined in one of two ways:
1. Directly, via construction: `new Set<string>()`
2. Indirectly, via inference from constructor parameters: `new Set(['foo', 'bar']); // Set<string>`
For directives, neither of these options makes sense. Users do not write direct constructor calls to directives in a template, so there is no mechanism by which they can specify generic types directly. Directive constructors are also dependency-injected, and generic types cannot be used as DI tokens and so they cannot be inferred from DI.
Instead, conceptually, the generic type of a directive depends on the types bound to its _inputs_. This is immediately evident for a directive such as `NgFor`:
```typescript
@Directive({selector: '[ngFor]'})
export class NgFor<T> {
@Input() ngForOf!: Iterable<T>;
}
```
(Note: the real `NgFor` directive is more complex than the simplistic version examined here, but the same principles still apply)
In this case, the `T` type parameter of `NgFor` represents the value type of the `Iterable` over which we're iterating. This depends entirely on the `Iterable` passed to `NgFor` - if the user passes a `User[]` array, then this should conceptually create an `NgFor<User>` instance. If they pass a `string[]` array, it should be an `NgFor<string>` instead.
To infer a correct type for a generic directive, the TCB system generates a **type constructor** for the directive. The type constructor is a "fake" constructor which can be used to infer the directive type base
angularjs Web页面框架 v15.2.4
需积分: 0 141 浏览量
更新于2023-04-02
收藏 42.15MB ZIP 举报
AngularJS 是一个强大的前端JavaScript框架,由Google维护,主要用于构建动态Web应用。版本v15.2.4代表了该框架的一个稳定版本,提供了一系列改进和优化,旨在提高开发效率和用户体验。
AngularJS的核心概念是数据绑定和依赖注入。数据绑定使得视图和模型之间的数据变化能够自动同步,无需手动操作DOM元素。这简化了开发流程,让开发者可以专注于业务逻辑,而不是底层的DOM操作。依赖注入则是AngularJS中的另一大特色,它帮助管理组件之间的依赖关系,降低了代码耦合度,使代码更易于测试和维护。
在AngularJS 15.2.4版本中,我们可以期待以下关键特性:
1. **模块化**:AngularJS支持模块化开发,允许将应用程序分解为可重用的组件或模块,便于代码组织和维护。
2. **指令系统**:AngularJS的指令系统扩展了HTML的功能,允许创建自定义的DOM行为。例如,`ng-repeat`用于数据迭代,`ng-show`和`ng-hide`用于条件展示,以及`ng-model`用于双向数据绑定。
3. **服务**:AngularJS的服务是可注入的单例对象,它们提供了一种抽象层来处理如HTTP请求、缓存、事件广播等通用任务。在v15.2.4中,可能包含对某些服务的优化和增强。
4. **路由**:AngularJS的路由功能允许根据URL导航到不同的视图,实现单页应用(SPA)的功能。开发者可以使用`$routeProvider`配置路由规则。
5. **表单和验证**:AngularJS提供了强大的表单处理能力,包括内置的表单验证,如`ng-required`、`ng-minlength`等,以及通过`ngModelController`进行的模型验证。
6. **动画**:AngularJS的动画库使得在页面过渡、显示隐藏等操作中添加平滑动画效果变得简单。
7. **性能优化**:随着版本的迭代,AngularJS不断优化其性能,如减少DOM操作、提升指令性能等。v15.2.4可能会包含更多针对性能的改进。
8. **兼容性和修复**:新版本通常会修复已知的问题,提高与不同浏览器的兼容性,确保应用的稳定运行。
在下载的压缩包`csdn`中的`angular-15.2.4`文件,可能包含了AngularJS的库文件、文档、示例代码和开发工具。通过这些资源,开发者可以快速开始AngularJS项目,理解框架的使用方法,学习最佳实践,并利用提供的API和工具进行调试和优化。
AngularJS v15.2.4是一个成熟的前端框架,提供了丰富的特性和工具,用于构建复杂的Web应用。它通过其独特的数据绑定、依赖注入和模块化设计,提高了开发效率和代码质量,是现代Web开发的重要选择之一。
weixin_54393129
- 粉丝: 0
- 资源: 5
最新资源
- IP102中分离出来的害虫数据集,使用COCO JSON标注
- 几何物体检测50-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar
- 石家庄2005-2024年近20年历史气象数据下载
- C语言实例-毕业设计项目开发:系统信息获取与显示工具-开题报告,论文,答辩PPT参考
- 秦皇岛2005-2024年近20年历史气象数据下载
- 太原市2005-2024年近20年历史气象数据下载
- 大同市2005-2024年近20年历史气象数据下载
- 沈阳市2005-2024年近20年历史气象数据下载
- 长春市2005-2024年近20年历史气象数据下载
- 齐齐哈尔市2005-2024年近20年历史气象数据下载
- 徐州市2005-2024年近20年历史气象数据下载
- nvm desktop -4.0.5-x64-setup
- 医护人员检测22-YOLO(v5至v11)、COCO、CreateML、Paligemma、TFRecord、VOC数据集合集.rar
- 饿了么bxet参数算法
- 南通市2005-2024年近20年历史气象数据下载
- 连云港市2005-2024年近20年历史气象数据下载