web-dev-qa-db-fra.com

Utilisation d'un espace de noms réparti sur plusieurs fichiers de module dans TypeScript

J'ai commencé à travailler sur un projet TypeScript à grande échelle.

Dès le départ, je veux garder mes fichiers organisés (ce projet sera partagé entre de nombreux développeurs donc l'ordre est très nécessaire).

J'ai essayé d'utiliser des modules/espaces de noms et de diviser les classes en fichiers séparés pour chacun, avec un dossier contenant l'espace de noms.

La structure du fichier est la suivante:

app.ts
\Classes
---- \Animals
---- ---- Mammals.ts
---- ---- Reptiles.ts

J'essaie ensuite d'importer tous les fichiers de cet espace de noms dans app.ts en utilisant quelque chose comme: import * as Animals from "./Classes/Animals"

En ce qui concerne les fichiers d'espace de noms eux-mêmes, j'ai essayé sans succès:

namespace Animals {
    export class Mammals {
        constructor() {
        }
    }
}

et aussi:

module Animals {
    export class Reptiles {
        constructor() {
        }
    }
}

Malheureusement, le chemin n'est jamais reconnu (car il pointe vers un dossier et non un seul fichier). Est-ce seulement possible? Le fait d'avoir toutes mes classes à partir d'un seul espace de noms dans un seul fichier entraînera des fichiers de milliers de lignes et pour ce projet qui n'est pas maintenable.

J'ai également remarqué que TypeScript 1.5 prend en charge tsconfig.json - cependant, devoir ajouter chaque fichier manuellement à la carte est une façon infaillible d'introduire des problèmes lorsque les développeurs commencent à ajouter des classes.

REMARQUE: j'utilise Visual Studio 2015, TypeScript 1.5 (je crois, je ne sais pas comment vérifier). J'ai également le support ES6 activé.

31
aaron-bond

Utilisez la réexportation pour créer un module externe qui regroupe et expose les types d'autres modules:

// Classes/Animals.ts
export * from '.\Animals\Mammals';
export * from '.\Animals\Reptiles';

Importez ensuite les types du nouveau module comme d'habitude:

// app.ts
import * as Animals from '.\Classes\Animals'

let dog: Animals.Dog;
let snake: Animals.Snake;

Ou

// app.ts
import { Dog, Snake } from '.\Classes\Animals'

let dog: Dog;
let snake: Snake;
27
Vadim Macagon

Trouvé un moyen d'atteindre votre objectif, mais pas avec le mot-clé namespace.

  1. Les classes "Animaux", Animal.ts & Mammal.ts & Reptile.ts sous namespace.
  2. avec index.ts pour le baril.
  3. animals.ts pour le regroupement des espaces de noms.

Animal namespace

Exemples de classes:

Classes

index.ts (en baril)

enter image description here

animals.ts (pour le regroupement d'espaces de noms)

enter image description here

Et ici, vous allez du concept de l'espace de noms.

enter image description here

15
Val

Les modules externes impliquent que vous chargez les modules fichier par fichier. AMD et CommonJS n'ont pas d'espace de noms. Vous pouvez utiliser une sorte de post-traitement pour regrouper les fichiers dans un module.


Ce qui suit définit un module interne:

module Animals {
    export class Reptiles {
        constructor() {
        }
    }
}

Vous ne devez pas utiliser import pour cela. Animals.Reptiles est visible partout. Le seul objectif est de charger les scripts dans le bon ordre (par exemple, les classes de base avant les héritiers). Vous devez donc répertorier tous les fichiers dans ts.config ou ailleurs. Dans mon projet, j'utilise des bundles sur des dossiers et j'ai une convention pour ajouter @ aux noms de fichiers des classes de base.

Une autre solution consiste à utiliser des modules externes: AMD ( RequireJS ) ou CommonJS ( Browserify ). Dans ce cas, supprimez le niveau supérieur module de la déclaration. Si un fichier ne contient qu'un seul type, vous pouvez l'exporter en tant que racine:

class Reptiles {
    constructor() {
    }
}

export = Reptiles;

Vous pouvez référencer le module par chemin de fichier:

import Reptilies = require('..\Animals\Reptilies')
var  reptile = new Reptile();

Ou avec de nouveaux modules ES6:

export class Reptiles {
    constructor() {
    }
}

import { Reptiles } from '..\Animals\Reptilies';
1
Artem

Il semble qu'il n'y ait aucun moyen de le faire en utilisant des espaces de noms seuls (sauf si vous souhaitez utiliser Module Augmentation et declare chaque nouvel élément à ajouter séparément); cependant, un espace de noms peut faire partie d'une classe, qui peut être étendue! C'est la meilleure alternative que je puisse trouver:

CoreLibraryTypes.ts

abstract class Types { }
namespace Types { 
    export class TypeA { }
    export class TypeB { }
    export class TypeC { }
}
export { Types };

CoreTypesExtended.ts

import CoreLibraryTypes from "./CoreLibraryTypes";

abstract class Types extends CoreLibraryTypes { }
namespace Types { 
    export class TypeD { }
    export class TypeE { }
    export class TypeF { }
}
export { Types };

L'inconvénient, bien sûr, est que seule l'importation du deuxième module aura les nouveaux types ajoutés. Le premier module restera comme avant. Idéalement, ce serait bien de "mettre à jour" un espace de noms de types avec des types supplémentaires (comme ceux des plugins), de telle sorte que l'augmentation du module était plus naturellement prise en charge (au lieu de devoir l'écrire à la main), mais je suppose que cela devra se faire jusqu'à quelqu'un réalise l'augmentation des modules en déclarant manuellement les définitions mises à jour n'est qu'un moyen à moitié de faire ce que les espaces de noms font déjà lol (y compris les classes, comme vu ci-dessus, qui peuvent déjà utiliser la fusion des espaces de noms dans le cadre de la classe). ;)

Remarque: Dans l'exemple ci-dessus, j'ai utilisé export { Types }; pour une raison - cela permettra à d'autres d'augmenter mes modules. L'augmentation n'est pas prise en charge pour les exportations par défaut (sauf si cela est souhaité - sorte de sceller virtuellement).

0
James Wilkins