Как использовать addExtraLib в Монако с определением внешнего типа

Я вижу, как использовать 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 ответа

Решение

Поиграв немного, я нашел решение. По сути, файл должен быть загружен с помощью createModel с явным URL файла. Если вы сделаете это, то относительный путь к файлу для 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")), 
});

Ответ Джо у меня не сработал, исправлено путем добавления префикса пути к файлу определения внешнего типа с помощью file:///

Вот обновленный пример для детской площадки:

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});

Нет необходимости указывать параметры компилятора и параметры диагностики.

По состоянию на апрель 2021 г. ( monaco-editor@0.23.0), Мне не удалось заставить работать ни одно из предыдущих решений без некоторых дополнительных деталей на основе monaco-editor#2295, monaco-editor#1839 и /questions/53588093/kak-zagruzit-opredelenie-tipa-modulya-npm-v-monako-s-pomoschyu-webpack-i-otreagi/53588104#53588104. Мой вариант использования требовал предоставления определений типов из нескольких существующих пакетов NPM (а не только произвольных путей к файлам), и это могло повлиять на решение. Подводя итог, мне нужно было:

  1. Объедините все файлы из каждого пакета в один файл. TypeScript не упрощает эту задачу , поэтому вместо этого я использовал dts-bundle-generator, но существуют и другие решения.
  2. Импортируйте .d.tsконтент для каждого пакета с использованием raw-loader или других альтернатив загрузки с открытым текстом.
  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'
});
Другие вопросы по тегам