我有一些JavaScript模块存储为字符串,它们由Quick.js评估。
下面是一个例子:
const logic = `
export function foobar() { return true; }
`;
我想用TypeScript检查存储在logic
常量中的代码,但我找不到任何东西,我发现的唯一解决方案是围绕运行Node.js脚本,复制新文件中的代码,然后在它们上运行TS。
我想要一个在我的IDE中自动工作的解决方案。
我最终编写了一个自定义ESLint插件,它将检查任何字符串字面值或模板字面值,如果前缀为/*javascript*/
,例如:
export const foo = /*javascript*/ `
/**
* @returns {boolean}
*/
export function bar() { return 'string'; }
`;
这与es6-string-javascript
(zjcompt.es6-string-javascript
) VS Code扩展配合得很好,这将注意语法高亮显示JavaScript代码。
插件如下,你可以使用eslint-local-rules
ESLint插件:
const { ESLintUtils } = require('@typescript-eslint/utils');
const ts = require('typescript');
const fs = require('fs');
const path = require('path');
const os = require('os');
const checkJsInStringRule = ESLintUtils.RuleCreator((name) => name)({
meta: {
type: 'problem',
docs: {
description: 'Check JavaScript code stored in strings and template literals',
category: 'Possible Errors',
recommended: false,
},
schema: [],
messages: {
jsInStringError: 'Error in JavaScript code inside string or template literal: {{error}}',
},
},
defaultOptions: [],
create(context) {
function hasJavascriptComment(node) {
const sourceCode = context.getSourceCode();
const commentsBefore = sourceCode.getCommentsBefore(node);
return (
commentsBefore.length > 0 &&
commentsBefore.some((comment) => comment.value.trim() === 'javascript')
);
}
function checkCode(code, node) {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'eslint-'));
const tempFile = path.join(tempDir, 'temp.js');
fs.writeFileSync(tempFile, code);
const program = ts.createProgram([tempFile], {
allowJs: true,
checkJs: true,
noEmit: true,
});
const sourceFile = program.getSourceFile(tempFile);
const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
fs.rmSync(tempDir, { recursive: true });
if (diagnostics) {
diagnostics.forEach((diagnostic) => {
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, 'n');
context.report({
node,
messageId: 'jsInStringError',
data: {
error: message,
},
});
});
}
}
return {
Literal(node) {
if (typeof node.value !== 'string') {
return;
}
if (!hasJavascriptComment(node)) {
return;
}
const code = node.value.trim();
checkCode(code, node);
},
TemplateLiteral(node) {
if (!hasJavascriptComment(node)) {
return;
}
const code = node.quasis.map((quasi) => quasi.value.raw).join('');
checkCode(code, node);
},
};
},
});
module.exports = {
'check-js-in-string': checkJsInStringRule,
};
这将使TypeScript对代码进行类型检查,并通过ESLint报告任何错误。