Angular 18升级FontAwesome 6.6.0后类型不兼容编译错误求助
Angular 18 + FontAwesome 6.6.0 升级类型不兼容问题解决
背景
将Angular项目从17升级到18,同步升级FontAwesome至6.6.0、@fortawesome/angular-fontawesome至0.15.0,已确认package-lock.json中所有FontAwesome相关包版本一致。此前使用的是FontAwesome 6.5.2和@fortawesome/angular-fontawesome 0.14.1。按照官方指引将类型导入从@fortawesome/fontawesome-svg-core迁移至@fortawesome/angular-fontawesome后,出现编译错误。
编译错误信息
✘ [ERROR] TS2345: Argument of type 'IconDefinition' is not assignable to parameter of type 'IconName | IconLookup'. Type 'IconDefinition' is not assignable to type 'IconLookup'. Types of property 'prefix' are incompatible. Type 'import("D:/Project/Frontend/OAKKPortal/OAKKPortal/node_modules/@fortawesome/angular-fontawesome/types").IconPrefix' is not assignable to type 'import("D:/Project/Frontend/OAKKPortal/OAKKPortal/node_modules/@fortawesome/fontawesome-common-types/index").IconPrefix'. Type 'string & {}' is not assignable to type 'IconPrefix'. [plugin angular-compiler] projects/material-lib/src/lib/util/register-icons.class.ts:43:20: 43 │ return iconFunc(icon).html.join(''); ╵ ~~~~ ✘ [ERROR] TS2345: Argument of type 'IconDefinition' is not assignable to parameter of type 'IconName | IconLookup'. [plugin angular-compiler] projects/material-lib/src/lib/util/register-icons.class.ts:47:54: 47 │ ...n sanitizer.bypassSecurityTrustHtml(iconFunc(icon).html.join('')); ╵ ~~~~
相关代码
import { MatIconRegistry } from '@angular/material/icon'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; import { FaIconLibrary, IconDefinition, IconName, IconPrefix, } from '@fortawesome/angular-fontawesome'; import { icon as iconFunc } from '@fortawesome/fontawesome-svg-core'; export class RegisterFontIcons { public static registerMaterialIcons(iconRegistry: MatIconRegistry) { // Register the material icon styles iconRegistry.registerFontClassAlias( 'outlined', 'mat-ligature-font material-icons material-icons-outlined', ); } public static registerFontAwesomIcons(iconRegistry: MatIconRegistry) { // Set default font set to Font Awesome Solid icons for non-SVG icons iconRegistry.setDefaultFontSetClass('fa-solid'); } public static registerFontAwesomSvgIcons( iconRegistry: MatIconRegistry, sanitizer: DomSanitizer, icons: IconDefinition[], ) { icons.forEach((icon: IconDefinition) => { // console.log(icon.prefix, icon.iconName); const svg: SafeHtml = RegisterFontIcons.getLiteralSafeSvg(sanitizer, icon); if (icon.prefix === 'fas') { iconRegistry.addSvgIconLiteral(icon.iconName, svg); } else { // Only use a namespace for the non-solid icons iconRegistry.addSvgIconLiteralInNamespace(icon.prefix, icon.iconName, svg); } }); } public static getLiteralSvg(icon: IconDefinition): string { return iconFunc(icon).html.join(''); } public static getLiteralSafeSvg(sanitizer: DomSanitizer, icon: IconDefinition): SafeHtml { return sanitizer.bypassSecurityTrustHtml(iconFunc(icon).html.join('')); } public static getFontAwesomeIcon( faIconLibrary: FaIconLibrary, prefix: IconPrefix, name: IconName, ): IconDefinition { return faIconLibrary.getIconDefinition(prefix, name); } }
尝试修改后的新错误
尝试将传入iconFunc的参数改为IconLookup格式后,出现类型不兼容错误:
public static getLiteralSvg(icon: IconDefinition): string { return iconFunc({ iconName: icon.iconName, prefix: icon.prefix }).html.join(''); }
错误信息:
✘ [ERROR] TS2322: Type 'import("D:/Project/Frontend/OAKKPortal/OAKKPortal/node_modules/@fortawesome/angular-fontawesome/types").IconName' is not assignable to type 'import("D:/Project/Frontend/OAKKPortal/OAKKPortal/node_modules/@fortawesome/fontawesome-common-types/index").IconName'. Type 'string & {}' is not assignable to type 'IconName'. [plugin angular-compiler] projects/material-lib/src/lib/util/register-icons.class.ts:43:22: 43 │ return iconFunc({ iconName: icon.iconName, prefix: icon.prefix... ╵ ~~~~~~~~ ✘ [ERROR] TS2322: Type 'import("D:/Project/Frontend/OAKKPortal/OAKKPortal/node_modules/@fortawesome/angular-fontawesome/types").IconPrefix' is not assignable to type 'import("D:/Project/Frontend/OAKKPortal/OAKKPortal/node_modules/@fortawesome/fontawesome-common-types/index").IconPrefix'. Type 'string & {}' is not assignable to type 'IconPrefix'. [plugin angular-compiler] projects/material-lib/src/lib/util/register-icons.class.ts:43:47: 43 │ ...c({ iconName: icon.iconName, prefix: icon.prefix }).html.join(''); ╵ ~~~~~~
解决方法
方法一:统一类型导入来源(推荐)
错误根源是@fortawesome/angular-fontawesome 0.15.x封装了内部的Icon类型,与@fortawesome/fontawesome-svg-core、@fortawesome/fontawesome-common-types的原始类型不再是同一引用。将类型导入改为从原始包获取,即可统一类型:
修改代码的导入部分:
import { MatIconRegistry } from '@angular/material/icon'; import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; // 仅从angular-fontawesome导入FaIconLibrary import { FaIconLibrary } from '@fortawesome/angular-fontawesome'; // 从fontawesome-svg-core导入IconDefinition import { IconDefinition } from '@fortawesome/fontawesome-svg-core'; // 从fontawesome-common-types导入IconName、IconPrefix import { IconName, IconPrefix } from '@fortawesome/fontawesome-common-types'; import { icon as iconFunc } from '@fortawesome/fontawesome-svg-core';
方法二:类型断言
如果不想调整导入结构,可以通过类型断言将angular-fontawesome的类型转换为fontawesome-svg-core可接受的类型:
修改getLiteralSvg和getLiteralSafeSvg函数:
public static getLiteralSvg(icon: IconDefinition): string { // 将angular-fontawesome的类型断言为fontawesome-svg-core的IconDefinition return iconFunc(icon as unknown as import('@fortawesome/fontawesome-svg-core').IconDefinition).html.join(''); } public static getLiteralSafeSvg(sanitizer: DomSanitizer, icon: IconDefinition): SafeHtml { return sanitizer.bypassSecurityTrustHtml( iconFunc(icon as unknown as import('@fortawesome/fontawesome-svg-core').IconDefinition).html.join('') ); }
或者针对IconLookup做更细粒度的断言:
import { IconLookup } from '@fortawesome/fontawesome-svg-core'; // ... public static getLiteralSvg(icon: IconDefinition): string { const lookup: IconLookup = { iconName: icon.iconName as import('@fortawesome/fontawesome-common-types').IconName, prefix: icon.prefix as import('@fortawesome/fontawesome-common-types').IconPrefix }; return iconFunc(lookup).html.join(''); }
内容的提问来源于stack exchange,提问作者Kees de Bruin
相关产品推荐
相关产品推荐

