Moment: [TypeScript] "erreur TS2304 : Impossible de trouver le nom 'moment'" lorsqu'il est utilisé avec "module":"none"

Créé le 14 févr. 2017  ·  51Commentaires  ·  Source: moment/moment

Typescript semble ne pas être en mesure de résoudre la fonction globale moment() lorsqu'il est utilisé dans un contexte non-module.

version tsc : 2.1.6
version momentanée : 2.17.1

Repro (en supposant que tsc trouve sur votre $PATH ):

$ mkdir repro && cd repro
$ npm i moment
$ echo 'const now = moment();' > test.ts
$ tsc --module none test.ts
test.ts(1,13): error TS2304: Cannot find name 'moment'.

Cependant, l'utilisation d'un type de module fonctionne comme prévu :

$ echo 'import * as moment from "moment"; const now = moment();' > test2.ts
$ tsc --module commonjs test2.js

Malheureusement, mon projet n'utilise pas de bundler ou de système de module, donc je suis bloqué avec "module": "none" pour le moment.

Est-ce que ma seule alternative est d'utiliser quelque chose comme typings install --save --global dt~moment ?

TypeScript Up-For-Grabs

Commentaire le plus utile

+1 s'il vous plaît corriger cela

Tous les 51 commentaires

Je suis confronté au même problème. Peu importe le type de module que vous spécifiez dans tsconfig.json. J'obtiens la même erreur que

J'ai signalé le même problème (https://github.com/moment/moment/issues/3663), mais malheureusement, il a été fermé sans aucune réaction.

J'ai fini par copier moment.d.ts dans mon répertoire /scripts/app et implémenté le correctif spécifié dans https://github.com/moment/moment/issues/3663#issuecomment -273199291

Espérons qu'un correctif plus permanent finira par faire son chemin dans moment.d.ts .

J'ai résolu ce problème en spécifiant "moduleResolution": "node" dans mon tsconfig. Je ne sais pas si c'est une option pour vous, mais cela semble faire l'affaire.

"moduleResolution": "node" ne l'a pas résolu pour moi, malheureusement

@rossipedia Moi non plus.

Ne serait-il pas utile d'ajouter export as namespace moment; dans le fichier moment.d.ts ?

Voir : https://github.com/moment/moment/issues/3808

@czb qui n'a pas non plus

J'ai résolu ce problème en utilisant quelques hacks que d'autres ont mentionnés autour d'une tonne de problèmes dans de nombreux projets qui rencontrent ce problème. Enveloppez-le simplement dans votre propre fichier de définition personnalisé. Ceci utilise Typescript 2.2. De cette façon, je ne m'occupe pas de la dépendance provenant de npmjs.org et je n'ai pas à vérifier le tout dans le contrôle de source.

tsconfig.json

"compilerOptions": {
    "target": "ES5",
    "moduleResolution": "node",
    ...
}

moment.custom.d.ts

import * as _moment from 'moment';
export as namespace moment;
export = _moment;

Je suis curieux de savoir pourquoi cela ne fonctionne pas lorsque ce code est ajouté directement à moment.d.ts ? Je ne peux pas m'empêcher de penser que nous nous heurtons à un obscur bug de résolution TypeScript, et malheureusement tsc n'a pas de mode détaillé (à ma connaissance) qui aiderait à identifier où les choses ne vont pas.

Je pense que si vous définissez "module": "none" tapuscrit ne cherche pas d.ts fichiers sous le node_modules/moment dossier. Mon expérience est qu'il ne regarde que sous le dossier node_modules/@types . Il y a donc essentiellement ces options.

  1. Copier moment.d.ts sous node_modules/@types/moment
  2. Incluez /// <reference path="./node_modules/moment/moment.d.ts" /> dans votre fichier .ts
  3. Appelez tsc --typeRoots node_modules test.ts
  4. Mettez le ./node_modules/moment/moment.d.ts dans la section files de tsconfig.json

Vous devez également ajouter export as namespace moment; dans le fichier moment.d.ts .

l'équipe Moment aimerait tout PR qui résoudrait ce problème, mais resterait compatible avec TS 1.x.

Je n'ai pas encore trouvé de solution qui fonctionne du tout, mais quand je le ferai, je serai sûr d'ajouter un PR

Selon # 3663, le correctif temporaire pour le faire fonctionner sans aucun bundler ...

  • Copier moment.d.ts de node_modules/moment/ à node_modules/@types/moment

  • Remplacez export = moment; en moment.d.ts par

declare module "moment" {
    export = moment;
}
  • Renommer moment.d.ts en index.d.ts

Utilisez simplement moment et votre éditeur (dans mon cas vscode) et tsc ne devrait pas se plaindre

+1 s'il vous plaît corriger cela

@mtgibbs

@elSteeze

Oui, je les ajoute à mon tsconfig.json . Voici un exemple nettoyé :

{
  "compilerOptions": {
    "target": "ES5",
    "moduleResolution": "node",
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "compileOnSave": true,
  "exclude": [
    "node_modules",
    "./path/to/typings/**/*.d.ts",
    "./typings"
  ],
  "include": [
    "./path/to/typings/moment.custom.d.ts",
    "./path/to/src/**/*.ts"
  ]
}

@mtgibbs Hé merci mec ! Appréciez la réponse rapide. Je vais essayer ça.

@mtgibbs Désolé pour une autre question de type noob, après avoir mis en œuvre votre solution, j'ai commencé à recevoir des erreurs d'éditeur sur le mot-clé moment dans mon code ts...

'moment' refers to a UMD global, but the current file is a module. Consider adding an import instead

J'ai fait des recherches personnelles et tenté de mettre en œuvre une solution en réécrivant moment.custom.d.ts, mais malheureusement, cela n'a pas résolu mon problème.

Désolé, je n'essaie pas d'être l'un de ces développeurs embêtants qui obligent tout le monde à déboguer leur code, je suis un diplômé récent et je suis nouveau dans le travail avec des bibliothèques tierces dans un environnement Angular 2

Voici mon module mis à jour.custom.d.ts

declare var moment: any;
declare var module: NodeModule;
interface NodeModule {
    id: string;
}
import * as _moment from 'moment';
export as namespace moment;
export = _moment;

Aucun problème. Si vous utilisez Angular 2, vous devriez être sur 2.0+ TS. Je ne travaille pas dans Angular donc je ne suis pas sûr. N'oubliez pas de coller ce que vous pouvez de votre tsconfig.json et j'y jetterai un coup d'œil après être revenu sur un vrai ordinateur.

Sûr!

Il s'agit de l'intégralité de mon fichier tsconfig.es5.json dans le répertoire src de mon module angulaire 2 que je construis.
J'apprécie l'aide d'ailleurs

{
  "compilerOptions": {
    "declaration": true,
    "module": "es2015",
    "target": "es5",
    "baseUrl": ".",
    "stripInternal": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "outDir": "../build",
    "rootDir": ".",
    "lib": [
      "es2015",
      "dom"
    ],
    "skipLibCheck": true,
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "compileOnSave": true,
  "exclude": [
    "node_modules",
    "./typings/**/*.d.ts",
    "./typings"
  ],
  "include": [
    "./typings/moment.custom.d.ts",
    "./src/**/*.ts"
  ],
  "angularCompilerOptions": {
    "annotateForClosureCompiler": true,
    "strictMetadataEmit": true,
    "skipTemplateCodegen": true,
    "flatModuleOutFile": "new-version-library.js",
    "flatModuleId": "new-version-library"
  },
  "files": [
    "./index.ts"
  ]
}

Dans quelle version de TS compilez-vous ? Vous devriez juste pouvoir importer le moment en haut sans mon hack.

@mtgibbs J'utilise la v2.2, et c'est ce que je pensais. Malheureusement, cela ne fonctionne pas. J'en suis presque au point où j'écris ma propre version des fonctionnalités que nous prenons de momentjs, car je n'arrive pas à faire fonctionner cela.

@elSteeze

D'accord, je reviens ici. J'ai remarqué que vous avez dit que vous aviez fait un module.custom.d.ts , mais ensuite vous faites référence à mon moment.custom.d.ts dans votre tsconfig.json . Assurez-vous que vous avez créé moment.custom.d.ts et que vous l'avez ajouté à votre compilateur, rien de tout ce que vous aviez en plus pour le déclarer. Assurez-vous ensuite que vous le référencez en haut du fichier dans lequel vous souhaitez l'utiliser.

/// <reference path="path/to/your/moment.custom.d.ts" />

Cela devrait vous permettre de le référencer en tant que variable globale comme dans ma solution de contournement d'origine.

Super merci @mtgibbs ! J'apprécie vraiment l'aide.
J'ai modifié la structure de mes fichiers pour prendre en charge vos chemins. Ce sont donc des chemins corrects.
Bravo mon pote !

Cela fonctionne pour moi:

  • commentez // export = moment dans le fichier moment.d.ts officiel
  • ajouter node_modules/moment/moment.d.ts à tsconfig.json

Alternativement, copiez le moment.d.ts modifié dans un emplacement de votre choix et ajoutez-y le chemin dans votre tsconfig.json

Je pense que le principal problème est que lorsque vous utilisez explicitement "module":"none" dans tsconfig.json, vous ne pouvez avoir aucune importation ou exportation de niveau supérieur dans aucune bibliothèque (car vous utilisez alors des modules).

vous devez d'abord importer dans le composant en tant que
importer * comme moment à partir de "moment" ;

Ça a bien marché pour moi

vous devez d'abord importer dans le composant en tant que
importer * comme moment à partir de "moment" ;
Ça a bien marché pour moi

Si vous faites cela dans un fichier, la résolution de l'espace de noms est désactivée pour ces fichiers.

Pls les gars +1 pour résoudre ce problème

Pourquoi ne résolvez-vous pas ce problème ? Il est très important.

L'ajout de "module": "commonjs" au tsconfig.json corrigé pour moi

Mais je dois utiliser "module": "none" . Commonjs n'est pas une solution.

Si je comprends bien, cela sera résolu avec la fonctionnalité d'importation de types de TypeScript 2.9 , qui permettra des définitions de types import sans affecter le module / contexte ambiant.

J'utilise TS 3.0.1, est-ce maintenant résolu ? Cela ne fonctionne pas hors de la boîte au moins.

EDIT , avec TS 3.0.1, je pourrais faire ceci :

declare var moment: typeof import("moment");

Hourra!

Avec tsconfig

{
    "compilerOptions": {
        "module": "none"
        "moduleResolution": "node", 
        // ...
    }
}

TS 3.0.1 semble résoudre ce problème (et il est ouvert depuis plus d'un an et demi sans traction)

Salut rossipède,
Je suis confronté au même problème dans le projet angulaire-6. Selon vos commentaires, il est résolu dans TS 3.0.1 mais angular6 CLI ne prend pas en charge TypeScript version 3.0.1.

Pouvez-vous s'il vous plaît aider à résoudre ce problème?

Quelqu'un d'autre a-t-il également rencontré le package @types/moment npm qui n'est qu'un stub et vous dit d'utiliser le fichier fourni par le package moment normal ?

... Pourquoi moment doit-il procéder différemment par rapport à tous les autres packages ? C'est la raison pour laquelle ce problème existe, et des milliers d'heures ont été passées par les développeurs aux prises avec cela.

Bien sûr, la solution de @Ciantic fonctionne dans TS 3.0.1, mais je n'ai pas besoin d'utiliser quelque chose comme declare var moment: typeof import("moment"); pour les autres packages que j'utilise.

Il ne semble pas que Typescript 3.0.1 résolve ce problème, il semble que cela nous donne simplement une solution de contournement.

il semble que cela nous donne une solution de contournement.

Ouais, c'est exactement ça. Ce n'est pas une "correction" acceptable.

Cela ne fait qu'un jour et je viens de réaliser que la solution de contournement TS 3.0.1 n'importe que la fonction moment , pas l'espace de noms/les types. Donc, si vous voulez passer un objet moment dans une fonction, cela se produit :

image

Veuillez rouvrir ce problème, ou mieux : corriger le fichier .dts.

Pas une solution au problème d'origine, mais pour les personnes qui recherchent cela plus tard: spécifier ce qui suit dans tsconfig.json l'a corrigé (typescript 3.3.3 et moment 2.24.0)

{
  "compilerOptions": {
    "module": "commonjs"
  }
}

Je n'utilise plus moment beaucoup ces jours-ci, mais je suis heureux de rouvrir le problème s'il est toujours valable.

ERREUR dans src/app/services/get-list.service.ts(22,54) : erreur TS2304 : Impossible de trouver le nom '_'.

Quelle est la solution pour cela??

@nagipogu Aucune solution pour cela, ce problème est pour moment.js , veuillez ouvrir votre problème dans le référentiel Github de underscore.js .

Je rencontre ce problème avec la dernière version de moment avec la dernière version de TS. Quelqu'un a-t-il une solution de contournement réussie?

Ne fonctionnait toujours pas, la solution pour moi était de yarn add -W [email protected] .

Lorsque j'ai installé la dernière version de moment et regardé dans node_modules/moment/package.json, j'ai vu ceci : https://github.com/moment/moment/blob/develop/package.json#L29 - mais il n'y avait pas de répertoire existant node_modules/moment/ts3.1-typings , il n'est donc pas surprenant que TS ne puisse pas le trouver. Je pense qu'il peut y avoir un bug avec un script d'installation (ou un package) ou autre. Oui, nous avons "module": "esnext" dans tsconfig.json.

Pour moi, il a cassé avec 2.25.0 :

J'ai utilisé pnpm add [email protected] comme solution de contournement temporaire.

Pour moi, il a cassé avec 2.25.0 :

J'ai utilisé pnpm add [email protected] comme solution de contournement temporaire.

fonctionne bien, merci

Pour moi, il a cassé avec 2.25.0 :

J'ai utilisé pnpm add [email protected] comme solution de contournement temporaire.

Idem ici ajouté à : "dependencies" {"moment": "^2.24.0",
}... semble fonctionner merci.

La rétrogradation à 2.24.0 a également fonctionné pour moi. Ressemble à une régression dans 2.25.0.

2.25.3 résout-il vos problèmes ?

Il existe tellement de types de situations différentes dans lesquelles Moment.js est utilisé, sans parler de TS 1.x, TS 2.x, TS 3.x...
J'hésite à apporter des modifications qui cassent un groupe de ces utilisateurs.

Si vous pensez que la documentation peut être améliorée, veuillez la poster sur https://github.com/moment/momentjs.com/

2.25.3 résout-il vos problèmes ?

Oui.

Revenu à 2.24.0 lorsque 2.25.1 a échoué pour moi dans Angular 9. Avec 2.25.3, il est de nouveau sur la bonne voie.

OK super. Je vais fermer pour le moment.

Veuillez rouvrir (ou ouvrir un nouveau numéro) si vous avez toujours des inquiétudes.

Cette page vous a été utile?
0 / 5 - 0 notes