javascript - Kan inte använda exporten av en ambient modul som typannotering i TypeScript


Jag skriver en TypeScript-typdefinition för ett ganska stort (800+ filer) AMD JavaScript-bibliotek. Nedan kan du se ett utdrag:

declare namespace myjslib {
  namespace shape {
    interface Shape {
      contains(p: Point): boolean;
    }

    class Point implements Shape {
      constructor(x: number, y: number);
      contains(p: Point): boolean;
    }

    class Circle implements Shape {
      constructor(p: Point, radius: number);
      contains(p: Point): boolean;
    }
  }
}

declare module "myjslib/shape/Point" {
  export = myjslib.shape.Point;
}

declare module "myjslib/shape/Circle" {
  export = myjslib.shape.Circle;
}

Jag har definierat typer i namnrymder. (Observera att myjslib inte är det verkliga namnet på biblioteket :)):

  • Namespace:en motsvarar i stort sett modul-ID:na i AMD-biblioteket, som du kan se från moduldeklarationerna.
  • Jag bestämde mig för att lägga dessa klasser i namnrymder för att undvika konflikter (jfr. https://www.typescriptlang.org/docs/handbook/writing-declaration-files.html). Klassnamn som Point och Circle kan lätt krocka om mitt bibliotek kombineras med andra JavaScript-bibliotek.

Jag försöker sedan skriva en TypeScript-applikation som är beroende av denna typdefinitionsfil:

/// <reference path="./myjslib.d.ts" />
import Point = require("myjslib/shape/Point");
import Circle = require("myjslib/shape/Circle");

import Circ = myjslib.shape.Circle;

let c1 = new Circle(new Point(1,3), 20);
let c2: Circle;
let c3: myjslib.shape.Circle;
let c4: Circ;

c1.contains(new Point(5,6));
c2 = c1;
c3 = c1;
c4 = c1;

När denna TypeScript-fil kompileras genereras korrekt JavaScript-kod: utdata är giltig AMD, kan laddas med en färdig AMD-modulladdare och kan optimeras till en enda JavaScript-fil, etc.

Dock genererar TypeScript-kompilatorn ett fel vid deklarationen av c2-variabeln:

>tsc --module amd app.ts
app.ts(8,9): error TS2304: Cannot find name 'Circle'.

Tydligen är det möjligt att hänvisa till den importerade Circle för att skapa en cirkel. import-satsen fungerar eftersom du har tillgång till Circle-konstruktorn. Däremot kan Circle inte användas som en typannotation när du deklarerar en variabel av den typen. Det som också är möjligt är att använda det fullständiga kvalificerade namnet för typen: kompilatorn klagar inte på c3-deklarationen, så TypeScript-definitionfilen hittas och används av kompilatorn. Dessutom, om jag skapar ett alias Circ, fungerar typsystemet perfekt (deklaration av c4).

Jag förstod det som att import Circle=require("myjslib/shape/Circle")-satsen även importerade typinformationen. Med terminologin i TypeScript Deep Dive skulle jag förvänta mig att Circle är tillgänglig i typdeklarationsutrymmet i den modulen, men det är det inte. Typinformationen laddas dock genom TypeScript-definitionfilen: myjslib-namnrymden är tillgänglig.

Så för att sammanfatta: Jag måste skriva kod där jag måste använda importen för att skapa instanser av en viss klass, men jag måste använda det fullständigt kvalificerade typenamnet om jag vill deklarera variabler av den klassen. Detta gör kodskrivningen ganska förvirrande (och ordkrävande). Finns det något sätt runt detta? Är detta det förväntade beteendet, eller råkar jag ut för en bugg i TypeScript-kompilatorn?