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