TypeScript基础为Angular开发奠基
一、TypeScript 基础类型
1.1 布尔类型(boolean)
在 TypeScript 中,布尔类型是最基本的数据类型之一,用于表示真或假。其声明方式非常直观:
let isDone: boolean = false;
这里,我们声明了一个名为 isDone
的变量,指定其类型为 boolean
并初始化为 false
。在 Angular 开发中,布尔类型常用于控制组件的显示状态,比如一个模态框是否可见:
import { Component } from '@angular/core';
@Component({
selector: 'app-modal',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.css']
})
export class ModalComponent {
isModalVisible: boolean = false;
showModal() {
this.isModalVisible = true;
}
hideModal() {
this.isModalVisible = false;
}
}
在 modal.component.html
中可以根据 isModalVisible
的值来决定模态框的显示或隐藏:
<div *ngIf="isModalVisible" class="modal">
<!-- 模态框内容 -->
</div>
<button (click)="showModal()">显示模态框</button>
<button (click)="hideModal()">隐藏模态框</button>
1.2 数字类型(number)
TypeScript 中的数字类型用于表示各种数值,包括整数和浮点数。声明数字类型变量如下:
let age: number = 25;
let pi: number = 3.14;
在 Angular 应用中,数字类型常用于处理计数器、价格等数据。例如,一个简单的购物车组件中商品数量的处理:
import { Component } from '@angular/core';
@Component({
selector: 'app-cart-item',
templateUrl: './cart-item.component.html',
styleUrls: ['./cart-item.component.css']
})
export class CartItemComponent {
itemQuantity: number = 1;
incrementQuantity() {
this.itemQuantity++;
}
decrementQuantity() {
if (this.itemQuantity > 1) {
this.itemQuantity--;
}
}
}
在 cart-item.component.html
中:
<div>
<span>商品数量: {{ itemQuantity }}</span>
<button (click)="incrementQuantity()">增加</button>
<button (click)="decrementQuantity()">减少</button>
</div>
1.3 字符串类型(string)
字符串类型用于表示文本数据。可以使用单引号或双引号来定义字符串:
let name: string = 'John Doe';
let message: string = "Hello, world!";
在 Angular 开发中,字符串类型广泛应用于组件的文本显示、用户输入等方面。例如,一个用户登录组件中用户名和密码的输入处理:
import { Component } from '@angular/core';
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
username: string = '';
password: string = '';
onSubmit() {
console.log(`用户名: ${this.username}, 密码: ${this.password}`);
}
}
在 login.component.html
中:
<form (ngSubmit)="onSubmit()">
<label>用户名:
<input type="text" [(ngModel)]="username">
</label>
<label>密码:
<input type="password" [(ngModel)]="password">
</label>
<button type="submit">登录</button>
</form>
1.4 数组类型(array)
TypeScript 支持两种方式声明数组。一种是在类型后面加上 []
,另一种是使用 Array<类型>
的形式。
// 第一种方式
let numbers: number[] = [1, 2, 3, 4, 5];
// 第二种方式
let names: Array<string> = ['Alice', 'Bob', 'Charlie'];
在 Angular 中,数组常用于存储列表数据,比如文章列表、用户列表等。以一个文章列表组件为例:
import { Component } from '@angular/core';
@Component({
selector: 'app-article-list',
templateUrl: './article-list.component.html',
styleUrls: ['./article-list.component.css']
})
export class ArticleListComponent {
articles: Array<{ title: string; content: string }> = [
{ title: '第一篇文章', content: '文章内容1' },
{ title: '第二篇文章', content: '文章内容2' }
];
}
在 article-list.component.html
中:
<ul>
<li *ngFor="let article of articles">
<h3>{{ article.title }}</h3>
<p>{{ article.content }}</p>
</li>
</ul>
1.5 元组类型(tuple)
元组类型允许表示一个固定长度的数组,其中每个元素的类型可以不同。声明元组如下:
let user: [string, number] = ['John', 25];
这里,user
元组的第一个元素是字符串类型,第二个元素是数字类型。在 Angular 开发中,元组可以用于一些特定场景,比如存储坐标信息:
import { Component } from '@angular/core';
@Component({
selector: 'app-map-marker',
templateUrl: './map-marker.component.html',
styleUrls: ['./map-marker.component.css']
})
export class MapMarkerComponent {
markerPosition: [number, number] = [10.0, 20.0];
}
在 map-marker.component.html
中可能会根据 markerPosition
来显示地图上的标记位置(实际应用中需要结合地图相关库)。
1.6 枚举类型(enum)
枚举类型用于定义一组命名的常量。它可以让代码更易读和维护。
enum Color {
Red,
Green,
Blue
}
let myColor: Color = Color.Green;
默认情况下,枚举成员从 0 开始自动赋值。也可以手动指定值:
enum Direction {
Up = 1,
Down,
Left,
Right
}
let myDirection: Direction = Direction.Right;
在 Angular 开发中,枚举可用于表示组件的不同状态,比如一个按钮的不同操作状态:
import { Component } from '@angular/core';
enum ButtonState {
Normal,
Loading,
Disabled
}
@Component({
selector: 'app-custom-button',
templateUrl: './custom-button.component.html',
styleUrls: ['./custom-button.component.css']
})
export class CustomButtonComponent {
buttonState: ButtonState = ButtonState.Normal;
onClick() {
this.buttonState = ButtonState.Loading;
// 模拟异步操作
setTimeout(() => {
this.buttonState = ButtonState.Normal;
}, 2000);
}
}
在 custom - button.component.html
中:
<button [disabled]="buttonState === ButtonState.Disabled || buttonState === ButtonState.Loading" (click)="onClick()">
{{ buttonState === ButtonState.Loading? '加载中...' : '点击我' }}
</button>
1.7 任意类型(any)
当我们不确定一个变量的类型,或者希望它可以是任意类型时,可以使用 any
类型。
let value: any = 'Hello';
value = 123;
虽然 any
类型提供了很大的灵活性,但过度使用会失去 TypeScript 类型检查的优势。在 Angular 开发中,尽量避免在公共 API 或关键逻辑中使用 any
类型。不过,在处理第三方库或动态数据时,有时可能会用到。例如,在从一个不确定结构的 API 中获取数据时:
import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-dynamic-data',
templateUrl: './dynamic-data.component.html',
styleUrls: ['./dynamic-data.component.css']
})
export class DynamicDataComponent implements OnInit {
data: any;
constructor(private http: HttpClient) {}
ngOnInit() {
this.http.get('https://example.com/api/data').subscribe((response) => {
this.data = response;
});
}
}
在 dynamic - data.component.html
中可以根据 data
的实际结构来显示数据。
1.8 空值类型(void)
void
类型表示没有任何类型。通常用于函数返回值类型,当函数没有返回值时使用。
function logMessage(message: string): void {
console.log(message);
}
在 Angular 组件的一些方法中,如果只是执行某些操作而不返回数据,就可以使用 void
类型。比如一个清除表单数据的方法:
import { Component } from '@angular/core';
@Component({
selector: 'app-form',
templateUrl: './form.component.html',
styleUrls: ['./form.component.css']
})
export class FormComponent {
username: string = '';
password: string = '';
clearForm(): void {
this.username = '';
this.password = '';
}
}
在 form.component.html
中可以添加一个按钮来调用 clearForm
方法。
1.9 空值(null)和未定义(undefined)
在 TypeScript 中,null
和 undefined
分别表示空值和未定义的值。它们本身有自己的类型,即 null
类型和 undefined
类型。
let a: null = null;
let b: undefined = undefined;
默认情况下,null
和 undefined
是所有类型的子类型,也就是说,可以把 null
和 undefined
赋值给其他类型的变量。但在严格模式下(strictNullChecks
开启),这种赋值会报错。在 Angular 开发中,经常会遇到变量可能为 null
或 undefined
的情况,比如在获取 DOM 元素时:
import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
@Component({
selector: 'app - dom - access',
templateUrl: './dom - access.component.html',
styleUrls: ['./dom - access.component.css']
})
export class DomAccessComponent implements AfterViewInit {
@ViewChild('myElement') myElement: ElementRef<HTMLElement> | null = null;
ngAfterViewInit() {
if (this.myElement) {
this.myElement.nativeElement.style.color = 'red';
}
}
}
在 dom - access.component.html
中:
<div #myElement>这是一个测试元素</div>
1.10 never 类型
never
类型表示永远不会出现的值的类型。通常在函数抛出异常或无限循环时使用。
function throwError(message: string): never {
throw new Error(message);
}
function infiniteLoop(): never {
while (true) {}
}
在 Angular 开发中,当一个函数预期永远不会正常返回时,可以使用 never
类型。比如在处理错误状态,直接抛出异常中断操作:
import { Component } from '@angular/core';
@Component({
selector: 'app - error - handling',
templateUrl: './error - handling.component.html',
styleUrls: ['./error - handling.component.css']
})
export class ErrorHandlingComponent {
data: string | null = null;
getData(): string {
if (!this.data) {
throwError('数据未初始化');
}
return this.data;
}
}
这里 throwError
函数返回 never
类型,因为它抛出异常不会正常返回。
二、TypeScript 函数
2.1 函数定义
TypeScript 中函数的定义与 JavaScript 类似,但可以添加类型注解。函数定义有两种常见形式:函数声明和函数表达式。 函数声明:
function add(a: number, b: number): number {
return a + b;
}
这里,add
函数接受两个 number
类型的参数 a
和 b
,并返回一个 number
类型的值。
函数表达式:
let subtract: (a: number, b: number) => number = function (a: number, b: number): number {
return a - b;
};
在 Angular 开发中,函数常用于组件的业务逻辑处理。例如,一个计算商品总价的函数:
import { Component } from '@angular/core';
@Component({
selector: 'app - product - total',
templateUrl: './product - total.component.html',
styleUrls: ['./product - total.component.css']
})
export class ProductTotalComponent {
price: number = 10;
quantity: number = 3;
calculateTotal(): number {
return this.price * this.quantity;
}
}
在 product - total.component.html
中可以显示计算结果:
<p>商品总价: {{ calculateTotal() }}</p>
2.2 函数参数
函数参数可以有默认值。当调用函数时没有传入该参数的值,就会使用默认值。
function greet(name: string = 'Guest') {
console.log(`Hello, ${name}!`);
}
greet(); // 输出: Hello, Guest!
greet('John'); // 输出: Hello, John!
在 Angular 中,这种特性可以用于设置组件的默认配置。例如,一个弹窗组件可以有默认的标题和内容:
import { Component } from '@angular/core';
@Component({
selector: 'app - popup',
templateUrl: './popup.component.html',
styleUrls: ['./popup.component.css']
})
export class PopupComponent {
title: string = '默认标题';
content: string = '默认内容';
constructor(title?: string, content?: string) {
if (title) {
this.title = title;
}
if (content) {
this.content = content;
}
}
}
在使用该组件时,可以传入自定义的标题和内容,也可以使用默认值。
2.3 剩余参数
剩余参数允许我们将不确定数量的参数作为一个数组来处理。使用 ...
语法来定义剩余参数。
function sum(...numbers: number[]): number {
return numbers.reduce((acc, num) => acc + num, 0);
}
let result = sum(1, 2, 3, 4, 5); // result 为 15
在 Angular 中,剩余参数可用于处理组件的动态输入。比如一个按钮组组件,接受多个按钮的文本:
import { Component } from '@angular/core';
@Component({
selector: 'app - button - group',
templateUrl: './button - group.component.html',
styleUrls: ['./button - group.component.css']
})
export class ButtonGroupComponent {
buttons: string[] = [];
constructor(...buttonTexts: string[]) {
this.buttons = buttonTexts;
}
}
在 button - group.component.html
中:
<div>
<button *ngFor="let button of buttons">{{ button }}</button>
</div>
2.4 函数重载
函数重载允许我们为同一个函数定义多个不同的签名。编译器会根据调用时传入的参数类型和数量来选择合适的实现。
function print(value: string): void;
function print(value: number): void;
function print(value: any) {
console.log(value);
}
print('Hello'); // 调用第一个重载
print(123); // 调用第二个重载
在 Angular 开发中,函数重载可以用于处理不同类型数据的相同操作。比如一个日志记录组件,根据传入的数据类型不同进行不同格式的记录:
import { Component } from '@angular/core';
@Component({
selector: 'app - logger',
templateUrl: './logger.component.html',
styleUrls: ['./logger.component.css']
})
export class LoggerComponent {
log(message: string): void;
log(message: number): void;
log(message: any) {
if (typeof message ==='string') {
console.log(`字符串日志: ${message}`);
} else if (typeof message === 'number') {
console.log(`数字日志: ${message}`);
}
}
}
在组件使用中可以调用 log
方法并传入不同类型的数据。
三、TypeScript 接口
3.1 接口基础
接口是 TypeScript 中非常重要的概念,它用于定义对象的形状(结构)。通过接口,我们可以明确对象应该具有哪些属性以及这些属性的类型。
interface User {
name: string;
age: number;
}
let user: User = {
name: 'John Doe',
age: 25
};
在 Angular 开发中,接口常用于定义服务返回的数据结构、组件输入输出属性的类型等。例如,一个用户服务返回用户信息:
import { Injectable } from '@angular/core';
interface User {
id: number;
name: string;
email: string;
}
@Injectable({
providedIn: 'root'
})
export class UserService {
getUser(): User {
return {
id: 1,
name: 'Jane Smith',
email: 'jane@example.com'
};
}
}
在组件中使用该服务:
import { Component } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app - user - profile',
templateUrl: './user - profile.component.html',
styleUrls: ['./user - profile.component.css']
})
export class UserProfileComponent {
user: User;
constructor(private userService: UserService) {
this.user = this.userService.getUser();
}
}
在 user - profile.component.html
中可以显示用户信息:
<div>
<p>姓名: {{ user.name }}</p>
<p>邮箱: {{ user.email }}</p>
</div>
3.2 可选属性
接口中的属性可以是可选的,使用 ?
来表示。
interface Product {
name: string;
price: number;
description?: string;
}
let product: Product = {
name: '手机',
price: 5000
};
在 Angular 组件开发中,可选属性很有用。比如一个商品展示组件,描述信息可能不是必填的:
import { Component } from '@angular/core';
interface Product {
name: string;
price: number;
description?: string;
}
@Component({
selector: 'app - product - display',
templateUrl: './product - display.component.html',
styleUrls: ['./product - display.component.css']
})
export class ProductDisplayComponent {
product: Product = {
name: '笔记本电脑',
price: 8000,
description: '高性能笔记本'
};
}
在 product - display.component.html
中:
<div>
<h2>{{ product.name }}</h2>
<p>价格: {{ product.price }}</p>
<p *ngIf="product.description">{{ product.description }}</p>
</div>
3.3 只读属性
接口中可以定义只读属性,使用 readonly
关键字,一旦赋值后就不能再修改。
interface Point {
readonly x: number;
readonly y: number;
}
let point: Point = {
x: 10,
y: 20
};
// point.x = 20; // 报错,不能修改只读属性
在 Angular 中,对于一些不可变的数据结构可以使用只读属性。比如一个配置对象,其某些属性在初始化后不应被修改:
import { Component } from '@angular/core';
interface AppConfig {
readonly appName: string;
readonly version: string;
}
const config: AppConfig = {
appName: 'My Angular App',
version: '1.0.0'
};
@Component({
selector: 'app - config - display',
templateUrl: './config - display.component.html',
styleUrls: ['./config - display.component.css']
})
export class ConfigDisplayComponent {
config = config;
}
在 config - display.component.html
中显示配置信息:
<div>
<p>应用名称: {{ config.appName }}</p>
<p>版本: {{ config.version }}</p>
</div>
3.4 函数类型接口
接口不仅可以定义对象的结构,还可以定义函数的类型。
interface AddFunction {
(a: number, b: number): number;
}
let add: AddFunction = function (a: number, b: number): number {
return a + b;
};
在 Angular 开发中,函数类型接口可以用于定义组件中回调函数的类型。比如一个可点击按钮组件,接受一个点击回调函数:
import { Component } from '@angular/core';
interface ClickCallback {
(): void;
}
@Component({
selector: 'app - clickable - button',
templateUrl: './clickable - button.component.html',
styleUrls: ['./clickable - button.component.css']
})
export class ClickableButtonComponent {
clickHandler: ClickCallback;
constructor(clickHandler: ClickCallback) {
this.clickHandler = clickHandler;
}
}
在 clickable - button.component.html
中:
<button (click)="clickHandler()">点击我</button>
在使用该组件时传入具体的回调函数:
import { Component } from '@angular/core';
@Component({
selector: 'app - parent - component',
templateUrl: './parent - component.html',
styleUrls: ['./parent - component.css']
})
export class ParentComponent {
onButtonClick() {
console.log('按钮被点击了');
}
}
在 parent - component.html
中:
<app - clickable - button [clickHandler]="onButtonClick"></app - clickable - button>
四、TypeScript 类
4.1 类的基础
类是面向对象编程的核心概念之一。TypeScript 支持类的定义,包括属性、方法、构造函数等。
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I'm ${this.name} and I'm ${this.age} years old.`);
}
}
let person = new Person('John Doe', 25);
person.greet();
在 Angular 开发中,组件就是基于类的。每个 Angular 组件都是一个类,带有特定的装饰器(如 @Component
)。例如,一个简单的用户信息组件:
import { Component } from '@angular/core';
@Component({
selector: 'app - user - info',
templateUrl: './user - info.component.html',
styleUrls: ['./user - info.component.css']
})
export class UserInfoComponent {
name: string = 'Jane Smith';
age: number = 30;
constructor() {}
displayInfo() {
console.log(`姓名: ${this.name}, 年龄: ${this.age}`);
}
}
在 user - info.component.html
中:
<button (click)="displayInfo()">显示信息</button>
4.2 继承
类可以通过继承来复用代码。使用 extends
关键字来实现继承。
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a sound.`);
}
}
class Dog extends Animal {
breed: string;
constructor(name: string, breed: string) {
super(name);
this.breed = breed;
}
bark() {
console.log(`${this.name} barks.`);
}
}
let dog = new Dog('Buddy', 'Golden Retriever');
dog.speak();
dog.bark();
在 Angular 中,继承常用于创建具有公共功能的基类组件,然后其他组件继承自该基类。比如一个具有通用样式和行为的基类表单组件,其他具体表单组件继承自它:
import { Component } from '@angular/core';
@Component({
selector: 'app - base - form',
templateUrl: './base - form.component.html',
styleUrls: ['./base - form.component.css']
})
export class BaseFormComponent {
formTitle: string = '默认表单';
constructor() {}
submitForm() {
console.log('表单提交');
}
}
import { Component } from '@angular/core';
@Component({
selector: 'app - login - form',
templateUrl: './login - form.component.html',
styleUrls: ['./login - form.component.css']
})
export class LoginFormComponent extends BaseFormComponent {
constructor() {
super();
this.formTitle = '登录表单';
}
}
在 login - form.component.html
中可以使用从基类继承的属性和方法。
4.3 访问修饰符
TypeScript 提供了三种访问修饰符:public
、private
和 protected
。
public
:默认的访问修饰符,属性和方法可以在类的内部和外部访问。private
:属性和方法只能在类的内部访问。protected
:属性和方法可以在类的内部以及子类中访问。
class Car {
public brand: string;
private model: string;
protected year: number;
constructor(brand: string, model: string, year: number) {
this.brand = brand;
this.model = model;
this.year = year;
}
getDetails() {
return `${this.brand} ${this.model} (${this.year})`;
}
}
class SportsCar extends Car {
constructor(brand: string, model: string, year: number) {
super(brand, model, year);
}
getSportsCarDetails() {
return `Sports Car: ${this.getDetails()}`;
}
}
let car = new Car('Toyota', 'Corolla', 2020);
console.log(car.brand);
// console.log(car.model); // 报错,model 是 private
// console.log(car.year); // 报错,year 是 protected
let sportsCar = new SportsCar('Ferrari', '488 GTB', 2019);
console.log(sportsCar.getSportsCarDetails());
在 Angular 开发中,合理使用访问修饰符可以保护组件的内部状态和逻辑。比如,一个组件内部的某些方法或属性不希望被外部组件直接访问,可以设置为 private
或 protected
。
4.4 静态成员
类的静态成员属于类本身,而不是类的实例。使用 static
关键字来定义静态属性和方法。
class MathUtils {
static PI: number = 3.14159;
static calculateCircleArea(radius: number): number {
return this.PI * radius * radius;
}
}
let area = MathUtils.calculateCircleArea(5);
console.log(area);
在 Angular 开发中,静态成员可用于提供一些全局的工具方法或常量。比如一个常量类,包含应用中常用的配置常量:
export class AppConstants {
static API_URL: string = 'https://example.com/api';
static DEFAULT_PAGE_SIZE: number = 10;
}
在其他组件或服务中可以直接使用这些静态常量:
import { Component } from '@angular/core';
import { AppConstants } from './app.constants';
@Component({
selector: 'app - api - call',
templateUrl: './api - call.component.html',
styleUrls: ['./api - call.component.css']
})
export class APICallComponent {
constructor() {
console.log(`API 地址: ${AppConstants.API_URL}`);
}
}
五、TypeScript 泛型
5.1 泛型基础
泛型是 TypeScript 中非常强大的特性,它允许我们在定义函数、接口或类时使用类型参数。这样可以使代码更加灵活和可复用。
function identity<T>(arg: T): T {
return arg;
}
let result = identity<number>(5);
let strResult = identity<string>('Hello');
在 Angular 开发中,泛型常用于服务和组件的通用操作。比如一个通用的获取数据的服务:
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class GenericService {
constructor(private http: HttpClient) {}
get<T>(url: string): Promise<T> {
return this.http.get<T>(url).toPromise();
}
}
在组件中使用该服务:
import { Component } from '@angular/core';
import { GenericService } from './generic.service';
interface User {
name: string;
age: number;
}
@Component({
selector: 'app - user - fetch',
templateUrl: './user - fetch.component.html',
styleUrls: ['./user - fetch.component.css']
})
export class UserFetchComponent {
user: User;
constructor(private genericService: GenericService) {
this.genericService.get<User>('https://example.com/api/user').then((data) => {
this.user = data;
});
}
}
5.2 泛型接口
可以定义泛型接口,使接口的类型参数化。
interface KeyValuePair<K, V> {
key: K;
value: V;
}
let pair: KeyValuePair<string, number> = { key: 'count', value: 10 };
在 Angular 开发中,泛型接口可用于定义一些通用的数据结构。比如一个分页结果的接口:
interface PaginationResult<T> {
data: T[];
total: number;
}
interface Product {
name: string;
price: number;
}
let productPagination: PaginationResult<Product> = {
data: [
{ name: '商品1', price: 100 },
{ name: '商品2', price: 200 }
],
total: 2
};
5.3 泛型类
泛型类允许我们创建具有通用类型的类。
class Stack<T> {
private items: T[] = [];
push(item: T) {
this.items.push(item);
}
pop(): T | undefined {
return this.items.pop();
}
}
let numberStack = new Stack<number>();
numberStack.push(1);
numberStack.push(2);
let popped = numberStack.pop();
在 Angular 开发中,泛型类可以用于实现一些通用的数据结构或操作。比如一个通用的缓存类:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class CacheService<T> {
private cache: { [key: string]: T } = {};
set(key: string, value: T) {
this.cache[key] = value;
}
get(key: string): T | undefined {
return this.cache[key];
}
}
在组件中使用该缓存服务:
import { Component } from '@angular/core';
import { CacheService } from './cache.service';
interface User {
name: string;
age: number;
}
@Component({
selector: 'app - user - cache',
templateUrl: './user - cache.component.html',
styleUrls: ['./user - cache.component.css']
})
export class UserCacheComponent {
user: User;
constructor(private cacheService: CacheService<User>) {
let cachedUser = this.cacheService.get('user - 1');
if (cachedUser) {
this.user = cachedUser;
} else {
this.user = { name: 'New User', age: 20 };
this.cacheService.set('user - 1', this.user);
}
}
}
5.4 泛型约束
有时我们需要对泛型类型参数进行约束,以确保它具有某些特定的属性或方法。可以使用 extends
关键字来实现泛型约束。
interface Lengthwise {
length: number;
}
function printLength<T extends Lengthwise>(arg: T) {
console.log(arg.length);
}
printLength('Hello');
printLength([1, 2, 3]);
// printLength(123); // 报错,number 类型没有 length 属性
在 Angular 开发中,泛型约束可用于确保传入的类型满足一定的条件。比如一个通用的显示组件,要求传入的数据对象具有 displayName
属性:
import { Component } from '@angular/core';
interface Displayable {
displayName: string;
}
@Component({
selector: 'app - display - generic',
templateUrl: './display - generic.component.html',
styleUrls: ['./display - generic.component.css']
})
export class DisplayGenericComponent<T extends Displayable> {
data: T;
constructor(data: T) {
this.data = data;
}
}
在 display - generic.component.html
中:
<div>
<p>{{ data.displayName }}</p>
</div>
在使用该组件时,传入的数据对象必须满足 Displayable
接口的约束。
通过以上对 TypeScript 基础的深入讲解和代码示例,相信读者对于如何利用 TypeScript 为 Angular 开发奠定坚实基础有了更清晰的认识。在实际的 Angular 项目开发中,熟练运用 TypeScript 的这些特性将大大提高代码的质量、可维护性和可扩展性。