ค้นหาเว็บไซต์

typescript - การนำเข้าเฉพาะชนิดการกำหนดค่าของห้องสมุดการตรวจสอบสิทธิ์ทำให้เกิดข้อผิดพลาดอ้างอิง


ฉันมีไลบรารีการยืนยันตัวตนที่ออกแบบมาเพื่อให้การยืนยันตัวตนสอดคล้องกันในเว็บแอปต่างๆ ได้ ได้รับแรงบันดาลใจจากไลบรารี angular-oauth2-oidc อย่างไรก็ตามฉันเจอปัญหาเมื่อทดสอบแอปของฉัน ในบริการการยืนยันตัวตนที่นำไปใช้งาน (employee-auth.service.ts) ซึ่งขยายจากบริการการยืนยันตัวตนของไลบรารี ฉันได้รับข้อผิดพลาด "ReferenceError: AuthLibConfig is not defined."

ฉันค้นพบในที่สุดว่าปัญหาคือการนำเข้าของไลบรารี config ตามคำสั่งของ eslint เป็นเพียงประเภทเท่านั้น ฉันกำลังมองหาคำอธิบายเกี่ยวกับสาเหตุที่การนำเข้าแบบประเภทเพียงอย่างเดียวไม่เพียงพอและทำไมมันถึงทำให้เกิดข้อผิดพลาดการอ้างอิงนี้

นี่ใช้ไม่ได้ แต่ผ่าน eslint

import { AUTH_CONFIG_TOKEN, type AuthLibConfig, AuthLibService } from '../auth-lib';

นี่ใช้ได้ แต่ทำให้เกิดข้อผิดพลาด eslint

import { AUTH_CONFIG_TOKEN, AuthLibConfig, AuthLibService } from '../auth-lib';

นี่คือสแตกบลิทซ์และคำแนะนำในการทำซ้ำ:

https://stackblitz.com/edit/stackblitz-starters-n8o79p

รอให้คอนเทนเนอร์ Stackblitz ติดตั้ง dependencies

  • กด Ctrl+C ที่แอปพลิเคชันที่ให้บริการอยู่
  • รัน ng test
  • พฤติกรรมที่คาดหวัง
  • ฉันคาดว่าการทดสอบจะผ่านโดยไม่มีข้อผิดพลาดการอ้างอิง สามารถลบ type ออกจากคำสั่งนำเข้าเพื่อให้การทดสอบผ่านได้

ฉันกำลังใช้ ng-mocks; ฉันกังวลเกี่ยวกับการที่มันอาจเป็นบั๊กของ MockBuilder ของพวกเขา แต่ฉันตัดทุกอย่างออกสำหรับการทดสอบหน่วย Angular ปกติและมันก็ไม่ได้ทำให้เกิดความแตกต่างใด ๆ

ฉันได้ลองให้ AuthLibConfig ในการทดสอบและสร้างอินสแตนซ์ของ AuthLibConfig โดยตรงในทดสอบแล้ว แต่ก็ยังคงเป็น undefined อยู่ดี

คำตอบ #1

ดังนั้น TS เข้าใจว่า AuthLibConfig ถูกใช้เป็นเพียง type ในไฟล์นั้นเท่านั้น แต่เราทราบว่า AuthLibConfig มากกว่าเพียง type ตามที่ใช้งานในโปรเจกต์ทั้งหมด ดังนั้นเราจึงไม่สามารถส่งออกมันเป็น type ได้

ถ้าเรา import มันเป็น type การอ้างอิง AuthLibConfig ในไฟล์นั้นจะไม่ถูกประมวลผลในระหว่างรันไทม์ของการทดสอบ และมันจะถูกตัดออกจากการกำหนดค่าที่บรรจุมาจริง ซึ่งส่งผลให้การทดสอบล้มเหลว

มันเหมือนกับการชักเย่อระหว่าง TS ที่มุ่งเน้นไปที่ไฟล์เดียวกับ Angular ที่มุ่งเน้นไปที่ทั้งโปรเจกต์ และไม่มีฝ่ายใดยอมแพ้วิธีการทำงานของตนโดยไม่ต่อสู้


ตัวเลือก 1: ผ่อนปรนกฎ eslint ของ TS สำหรับ consistent-type-imports แต่สามารถทำให้เกิดปัญหาได้หากโค้ดในอนาคตไม่ได้รับการจัดการอย่างถูกต้อง

(หรือ)

ตัวเลือกที่ 2: เขียนบริการที่ถูกฉีดใหม่โดยใช้วิธี inject ตามด้านล่าง,

จาก

...

export class EmployeeAuthService extends AuthLibService<Employee> {
  public constructor(
    @Inject(HttpClient) private readonly http: HttpClient,
    @Inject(OAuthService) oauth: OAuthService,
    @Inject(AUTH_CONFIG_TOKEN) config: AuthLibConfig
  ) {
    super(oauth, config);
  }
  ...
}

ถึง

import { inject } from '@angular/core'
...

export class EmployeeAuthService extends AuthLibService<Employee> {
  private readonly http = inject(HttpClient)
  oauth = inject(OAuthService)
  config = inject(AUTH_CONFIG_TOKEN)
  ...
}

สิ่งนี้จะทำให้ไม่จำเป็นต้องใช้ AuthLibConfig เป็น type แต่คุณอาจต้องเปลี่ยนในทุกไฟล์เพื่อความสอดคล้อง/อ่านง่ายที่ดียิ่งขึ้น