如何为导入 fontawesome 图标的项目界面分配正确的类型

问题描述

我正在开发一个使用 angular 11angular-fontawesomeangular material icon 项目。它包含一个 'problem' 模型,带有一个可选的 'icon' 属性:string;'。数据常量 "problem " 包含多个 "problem " 的排列,其属性 "icon": 是一个字符串,例如 "donate",它指的是 em>"faDonate"fontawesome 库中导入的图标。

我的代码

comun.module.ts:导入angular material icon fontawesome

的通用模块
import { MatIconModule } from '@angular/material/icon';
...
// FontAwesome
import {
  FontAwesomeModule,FaIconLibrary,} from '@fortawesome/angular-fontawesome';
import {
  faBars,faDonate,…
} from '@fortawesome/free-solid-svg-icons';
…
export class ComunModule {
  constructor(library: FaIconLibrary) {
    library.addIcons(
      faBars,...

problemas.model.ts

export interface Problema {
  id: number;
  grupo: string;
  idgrupo: number;
  subgrupo?: string;
  titulo: string;
  encabezado?: string;
  frase: string;
  icon?: string;
  ley: string;
  parrafounotitulo?: string;
  parrafounoparrafo?: string;
  parrafounoimg?: string;
  parrafodostitulo?: string;
  parrafodosparrafo?: string;
  parrafodosimg?: string;
  parrafotrestitulo?: string;
  parrafotresparrafo?: string;
  parrafotresimg?: string;
  parrafotablaa1?: string;
  parrafotablaa2?: string;
  parrafotablab1?: string;
  parrafotablab2?: string;
  parrafotablac1?: string;
  parrafotablac2?: string;
  parrafotablad1?: string;
  parrafotablad2?: string;
}

problema.component.html

<div class="mostrando">
      <mat-chip-list aria-label="Icono">
        <mat-chip>
          <h4>{{ "problemas.problemas.icon" | transloco }}:</h4>
          <mat-icon><fa-icon icon="{{ problema.icon }}"></fa-icon></mat-icon>
        </mat-chip>
      </mat-chip-list>
    </div>
  </div>
...

problema.component.ts

import {
  Component,OnInit,ChangeDetectionStrategy,OnDestroy,} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
// import { untilDestroyed } from 'ngx-take-until-destroy';
import { UntilDestroy,untilDestroyed } from '@ngneat/until-destroy';
import { filter,map,switchMap } from 'rxjs/operators';

import { ANIMACIOnes_RUTA_ELEMENTOS } from 'src/app/nucleo/nucleo.module';

import { ProblemasQuery } from 'src/app/pages/problemas/state/problemas.query';
import { ProblemasService } from 'src/app/pages/problemas/state/problemas.service';

@UntilDestroy()
@Component({
  selector: 'bab-problema',templateUrl: './problema.component.html',styleUrls: ['./problema.component.scss'],changeDetection: ChangeDetectionStrategy.OnPush,})
export class ProblemaComponent implements OnInit,OnDestroy {
  rutaAnimacionesElementos = ANIMACIOnes_RUTA_ELEMENTOS;
  problema$ = this.problemasQuery.selectEntity(this.problemaId);

  constructor(
    private activatedRoute: ActivatedRoute,private problemasQuery: ProblemasQuery,private problemasService: ProblemasService
  ) {}

  ngOnInit(): void {
    this.activatedRoute.paramMap.pipe(
      map((params) => params.get('id')),filter((id) => !this.problemasQuery.hasEntity(id)),untilDestroyed(this),switchMap((id) => this.problemasService.getProblemaPorId(id))
    );
  }

  get problemaId(): any {
    return this.activatedRoute.snapshot.params.id;
  }

  ngOnDestroy(): void {}
}

problemas.service.ts

@Injectable({ providedIn: 'root' })
export class ProblemasService {
  filtrosProblemas: AkitaFiltersPlugin<Problemasstate>;

  constructor(
    private problemasstore: Problemasstore,private problemasQuery: ProblemasQuery
  ) {
    this.filtrosProblemas = new AkitaFiltersPlugin<Problemasstate>(
      this.problemasQuery
    );
  }

  get(): Observable<Problema[]> {
    return timer(500).pipe(mapTo(problemas));
  }

  getProblemas(): Observable<Problema[]> {
    const request$ = this.get().pipe(
      tap((resp) => {
        this.problemasstore.set(resp);
      })
    );

    const requestUpdate$ = this.get().pipe(
      tap((resp) => {
        this.problemasstore.remove();
        this.problemasstore.set(resp);
      })
    );

    return this.problemasQuery.getHasCache() === false
      ? request$
      : requestUpdate$;

    // return request$;
  }

  getProblemaPorId(id: any): Observable<any> {
    const problema = problemas.find((current) => current.id === id);

    return timer(500).pipe(
      mapTo(problema),map(() => this.problemasstore.add(problema))
    );
  }

package.json

 "dependencies": {
    "@agm/core": "^3.0.0-beta.0","@angular/animations": "~11.0.6","@angular/cdk": "^11.0.3","@angular/common": "~11.0.6","@angular/compiler": "~11.0.6","@angular/core": "~11.0.6","@angular/forms": "~11.0.6","@angular/material": "^11.0.3","@angular/platform-browser": "~11.0.6","@angular/platform-browser-dynamic": "~11.0.6","@angular/router": "~11.0.6","@datorama/akita": "^4.22.0","@fortawesome/angular-fontawesome": "^0.8.1","@fortawesome/fontawesome-common-types": "^0.2.34","@fortawesome/fontawesome-free": "^5.15.1","@fortawesome/fontawesome-svg-core": "^1.2.34","@fortawesome/free-brands-svg-icons": "^5.15.1","@fortawesome/free-solid-svg-icons": "^5.15.1","@ngneat/transloco": "^2.20.0","@ngneat/transloco-locale": "^1.4.0","@ngneat/until-destroy": "^8.0.3","akita-filters-plugin": "^4.0.0","bootstrap": "^4.5.3","browser-detect": "^0.2.28","moment": "^2.29.1","ngx-take-until-destroy": "^5.4.0","rxjs": "~6.6.0","tslib": "^2.0.0","zone.js": "~0.10.2"
  },...

package-lock.json

"@fortawesome/angular-fontawesome": {
      "version": "0.8.1","resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.8.1.tgz","integrity": "sha512-dNmtFb/LTYWLNRfkKgCFwxgtQslNZLwUC+u7lkVAcIcjirIG6J9Ff0evl+9zR4DXFAkP0PN4RKe14NVDP3rUWA==","requires": {
        "tslib": "^2.0.3"
      }
    },"@fortawesome/fontawesome-common-types": {
      "version": "0.2.34","resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz","integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA=="
    },"@fortawesome/fontawesome-free": {
      "version": "5.15.2","resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz","integrity": "sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjsFymKSmTTPKYrivzbxxqA=="
    },"@fortawesome/fontawesome-svg-core": {
      "version": "1.2.34","resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.34.tgz","integrity": "sha512-0KNN0nc5eIzaJxlv43QcDmTkDY1CqeN6J7ocgSs+fwGPdtv0yOQqRjieopBCmw+yd7uD3N2HeNL3Zm5isDleLg==","requires": {
        "@fortawesome/fontawesome-common-types": "^0.2.34"
      },"dependencies": {
        "@fortawesome/fontawesome-common-types": {
          "version": "0.2.34","integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA=="
        }
      }
    },"@fortawesome/free-brands-svg-icons": {
      "version": "5.15.2","resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.2.tgz","integrity": "sha512-YPlVjE1cEO+OJ9I9ay3TQ3I88+XkxMTYwnnddqABoxLhPNGncsHV0DjWOVLCyuAY66yPfyndWwVn4v7vuqsO1g==","requires": {
        "@fortawesome/fontawesome-common-types": "^0.2.34"
      }
    },"@fortawesome/free-solid-svg-icons": {
      "version": "5.15.2","resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.2.tgz","integrity": "sha512-ZfCU+QjaFsdNZmogmfqEWhzI3JOe37x5dF4kz9GeXvKn/sTxhqMtZ7mh3lBf76SvcYY5/GKFuyG7p1r4iWMQqw==",...

当编译应用程序时,图标看起来和工作正常,但它会抛出错误 TS2322 类型‘字符串’不可分配给类型‘IconProp’

error TS2322

但是,当应用程序设法使用“ng serve”启动时,该图标是完全可见的:

the icon is displayed

我在没有它的情况下尝试过的:

  1. compilerOptions中切换到"strict" = false; tsconfig.json.
  2. 在其 official documentation 中阅读 angular-fontawesome 的说明。
  3. @fortawesome / fontawesome-svg-core 导入 * IconProp * 和其他类似 * IconName * 的内容,并将其分配给可选属性 "icon ?: string;"
    • “icon?: IconProp;”
    • “icon?: IconProp | string;”
    • “icon?: IconProp | IconName | string;”
  4. 按照此 issue 的建议,安装 ”@ fortawesome / fontawesome-common-types":"^ 0.2.34" 并使用相同版本的 @fortawesome/* 设置所有库 fontawesome-common-types
  5. 删除node_modules package-lock.json,然后在此issue之后运行npm i @ fortawesome / fontawesome-svg-core --savenpm install

我预先感谢您为我提供的所有宝贵帮助。谢谢。

更新:问题的解决方案。

我发现在 angularCompilerOptions 中设置 tsconfig.json 时使用启用 "strictTemplates ": truestrict mode 选项存在问题。

根据官方 angular documentationstrictTemplates 为 true 时,我们所做的是启用对模板类型的严格检查,这仅在 angular 9 及更高版本的 Ivy 中可用。

当我将 agm library 用于网络应用地图时,严格模式已经使我失败,所以我禁用了 strictTemplates。所以我禁用了严格模板,编译错误不再出现。这似乎是唯一的解决方案,因为我没有替代参数 "icon?: string;",它是 IconProp 类型,同时结合它与 html 模板中的角度插值。

解决方法

以前没有使用过这些图标,但您是否尝试过在 HTML 中不使用 {{ }} 引用它?

,

尝试以 font awesome 建议的方式使用它,并带有标签:

 <span >
            <i [ngClass]="['fas','fa-' + data.icon]"></i>

          </span>