在Angular中使用TypeScript的导入别名
嗨!嗳喲,聽說你在奧斯汀玩得很開心呢!
总结
介绍如何使用TypeScript功能在Angular中给模块导入添加别名。
背景 –
当我在Angular官方文档上阅读”创建一个英雄应用程序”的指南时,我对于在Angular中如何给TypeScript添加别名产生了兴趣。我进行了一次试验性的设置,发现竟然非常简单,因此我想要分享出来。
导入别名是指
通常情况下,导入ES模块时会使用相对路径来进行导入。
然而,当子目录增加时,import { helperA } from “../../../../../../helpers.js”这样的语句可能会变得非常冗长。
此外,如果将helpers.js移动,那就麻烦大了。
为了解决这个问题,TypeScript 提供了“导入别名”功能。
在tsconfig.json文件中,将helper.js的别名设置为以下方式。
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@helpers": ["helper.js"]
}
}
}
然后,之前的导入语法可以简化为以下形式。
import { helperA } from “@helpers”; -> 从”@helpers”中导入{ helperA }。
这就是导入别名的意思。
在Angular中使用导入别名。
使用Angular的导入别名很简单。只需像上面的例子一样在tsconfig.json中添加paths设置即可实现。
与Webpack不同,Angular会查看tsconfig.json,所以不需要特别的配置。
在制作导游英雄应用的前提下,我们继续推进!
将Hero类型放入types文件夹中。
我认为在上述指南中,通过src/app/hero.ts导出了Hero的类型定义,但是这次我们将创建一个名为src/types的文件夹,并将hero.ts移动到其中。
export interface Hero {
id: number;
name: string;
}
修改tsconfig
通过在tsconfig.json中指定我们在前面创建的文件夹的别名。
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"outDir": "./dist/out-tsc",
// ここです
"paths": {
"@custom-types/*": ["src/types/*"]
},
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2020",
"module": "es2020",
"lib": ["es2020", "dom"]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
根据此别名定义,推荐使用的原因是可以使用types中的所有文件。
可能会有一些读者注意到,我选择使用@custom-types/*而不是@types/*,这是有原因的。
- 因为我想传达明确这是在这个项目中添加的类型的意思,所以与TypeScript的node_modules的@types产生冲突。
如果在@types/中指定了以上内容,将会从TS解释器中抛出下列错误,请注意。
Cannot import type declaration files. Consider importing 'hero' instead of '@types/hero'
使用别名导入
只需提供一种选项,以下是对其进行中国语言的释义:
保存上述更改后,最终需要将使用Hero导入的所有文件的别名修改如下。
import { Component, OnInit } from '@angular/core';
// こうして普通のエイリアス構文でインポートすれば後はAngularがやってくれます!
import { Hero } from '@custom-types/hero';
import { HeroService } from '../hero.service';
import { MessageService } from '../message.service';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css'],
})
export class HeroesComponent implements OnInit {
public heroes: Hero[] = [];
public selectedHero?: Hero;
protected heroesSubscription!: ReturnType<
ReturnType<InstanceType<typeof HeroService>['getHeroes']>['subscribe']
>;
constructor(
private heroService: HeroService,
private messageService: MessageService
) {}
ngOnInit(): void {
this.getHeroes();
}
protected getHeroes() {
this.heroesSubscription = this.heroService
.getHeroes()
.subscribe((heroes) => {
this.heroes = heroes;
});
}
public handleSelection(hero: Hero): void {
if (hero.id === this.selectedHero?.id) {
this.messageService.add('HeroesComponent: Hero unselected.');
return (this.selectedHero = undefined);
}
this.messageService.add(`HeroesComponent: Selected ${hero.name}.`);
this.selectedHero = hero;
}
}
尝试对所有进行更改并保存,应该能够使错误消失并成功编译!
总结
迄今为止,我已经介绍了如何在Angular中使用TypeScript的导入别名,你觉得如何?
我很喜欢只需更改tsconfig.json文件,然后无需做任何其他事情的地方。
我在配置Webpack时记得第一次设置别名时遇到了一些困难。
Vite和Astro也是以类似的机制工作,只需在tsconfig.json中进行一次设置,就没有其他复杂的配置了。
附加信息:关于Angular的感想
我认为Angular是一个被严重低估的库。
为什么我无法理解为什么这么多人对此持反对意见呢?
我认为它比Vue更丰富工具、整体上支持面向对象的应用设计,并且学习门槛较低,使得代码整理更容易。
此外,该框架对可用的编写方式进行了限制,好处是即使是初级工程师也无法使用奇怪的写法。
坏处说的话,是不是觉得写作方式没有灵活性,感觉较为生硬呢?
作者认为由于采用了类结构并且具有明确的生命周期,基本上没有什么是这个语言不能做到的,但为什么它却受到了如此的厌恶呢。
我认为,总体而言,现代的Web开发与DOM和浏览器功能相去甚远,这是不好的。我觉得像Vue、Angular、Lit这样的库利用了JavaScript的原始功能来开发框架,这样的框架很有吸引力。