Hvorfor bryter importering av en node-modul mine interne Typescript-navnerom i atom-typescript?


Jeg har et veldig lite Node Typescript-prosjekt med følgende struktur:

Når jeg prøver å importere modulen "diff" i filen min index.ts på denne måten:

import * as diff from 'diff';

Atom-typescript mister plutselig evnen til å finne mitt "fgtApp.Interfaces"-navnerom:

Så snart jeg fjerner import-setningen, kan node løse opp navnerommet «fgtApp.Interfaces» uten problemer, slik:

Er dette en feil i atom-typescript eller en feil i min forståelse av hvordan importering av disse eksterne modulene fungerer?

Svar #1

Dette er ikke spesifikt et problem med atom-typescript. Atom-typescript-pluginen bruker den offisielle TypeScript-språkservicen (samme som Visual Studio), så dette ville være et problem i hvilken som helst editor.

Problemet er at når du har angitt en import eller eksport, blir filen et modul ("eksternt modul" før TypeScript 1.5). Dette betyr at når import * as diff from 'diff'; er til stede, blir ting som er erklært i index.ts kun lokale og tas ikke med i/merges med det globale navnerommet.

TypeScript-spesifikasjon, seksjon 11.1: ...kildefiler som inneholder minst én ekstern importdeklarasjon, eksportoppgave, eller toppnivå eksportert deklarasjon anses som separate eksterne moduler. Entiteter deklarert i en ekstern modul er kun tilgjengelige i den modulen, men eksporterte entiteter kan importeres til andre moduler ved hjelp av importdeklarasjoner

Når du ikke bruker eksterne moduler, lar TypeScript navneområder i forskjellige filer bygge videre på hverandre. Når du begynner å bruke eksterne moduler, er dette ikke lenger tilfelle uten å bruke løsninger. I dette tilfellet er det ofte best å bare bytte til å bruke eksterne moduler - hvis du lager et Node-prosjekt, er dette spesielt enkelt fordi du ikke trenger å bekymre deg for pakking.

I stedet for et "dypt navneområde" (f.eks. fgtApp.category.thing) som C# og .NET oppmuntrer til - begynn å tenke på hver TypeScript-kildefil som sitt eget modul. Hvis du virkelig ønsker en hierarki, implementer det med en mappestruktur.

Denne koden vil fungere som forventet selv med noImplicitAny aktiv:

interfaces.d.ts

// Notice that this is a d.ts file.  Since it will only contain interfaces,
//  making it a d.ts file means TypeScript doesn't have to worry about
//  emitting it and you also can't accidentally put executable code here.
export interface IFgtService {
    authenticateDisable: boolean;
    failedAttempt: boolean;
    authenticate: (username: string, password: string) => boolean;
}

export interface IAnotherInterfaceAsAnExample {
    isCool: boolean;
}

service.ts

// since there is no "relative path", diff will come from node_modules.
import * as diff from 'diff';
// since there IS a relative path, interfaces will come from ./interfaces.d.ts
import * as interfaces from './interfaces';

// You can still use namespaces inside an "external module", but mainly they
//  serve as a convenient way to bundle stuff for a one-line export (see
//  the last line of this file).
namespace Service {
  export class FgtService implements interfaces.IFgtService {
    authenticateDisable = true;
    failedAttempt = true;
    authenticate = (username: string, password: string) => {
      let d = diff.d;
      return true;
    }
  }
}
export = Service;

index.ts

import {FgtService} from './Service';

const myService = new FgtService();
console.log(myService.authenticateDisable);

Relaterte artikler