web-dev-qa-db-fra.com

Vous importez Victor.js dans TypeScript?

J'essaie d'utiliser la bibliothèque victor.js dans un projet TypeScript (3.0.1) et j'ai de la peine à essayer de l'importer et de l'utiliser. Je l'ai installé à partir de npm avec ses saisies (victor @ types/victor). J'ai essayé de l'importer d'une multitude de façons, mais je n'arrive pas à le faire importer avec la résolution de type dans mon IDE.

J'ai essayé ces derniers:

import { Victor} from 'victor';  
import * as v from 'victor'; 

(Ce module ne peut être référencé qu'avec les importations/exportations ECMAScript en activant le drapeau 'allowSyntheticDefaultImports' et en référençant son exportation par défaut)

import Victor = require('victor');  

(fonctionne mais n'est pas compatible lors du ciblage des modules ecmascript)

const Victor = require("victor");  

(Importe valablement et je peux construire des objets mais aucun des typages n'est présent)

Je suis sûr que quelqu'un a déjà rencontré une situation similaire à celle-ci auparavant. Si cela aide le haut de l'index.js du vainqueur a la ligne:

exports = module.exports = Victor;
27
radman

En bref

Vous essayez d'utiliser victor comme s'il s'agissait d'un module es6, mais ce n'est pas le cas. Je vois deux options:

  1. Laissez tsc convertir vos modules dans un format comme commonjs, auquel cas tsc fournira la logique de collage nécessaire entre victor et votre code

  2. Ou vous devez charger votre application via un chargeur de module qui fournit la colle.

Explication détaillée

Lorsque j'exécute le dernier tsc avec l'importation que vous montrez, l'erreur que j'obtiens est:

Ce module ne peut être référencé qu'avec les importations/exportations ECMAScript en activant l'indicateur 'esModuleInterop' et en référençant son exportation par défaut.

Lorsque j'active esModuleInterop, cela fonctionne très bien. Voici le code de test que j'ai utilisé:

import Victor from "victor";

const foo = new Victor(1, 2);
console.log(foo.y);

Et le tsconfig.json:

{
  "compilerOptions": {
    "esModuleInterop": true
  }
}

Le problème provient du fait que lorsque vous effectuez import Victor from "victor" vous demandez la valeur qui serait exportée via un export default..., qui est une syntaxe fournie par les modules es6. Cependant, victor exporte tout ce qui correspond à export default.... Il faut donc que quelque chose comble le fossé. Avec ce que j'ai montré ci-dessus, lorsque vous compilez, tsc émet ceci:

"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var victor_1 = __importDefault(require("victor"));
var foo = new victor_1["default"](1, 2);
console.log(foo.y);

Noter la __importDefault fonction d'assistance. Il est utilisé chaque fois que le code TS veut accéder à ce qu'un module exporte en tant que export default... Ce qu'il fait, c'est de vérifier si le module prétend être un module es6. Un module es6 qui souhaite exporter une valeur par défaut est déjà correctement structuré, il n'y a donc rien à faire si le module est un module es6. Si le module n'est pas un module es6, l'assistant crée une sorte de faux module dont la valeur exportée par défaut est la valeur du module d'origine.

Il y a une mise en garde importante puisque vous mentionnez "cibler les modules ecmascript". Si vous utilisez, cette tsconfig.json:

{
  "compilerOptions": {
    "esModuleInterop": true,
    "module": "es6"
  }
}

Alors le code émis est:

import Victor from "victor";
var foo = new Victor(1, 2);
console.log(foo.y);

Notez qu'il n'y a plus de fonction d'assistance. C'est au chargeur de modules qui chargera les modules de votre application de fournir la même logique que celle fournie par __importDefault. Si je renomme le fichier pour avoir l'extension mjs et que je lance:

$ node --experimental-modules test.mjs

J'obtiens cette sortie:

(node:18394) ExperimentalWarning: The ESM module loader is experimental.
2

Lorsque vous utilisez Node avec le support du module expérimental, il fournit les mêmes fonctionnalités que __importDefault.


Lorsque vous utilisez simplement allowSyntheticDefaultImports sans utiliser esModuleInterop, vous dites au compilateur supposez qu'il y aura quelque chose dans votre chaîne d'outils qui fera le travail de __importDefault. Le compilateur ne fournit donc pas d'aide. Il permet à la compilation de se poursuivre, mais vous êtes responsable plus tard d'utiliser un chargeur de module qui effectuera le même travail que __importDefault.

37
Louis

Je ressens votre chagrin d'amour, en ce que j'ai passé beaucoup de temps à déboguer diverses erreurs sur comment écrire des fichiers de définition TypeScript pour les modules javascript existants et finalement à ce que je pensais être le dernier obstacle quand je suis resté coincé sur la même erreur:

Ce module ne peut être référencé qu'avec les importations/exportations ECMAScript en activant le drapeau "allowSyntheticDefaultImports" et en référençant son exportation par défaut

Le javascript en question ici :

module.exports = class AthenaExpress { ...more code.. }

tsconfig.json pour la compilation/"Version de travail" 1:

{
  "compilerOptions": {
    "outDir": "dist/",
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es6",
    "jsx": "react"
  },
  "baseUrl": "./src",
  "include": [
    "**/*"
  ],
  "exclude": [
    "node_modules"
  ]
}

"Version de travail" du d.ts fichier avec quelques différences d'importation 2:

declare module 'athena-express' {
    import * as aws from "aws-sdk";
    interface ConnectionConfigInterface {
        aws: typeof aws,
        s3: string,
        getStats: boolean
    }
    interface QueryResultsInterface {
        Items: any[],
        DataScannedInMB: number,
        QueryCostInUSD: number,
        EngineExecutionTimeInMillis: number,
        Count: number,
    }

    interface QueryInterface {
        sql: string,
        db: string,
    }

    type QueryResult = QueryResultsInterface

    interface AthenaExpressInterface {
        new: (config: ConnectionConfigInterface) => any,
        query: (query: QueryInterface) => QueryResult,
    }

    class AthenaExpress {
        new: (config: ConnectionConfigInterface) => any;
        constructor(config: ConnectionConfigInterface);
        query: (query: QueryInterface) => QueryResult;
    }
}

Version du d.ts fichier qui a reçu la même erreur, même lorsque esModuleInterop était activé, j'ai également tripoté avec module et target en vain. Avec des différences de déclaration d'importation 3:

import * as aws from "aws-sdk";
interface ConnectionConfigInterface {
    aws: typeof aws,
    s3: string,
    getStats: boolean
}
interface QueryResultsInterface {
    Items: any[],
    DataScannedInMB: number,
    QueryCostInUSD: number,
    EngineExecutionTimeInMillis: number,
    Count: number,
}

interface QueryInterface {
    sql: string,
    db: string,
}

type QueryResult = QueryResultsInterface

interface AthenaExpressInterface {
    new: (config: ConnectionConfigInterface) => any,
    query: (query: QueryInterface) => QueryResult,
}

declare class AthenaExpress {
    new: (config: ConnectionConfigInterface) => any;
    constructor(config: ConnectionConfigInterface);
    query: (query: QueryInterface) => QueryResult;
}

export = AthenaExpress

notes:

L'emplacement du fichier de définition et le fichier que j'essayais de travailler avec la définition:

 tree src/backend/js
    src/backend/js
        ├── athena-express.d.ts
        └── helloworld.ts
  1. "Version de travail" signifiant tsc semblait compiler sans se plaindre
  2. Dans helloworld.ts import {AthenaExpress} from "athena-express";
  3. Dans helloworld.ts import * as AthenaExpress from "./athena-express";
4
jmunsch

Je vois qu'il y a déjà eu d'excellentes réponses, mais j'aimerais ajouter cette réponse plus courte.

Message d'erreur: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export.ts(2497)

J'ai eu ce problème avec l'importation lors du passage d'es5 à es6 (et javascript à TypeScript) lors de la conversion de mon propre fichier javascript en TypeScript.

Importer comme import * as File from "./MyFile" dans OtherFile.ts.

Dans le fichier MyFile.ts, j'avais export = {funcName} à la fin.

La solution consistait à supprimer = comme ça export {funcName} du fichier MyFile.ts.

(J'espère que cela aide quelqu'un, essayant pour la première fois de répondre à une erreur/problème)

1
Zpeed Tube