在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的原始功能来开发框架,这样的框架很有吸引力。

广告
将在 10 秒后关闭
bannerAds