2012-11-18 15 views
13

TypeScripts astrae le importazioni/esportazioni di moduli in modo "dichiarativo".TypeScript - import/export di modulo condizionale

Ma cosa succede se voglio importare o esportare qualcosa in base a una condizione calcolata in fase di esecuzione?

Il caso di utilizzo più comune è la condivisione del codice tra piattaforme come Node.js e Windows Script Host.

Gli io.ts propri di TypeScript che astraggono input/output nel compilatore TSC eseguono manualmente gli hacks attorno alla sintassi del modulo incorporata in TypeScript. E 'l'unica possibilità?

P.S. Il problema con semplicemente attaccare import fs = module ("fs") in se l'istruzione è che TypeScript consente solo le istruzioni di importazione ad un livello superiore. Il che significa che in WSH require ("fs") verrà eseguito e ovviamente non funzionante, poiché richiede non è definito.

risposta

8

Sono d'accordo che il fatto che essi possono avere solo scopo livello superiore è ottimale al meglio. Oltre al problema che hai affermato, significa anche tempi di caricamento iniziali del software più lenti. Per esempio all'interno di nodejs I ora qualche volta carico un modulo in una funzione se quella funzione viene usata raramente. Quindi la mia applicazione si avvia più velocemente poiché non carica ancora quel modulo.

E, naturalmente, è possibile utilizzare direttamente o direttamente la richiesta o AMD, ma in questo modo si dimenticheranno alcuni vantaggi della digitazione.

Penso tuttavia che il vero problema risieda nel fatto che i moduli definiti da harmony/es6 siano di livello superiore e TS sembra seguire questa proposta. Quindi non sono sicuro di quanto il team TS possa fare senza derivare dall'organismo degli standard.

0

Esiste un meccanismo per le importazioni dinamiche in TypeScript, sebbene l'implementazione differisca in base al tipo di modulo.

Il seguente esempio (per AMD) sarà condizionato caricare il modulo:

declare function require(moduleNames: string[], onLoad: (...args: any[]) => void): void; 

import * as ModuleAlias from './mod'; 

const someCondition = true; 

if (someCondition) { 
    require(["./mod"], (module: typeof ModuleAlias) => { 
     console.log(module.go()); 
    }); 
} 

Il import istruzione nella parte superiore del file è inerte, e il carico effettivo del modulo non accadrà a meno che la condizione if (someCondition) è vero.

È possibile verificare questo modificando someCondition e vedere l'impatto sulla vostra scheda di rete, o si può guardare il codice generato ... nella versione dinamica, "./mod" non appare nella chiamata define. In quello non dinamico, lo fa.

con caricamento dinamico

define(["require", "exports"], function (require, exports) { 
    "use strict"; 
    Object.defineProperty(exports, "__esModule", { value: true }); 
    const someCondition = true; 
    if (someCondition) { 
     require(["./mod"], (module) => { 
      console.log(module.go()); 
     }); 
    } 
}); 

Senza dinamica Caricamento

define(["require", "exports", "./mod"], function (require, exports, ModuleAlias) { 
    "use strict"; 
    Object.defineProperty(exports, "__esModule", { value: true }); 
    const someCondition = true; 
    if (someCondition) { 
     console.log(ModuleAlias.go()); 
    } 
}); 
5

Ho una soluzione leggermente goffo ma molto efficace per questo, in particolare se si utilizza l'importazione/esportazione condizionale per il test delle unità.

Avere un'esportazione che viene sempre emessa, ma rendere il contenuto varia in base a un valore di runtime. Per esempio.:

// outputModule.ts 
export const priv = (process.env.BUILD_MODE === 'test') 
    ? { hydrateRecords, fillBlanks, extractHeaders } 
    : null 

Poi nel file che consumano, importare l'esportazione, verificare che il valore importato esiste, e se lo fa, assegnare tutti i valori si sarebbe altrimenti importati stand-alone a un insieme di variabili:

// importingModule.spec.ts 
import { priv } from './outputModule'; 

const { hydrateRecords, fillBlanks, extractHeaders } = priv as any; 
// these will exist if environment var BUILD_MODE==='test' 

Limitazioni:

  1. È purtroppo necessario impostare l'importazione di 'qualsiasi' per rendere il compilatore felice.
  2. È necessario verificare se sono state definite o meno importazioni specifiche (ma che viene fornito con il territorio).
  3. Il file di importazione si aspetta che i valori siano definiti. Dovrai quindi assicurarti che l'importazione dei file abbia effettivamente bisogno dei moduli (che va bene se ad esempio gestisci i file solo durante i test), o dovrai definire valori alternativi per i casi in cui non vengono effettivamente esportati.

Tuttavia, ha funzionato molto bene per me per i miei scopi, speriamo che funzioni anche per voi. È particolarmente utile per i metodi privati ​​di test unitari.

Problemi correlati