如何在Monaco中使用addExtraLib和外部类型定义

20

我知道如何在Monaco中使用addExtraLib来添加环境声明文件。但是不清楚如何将该函数与外部声明文件一起使用,以便编辑器中的TypeScript代码可以执行:

import * as External from "external" 
    
External.foo();

在摩纳哥的安装方面,这似乎行不通:

 // compiler options
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
    target: monaco.languages.typescript.ScriptTarget.ES2016,
    allowNonTsExtensions: true,
    moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
    module: monaco.languages.typescript.ModuleKind.CommonJS,
    noEmit: true,
    noLib: true,
    typeRoots: ["node_modules/@types"]
});

// extra libraries
monaco.languages.typescript.typescriptDefaults.addExtraLib(
    'export declare function foo():string;', 'node_modules/@types/external/index.d.ts');

monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: false,
    noSyntaxValidation: false
3个回答

21

经过一番试验,我找到了解决方案。基本上,文件必须使用具有明确文件URL的createModel加载。如果这样做,那么node_module/@types的相对文件路径有效。这是我的工作解决方案,可在游乐场中使用:

// compiler options
monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
    target: monaco.languages.typescript.ScriptTarget.ES2016,
    allowNonTsExtensions: true,
    moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
    module: monaco.languages.typescript.ModuleKind.CommonJS,
    noEmit: true,
    typeRoots: ["node_modules/@types"]
});

// extra libraries
monaco.languages.typescript.typescriptDefaults.addExtraLib(
    `export declare function next() : string`,
    'node_modules/@types/external/index.d.ts');

monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions({
    noSemanticValidation: false,
    noSyntaxValidation: false
})

var jsCode = `import * as x from "external"
    const tt : string = x.dnext();`;

monaco.editor.create(document.getElementById("container"), {
    model: monaco.editor.createModel(jsCode,"typescript",new monaco.Uri("file:///main.tsx")), 
});

我想添加lodash。我可以添加文件路径,但是在文件内容中要写什么?我完全不知道文件内容的事情。 - Himanshu Shekhar
@HimanshuShekhar 可能来晚了,但你可以在这里查看 https://microsoft.github.io/monaco-editor/playground.html#extending-language-services-configure-javascript-defaults。 - Vladimir Gromes

14

Joe的答案对我没起作用。通过在外部类型定义文件路径前面加上file:///,问题得到了解决。

以下是更新后的示例,供参考:playground

monaco.languages.typescript.typescriptDefaults.addExtraLib(
    'export declare function add(a: number, b: number): number',
    'file:///node_modules/@types/math/index.d.ts'
);

const model = monaco.editor.createModel(
    `import {add} from 'math';\nconst x = add(3, 5);\n`,
    'typescript',
    monaco.Uri.parse('file:///main.tsx')
);

monaco.editor.create(document.getElementById('container'), {model});

无需提供编译器选项和诊断选项。


7
截至2021年4月(monaco-editor@0.23.0),根据monaco-editor#2295monaco-editor#1839https://dev59.com/77zpa4cB1Zd3GeqPOZ_8#63349650提供的额外细节,我无法使用先前的解决方案。 我的用例需要从多个已有的NPM包中获取类型定义(不仅仅是文件的任意路径),这可能会影响解决方案。 总之,我需要做到以下几点:
  1. 将每个软件包中的所有.d.ts文件捆绑到单个文件中。 TypeScript 不容易实现,因此我使用了 dts-bundle-generator ,但还存在其他解决方案。
  2. 使用raw-loader或其他纯文本加载替代方法导入每个软件包的.d.ts内容。
  3. 对于每个模块的源,使用addExtraLib进行调用,向源代码中添加显式的declare module 'module-name'
下面是完整的示例:
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';

import source1 from '!!raw-loader!./types/package-one.d.ts';
import source2 from '!!raw-loader!./types/package-two.d.ts'

monaco.languages.typescript.typescriptDefaults.addExtraLib(
  `declare module '@my-project/package-one' { ${source1} }`,
  'file:///node_modules/@my-project/package-one/index.d.ts' // irrelevant?
);
monaco.languages.typescript.typescriptDefaults.addExtraLib(
  `declare module '@my-project/package-two' { ${source2} }`,
  'file:///node_modules/@my-project/package-two/index.d.ts' // irrelevant?
);

monaco.editor.create(document.getElementById('root'), {
    value: `
import { Foo } from '@my-project/package-one';

const foo = new Foo();
`,
    language: 'typescript',
    theme: 'vs-dark'
});

尝试添加 esModule=false 选项,以避免声明模块:const typings = require("!!raw-loader?esModule=false!./debugger-runtime.d.ts"); 是的,标记为“不相关”的行确实是无关紧要的。 - Mike Lischke
我没有捆绑我的 typings 文件。我在我的 React 应用程序中添加了多个文件,每个文件都使用从上面的 require 调用加载它们的方式进行加载。 - Mike Lischke
我的项目中引用的每个包都包含数十个 typings 文件。如果没有一个真正的 package.json 指向 types 根目录,没有使用 ES 模块导入,也没有任何关于包的实际名称的引用,我不确定 Monaco 如何能够解析包名称的导入? - Don McCurdy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接