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

lba*_*oni 7 font-awesome angular-material angular angular-fontawesome

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

\n

我的代码:

\n

comun.module.tsangular material icon :导入和导出的公共模块 fontawesome

\n
import { MatIconModule } from \'@angular/material/icon\';\n...\n// FontAwesome\nimport {\n  FontAwesomeModule,\n  FaIconLibrary,\n} from \'@fortawesome/angular-fontawesome\';\nimport {\n  faBars,\n  faDonate,\n  \xe2\x80\xa6\n} from \'@fortawesome/free-solid-svg-icons\';\n\xe2\x80\xa6\nexport class ComunModule {\n  constructor(library: FaIconLibrary) {\n    library.addIcons(\n      faBars,\n      faDonate,\n...\n
Run Code Online (Sandbox Code Playgroud)\n

问题模型.ts

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

Problema.component.html

\n
<div class="mostrando">\n      <mat-chip-list aria-label="Icono">\n        <mat-chip>\n          <h4>{{ "problemas.problemas.icon" | transloco }}:</h4>\n          <mat-icon><fa-icon icon="{{ problema.icon }}"></fa-icon></mat-icon>\n        </mat-chip>\n      </mat-chip-list>\n    </div>\n  </div>\n...\n
Run Code Online (Sandbox Code Playgroud)\n

问题组件.ts

\n
import {\n  Component,\n  OnInit,\n  ChangeDetectionStrategy,\n  OnDestroy,\n} from \'@angular/core\';\nimport { ActivatedRoute } from \'@angular/router\';\n// import { untilDestroyed } from \'ngx-take-until-destroy\';\nimport { UntilDestroy, untilDestroyed } from \'@ngneat/until-destroy\';\nimport { filter, map, switchMap } from \'rxjs/operators\';\n\nimport { ANIMACIONES_RUTA_ELEMENTOS } from \'src/app/nucleo/nucleo.module\';\n\nimport { ProblemasQuery } from \'src/app/pages/problemas/state/problemas.query\';\nimport { ProblemasService } from \'src/app/pages/problemas/state/problemas.service\';\n\n@UntilDestroy()\n@Component({\n  selector: \'bab-problema\',\n  templateUrl: \'./problema.component.html\',\n  styleUrls: [\'./problema.component.scss\'],\n  changeDetection: ChangeDetectionStrategy.OnPush,\n})\nexport class ProblemaComponent implements OnInit, OnDestroy {\n  rutaAnimacionesElementos = ANIMACIONES_RUTA_ELEMENTOS;\n  problema$ = this.problemasQuery.selectEntity(this.problemaId);\n\n  constructor(\n    private activatedRoute: ActivatedRoute,\n    private problemasQuery: ProblemasQuery,\n    private problemasService: ProblemasService\n  ) {}\n\n  ngOnInit(): void {\n    this.activatedRoute.paramMap.pipe(\n      map((params) => params.get(\'id\')),\n      filter((id) => !this.problemasQuery.hasEntity(id)),\n      untilDestroyed(this),\n      switchMap((id) => this.problemasService.getProblemaPorId(id))\n    );\n  }\n\n  get problemaId(): any {\n    return this.activatedRoute.snapshot.params.id;\n  }\n\n  ngOnDestroy(): void {}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

问题服务.ts

\n
@Injectable({ providedIn: \'root\' })\nexport class ProblemasService {\n  filtrosProblemas: AkitaFiltersPlugin<ProblemasState>;\n\n  constructor(\n    private problemasStore: ProblemasStore,\n    private problemasQuery: ProblemasQuery\n  ) {\n    this.filtrosProblemas = new AkitaFiltersPlugin<ProblemasState>(\n      this.problemasQuery\n    );\n  }\n\n  get(): Observable<Problema[]> {\n    return timer(500).pipe(mapTo(problemas));\n  }\n\n  getProblemas(): Observable<Problema[]> {\n    const request$ = this.get().pipe(\n      tap((resp) => {\n        this.problemasStore.set(resp);\n      })\n    );\n\n    const requestUpdate$ = this.get().pipe(\n      tap((resp) => {\n        this.problemasStore.remove();\n        this.problemasStore.set(resp);\n      })\n    );\n\n    return this.problemasQuery.getHasCache() === false\n      ? request$\n      : requestUpdate$;\n\n    // return request$;\n  }\n\n  getProblemaPorId(id: any): Observable<any> {\n    const problema = problemas.find((current) => current.id === id);\n\n    return timer(500).pipe(\n      mapTo(problema),\n      map(() => this.problemasStore.add(problema))\n    );\n  }\n
Run Code Online (Sandbox Code Playgroud)\n

包.json

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

包锁.json

\n
"@fortawesome/angular-fontawesome": {\n      "version": "0.8.1",\n      "resolved": "https://registry.npmjs.org/@fortawesome/angular-fontawesome/-/angular-fontawesome-0.8.1.tgz",\n      "integrity": "sha512-dNmtFb/LTYWLNRfkKgCFwxgtQslNZLwUC+u7lkVAcIcjirIG6J9Ff0evl+9zR4DXFAkP0PN4RKe14NVDP3rUWA==",\n      "requires": {\n        "tslib": "^2.0.3"\n      }\n    },\n    "@fortawesome/fontawesome-common-types": {\n      "version": "0.2.34",\n      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz",\n      "integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA=="\n    },\n    "@fortawesome/fontawesome-free": {\n      "version": "5.15.2",\n      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-5.15.2.tgz",\n      "integrity": "sha512-7l/AX41m609L/EXI9EKH3Vs3v0iA8tKlIOGtw+kgcoanI7p+e4I4GYLqW3UXWiTnjSFymKSmTTPKYrivzbxxqA=="\n    },\n    "@fortawesome/fontawesome-svg-core": {\n      "version": "1.2.34",\n      "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.34.tgz",\n      "integrity": "sha512-0KNN0nc5eIzaJxlv43QcDmTkDY1CqeN6J7OCGSs+fwGPdtv0yOQqRjieopBCmw+yd7uD3N2HeNL3Zm5isDleLg==",\n      "requires": {\n        "@fortawesome/fontawesome-common-types": "^0.2.34"\n      },\n      "dependencies": {\n        "@fortawesome/fontawesome-common-types": {\n          "version": "0.2.34",\n          "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.34.tgz",\n          "integrity": "sha512-XcIn3iYbTEzGIxD0/dY5+4f019jIcEIWBiHc3KrmK/ROahwxmZ/s+tdj97p/5K0klz4zZUiMfUlYP0ajhSJjmA=="\n        }\n      }\n    },\n    "@fortawesome/free-brands-svg-icons": {\n      "version": "5.15.2",\n      "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-5.15.2.tgz",\n      "integrity": "sha512-YPlVjE1cEO+OJ9I9ay3TQ3I88+XkxMTYwnnddqAboxLhPNGncsHV0DjWOVLCyuAY66yPfyndWwVn4v7vuqsO1g==",\n      "requires": {\n        "@fortawesome/fontawesome-common-types": "^0.2.34"\n      }\n    },\n    "@fortawesome/free-solid-svg-icons": {\n      "version": "5.15.2",\n      "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.2.tgz",\n      "integrity": "sha512-ZfCU+QjaFsdNZmOGmfqEWhzI3JOe37x5dF4kz9GeXvKn/sTxhqMtZ7mh3lBf76SvcYY5/GKFuyG7p1r4iWMQqw==",\n      "requires": {\n        "@fortawesome/fontawesome-common-types": "^0.2.34"\n      }\n    },\n...\n
Run Code Online (Sandbox Code Playgroud)\n

编译应用程序时,图标看起来并可以工作,但它会引发错误TS2322 Type \xe2\x80\x98string\xe2\x80\x99 is not assignable to Type \xe2\x80\x98IconProp\xe2\x80\x99 : \n错误 TS2322

\n

但是,当应用程序设法使用“ngserve”启动时,该图标完全可见:\n显示图标

\n

我尝试过但没有成功:

\n
    \n
  1. 切换到\n tsconfig.json"strict" = false;中的编译器选项
  2. \n
  3. 阅读 angular-fontawesome官方文档中的说明
  4. \n
  5. 导入 * IconProp * 和其他类似 * IconName * 的内容@fortawesome / fontawesome-svg-core并将其分配给可选属性"icon ?: string;":\n
      \n
    • \xe2\x80\x9cicon?: IconProp;\xe2\x80\x9d
    • \n
    • \xe2\x80\x9cicon?: IconProp | string;\xe2\x80\x9d
    • \n
    • \xe2\x80\x9cicon?: IconProp | IconName | string;\xe2\x80\x9d
    • \n
    \n
  6. \n
  7. 按照本建议安装并设置具有相同版本的\xe2\x80\x9d@ fortawesome / fontawesome-common-types":"^ 0.2.34"所有库@fortawesome/*fontawesome-common-types问题
  8. \n
  9. 删除node_modules package-lock.json,然后运行npm i @ fortawesome / fontawesome-svg-core --savenpm install按照此操作问题
  10. \n
\n

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

\n

更新:问题的解决方案。

\n

我发现问题在于设置angularCompilerOptions启用的 tsconfig.json选项"strictTemplates ": truestrict mode

\n

根据官方角度文档,当strictTemplates的就是启用模板类型的严格检查,这仅适用于 Angular 版本 9 及更高版本的 Ivy。

\n

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

\n