티스토리 뷰

Angular2(이하 Angular) 개발시 Service에 선언한 Interface를 export를 하고 다른 컴퍼넌트에서 import를 할려고하니 아래와 같은 에러 메세지가 발생하였습니다.


WARNING in ./src/app/core/sidenav/sidenav-item/sidenav-item.component.ts

21:83-92 "export 'ISideItem' was not found in '../sidenav.service'

    at HarmonyImportSpecifierDependency._getErrors (/Users/david/work/resume/client/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:65:15)

    at HarmonyImportSpecifierDependency.getWarnings (/Users/david/work/resume/client/node_modules/webpack/lib/dependencies/HarmonyImportSpecifierDependency.js:39:15)

    at Compilation.reportDependencyErrorsAndWarnings (/Users/david/work/resume/client/node_modules/webpack/lib/Compilation.js:677:24)

    at Compilation.finish (/Users/david/work/resume/client/node_modules/webpack/lib/Compilation.js:535:9)

    at applyPluginsParallel.err (/Users/david/work/resume/client/node_modules/webpack/lib/Compiler.js:512:17)

    at /Users/david/work/resume/client/node_modules/tapable/lib/Tapable.js:289:11

    at _addModuleChain (/Users/david/work/resume/client/node_modules/webpack/lib/Compilation.js:481:11)

    at processModuleDependencies.err (/Users/david/work/resume/client/node_modules/webpack/lib/Compilation.js:452:13)

    at _combinedTickCallback (internal/process/next_tick.js:67:7)

    at process._tickCallback (internal/process/next_tick.js:98:9)


ISideItemsidenav.service에서 찾을 수 없다는데 export 잘 선언되어있고 작동도 잘하고 있었습니다.

waring이지만 뭔가 찜찜합니다. 일단 문제되던 코드를 살펴보겠습니다.


//sidenav-item.component.ts
import {Component, Input, OnInit} from '@angular/core';
import {ISideItem, SideItemTypes} from '../sidenav.service';

@Component({
  selector: 'app-sidenav-item',
  templateUrl: './sidenav-item.component.html',
  styleUrls: ['./sidenav-item.component.scss']
})
export class SidenavItemComponent implements OnInit {
  @Input('item') item: ISideItem;
  @Input('index') index: number;

  menuTypes = SideItemTypes;

  constructor() {}

  ngOnInit() {}
}

아래는 sidenav.service.ts 입니다.



import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

/**
 * sidenav 메뉴 type
 * (link/dropDown/icon/separator/extLink)
 */
export enum SideItemTypes {
  link,
  dropDown,
  icon,
  separator,
  extLink
}
/**
 * sidenav 메뉴 인터페이스
 */
export interface ISideItem {
  type: SideItemTypes;              // menu의 type:
  name?: string;                    // menu 노출될 이름
  path?: string;                    // 라우터 경로
  icon?: string;                    // 메뉴 아이콘
  tooltip?: string;                 // 메뉴 툴팁
  disabled?: boolean;               // 메뉴 숨김여부
  sub?: ISideSub[];                 // 하위 메뉴(Array)
}

/**
 * sidenav 하위 메뉴
 */
export interface ISideSub {
  name: string;                     // 하위메뉴 이름
  path: string;                     // 라우터 경로
}

@Injectable()
export class SidenavService {
  constructor() { }
  menu: ISideItem[] = [
    //....
  ];
  // 메뉴 subject
  menuItems = new BehaviorSubject(this.menu);
  // 메뉴 스트림
  menuItems$ = this.menuItems.asObservable();
}


분명히 Interface들이 선언이 잘되어있습니다. 구글링을 조금 해보니 해당 이슈가 발견되었습니다.

그리고 기존의 다른 개발자분들은 interface를 어떻게 export하고 import하고 있는지 확인해봤습니다.


angular.io/src/app/navigation/navigation.service.ts

// Import and re-export the Navigation model types
import { CurrentNodes, NavigationNode, NavigationResponse, NavigationViews, VersionInfo } from './navigation.model';
export { CurrentNodes, CurrentNode, NavigationNode, NavigationResponse, NavigationViews, VersionInfo } from './navigation.model';


Interface용 파일을 별도로 빼서 service에서 export로 from 구문으로 내보내고 있습니다.


그래서 아래와 같이 수정하였습니다.


//sidenav.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
// import 하고 export하는 이유는 https://github.com/angular/angular-cli/issues/2034#issuecomment-302666897 참고
import { ISideItem, SideItemTypes} from './sidenav.model';
export { ISideItem, ISideSub, SideItemTypes } from './sidenav.model';

@Injectable()
export class SidenavService {
  constructor() { }
  menu: ISideItem[] = [
    //...
  ];
  // 메뉴 subject
  menuItems = new BehaviorSubject(this.menu);
  // 메뉴 스트림
  menuItems$ = this.menuItems.asObservable();
}
// sidenav.model.ts
/**
 * sidenav 메뉴 type
 * (link/dropDown/icon/separator/extLink)
 */
export enum SideItemTypes {
  link,
  dropDown,
  icon,
  separator,
  extLink
}
/**
 * sidenav 메뉴 인터페이스
 */
export interface ISideItem {
  type: SideItemTypes;              // menu의 type:
  name?: string;                    // menu 노출될 이름
  path?: string;                    // 라우터 경로
  icon?: string;                    // 메뉴 아이콘
  tooltip?: string;                 // 메뉴 툴팁
  disabled?: boolean;               // 메뉴 숨김여부
  sub?: ISideSub[];                 // 하위 메뉴(Array)
}

/**
 * sidenav 하위 메뉴
 */
export interface ISideSub {
  name: string;                     // 하위메뉴 이름
  path: string;                     // 라우터 경로
}


Interface 선언용 파일 sidenav.model.ts를 별도로 분리하여 serivce에서 불러와 포함시키도록 하니 waring이 사라졌습니다.


Typescript에서 @(Decorator)를 사용한 경우 발생되는 문제라고 하니 참고하시면 좋을듯 합니다.

댓글