Skip to content

Instantly share code, notes, and snippets.

@robertrossmann
Last active November 25, 2021 15:04
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robertrossmann/0fb8b22341dcd83f37522ee654b0fb68 to your computer and use it in GitHub Desktop.
Save robertrossmann/0fb8b22341dcd83f37522ee654b0fb68 to your computer and use it in GitHub Desktop.
TypeScript - Intellisense support for ES modules (_.mjs_ files)

TypeScript - Intellisense support for ES modules

This patch, based on commit https://github.com/Microsoft/TypeScript/commit/beebda3574be7f9a51f33ac24ab117f696ca9055, will add Intellisense support to projects which utilise the .mjs file extension for JavaScript modules.

⚠️ Warning

  • I have only used this from within tsserver. I did not attempt to use the tsc tool to do any kind of compilation of .mjs files.
  • This patch causes tsserver to treat all .mjs files as regular JavaScript files. This might be semantically wrong since these files have different semantics.

What works

  • Import statements which refer to .mjs modules without extension
  • Intellisense for things declared in .mjs files

Usage

  • Clone the TypeScript repository
  • Download this patch file
  • Apply the patch on top of master (if it does not apply, checkout the base commit mentioned above and apply it on top of that instead): `cat tsserver-intellisense.patch | git am
  • Compile the TypeScript binaries: npm install && npx jake local
  • Point your IDE/other tool to TypeScript/built/local/tsserver.js to use the locally-built TypeScript server
  • Profit 🎉
From 6429aacce7611a236c559083ccd563259cbe64ca Mon Sep 17 00:00:00 2001
From: Robert Rossmann <rr.rossmann@me.com>
Date: Mon, 31 Dec 2018 18:29:45 +0100
Subject: [PATCH] Add intellisense support for .mjs files via tsserver
---
src/compiler/moduleNameResolver.ts | 2 +-
src/compiler/moduleSpecifiers.ts | 1 +
src/compiler/program.ts | 1 +
src/compiler/types.ts | 1 +
src/compiler/utilities.ts | 7 ++++---
src/services/stringCompletions.ts | 1 +
src/services/types.ts | 1 +
7 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts
index b8aa9fa2..7c6f9de6 100644
--- a/src/compiler/moduleNameResolver.ts
+++ b/src/compiler/moduleNameResolver.ts
@@ -1071,7 +1071,7 @@ namespace ts {
case Extensions.TypeScript:
return tryExtension(Extension.Ts) || tryExtension(Extension.Tsx) || tryExtension(Extension.Dts);
case Extensions.JavaScript:
- return tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
+ return tryExtension(Extension.Mjs) || tryExtension(Extension.Js) || tryExtension(Extension.Jsx);
case Extensions.TSConfig:
case Extensions.Json:
return tryExtension(Extension.Json);
diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts
index f5bac45f..14ac7bbe 100644
--- a/src/compiler/moduleSpecifiers.ts
+++ b/src/compiler/moduleSpecifiers.ts
@@ -433,6 +433,7 @@ namespace ts.moduleSpecifiers {
return Extension.Js;
case Extension.Tsx:
return options.jsx === JsxEmit.Preserve ? Extension.Jsx : Extension.Js;
+ case Extension.Mjs:
case Extension.Js:
case Extension.Jsx:
case Extension.Json:
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 080b17b8..3f0a3111 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -3152,6 +3152,7 @@ namespace ts {
return needJsx();
case Extension.Jsx:
return needJsx() || needAllowJs();
+ case Extension.Mjs:
case Extension.Js:
return needAllowJs();
case Extension.Json:
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index 6e2e4805..5ed67ae5 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -4962,6 +4962,7 @@ namespace ts {
Tsx = ".tsx",
Dts = ".d.ts",
Js = ".js",
+ Mjs = ".mjs",
Jsx = ".jsx",
Json = ".json"
}
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 23c92216..1cceb159 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -8124,6 +8124,7 @@ namespace ts {
export function getScriptKindFromFileName(fileName: string): ScriptKind {
const ext = fileName.substr(fileName.lastIndexOf("."));
switch (ext.toLowerCase()) {
+ case Extension.Mjs:
case Extension.Js:
return ScriptKind.JS;
case Extension.Jsx:
@@ -8146,8 +8147,8 @@ namespace ts {
export const supportedTSExtensionsWithJson: ReadonlyArray<Extension> = [Extension.Ts, Extension.Tsx, Extension.Dts, Extension.Json];
/** Must have ".d.ts" first because if ".ts" goes first, that will be detected as the extension instead of ".d.ts". */
export const supportedTSExtensionsForExtractExtension: ReadonlyArray<Extension> = [Extension.Dts, Extension.Ts, Extension.Tsx];
- export const supportedJSExtensions: ReadonlyArray<Extension> = [Extension.Js, Extension.Jsx];
- export const supportedJSAndJsonExtensions: ReadonlyArray<Extension> = [Extension.Js, Extension.Jsx, Extension.Json];
+ export const supportedJSExtensions: ReadonlyArray<Extension> = [Extension.Mjs, Extension.Js, Extension.Jsx];
+ export const supportedJSAndJsonExtensions: ReadonlyArray<Extension> = [Extension.Mjs, Extension.Js, Extension.Jsx, Extension.Json];
const allSupportedExtensions: ReadonlyArray<Extension> = [...supportedTSExtensions, ...supportedJSExtensions];
const allSupportedExtensionsWithJson: ReadonlyArray<Extension> = [...supportedTSExtensions, ...supportedJSExtensions, Extension.Json];
@@ -8255,7 +8256,7 @@ namespace ts {
}
}
- const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Js, Extension.Tsx, Extension.Jsx, Extension.Json];
+ const extensionsToRemove = [Extension.Dts, Extension.Ts, Extension.Mjs, Extension.Js, Extension.Tsx, Extension.Jsx, Extension.Json];
export function removeFileExtension(path: string): string {
for (const ext of extensionsToRemove) {
const extensionless = tryRemoveExtension(path, ext);
diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts
index 9548397a..d449b66c 100644
--- a/src/services/stringCompletions.ts
+++ b/src/services/stringCompletions.ts
@@ -66,6 +66,7 @@ namespace ts.Completions.StringCompletions {
function kindModifiersFromExtension(extension: Extension | undefined): ScriptElementKindModifier {
switch (extension) {
case Extension.Dts: return ScriptElementKindModifier.dtsModifier;
+ case Extension.Mjs: return ScriptElementKindModifier.mjsModifier;
case Extension.Js: return ScriptElementKindModifier.jsModifier;
case Extension.Json: return ScriptElementKindModifier.jsonModifier;
case Extension.Jsx: return ScriptElementKindModifier.jsxModifier;
diff --git a/src/services/types.ts b/src/services/types.ts
index 5100a999..6582dfd4 100644
--- a/src/services/types.ts
+++ b/src/services/types.ts
@@ -1138,6 +1138,7 @@ namespace ts {
dtsModifier = ".d.ts",
tsModifier = ".ts",
tsxModifier = ".tsx",
+ mjsModifier = ".mjs",
jsModifier = ".js",
jsxModifier = ".jsx",
jsonModifier = ".json",
--
2.20.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment