Created
May 11, 2021 12:37
-
-
Save chriscasola/d34000558dd006ae95df3efade36616c to your computer and use it in GitHub Desktop.
Type-check typescript in vue files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as path from 'path'; | |
import * as ts from 'typescript'; | |
import * as vtc from 'vue-template-compiler'; | |
function compile(fileNames: string[], options: ts.CompilerOptions): void { | |
const baseHost = ts.createCompilerHost(options); | |
const host: ts.CompilerHost = { | |
...baseHost, | |
resolveModuleNames( | |
moduleNames, | |
containingFile, | |
reusedNames, | |
redirectedReferences, | |
options | |
) { | |
const resolvedModules: (ts.ResolvedModule | undefined)[] = []; | |
for (let moduleName of moduleNames) { | |
// try to use standard resolution | |
let result = ts.resolveModuleName( | |
moduleName, | |
containingFile, | |
options, | |
baseHost | |
); | |
if (result.resolvedModule) { | |
resolvedModules.push(result.resolvedModule); | |
} else if (moduleName.endsWith('.vue') || moduleName.endsWith('css')) { | |
// use our own resolution for vue and css files | |
try { | |
const nodeModule = require.resolve(moduleName, { | |
paths: [path.dirname(containingFile)], | |
}); | |
resolvedModules.push({ | |
resolvedFileName: nodeModule + '.ts', | |
isExternalLibraryImport: | |
nodeModule.indexOf('/node_modules/') > -1, | |
}); | |
} catch { | |
resolvedModules.push(undefined); | |
} | |
} else { | |
resolvedModules.push(undefined); | |
} | |
} | |
return resolvedModules; | |
}, | |
getSourceFile(fileName, languageVersion, ...args) { | |
if (fileName.endsWith('css.ts')) { | |
return ts.createSourceFile(fileName, '', languageVersion); | |
} else if (fileName.endsWith('.vue.ts')) { | |
const actualPath = fileName.slice(0, -3); | |
const sourceText = ts.sys.readFile(actualPath); | |
if (sourceText === undefined) { | |
return undefined; | |
} | |
const descriptor = vtc.parseComponent(sourceText); | |
if (descriptor.script && descriptor.script.content) { | |
const scriptKind = | |
descriptor.script.lang?.toLowerCase() === 'ts' | |
? ts.ScriptKind.TS | |
: ts.ScriptKind.JS; | |
return ts.createSourceFile( | |
actualPath, | |
descriptor.script.content, | |
languageVersion, | |
undefined, | |
scriptKind | |
); | |
} else { | |
return ts.createSourceFile( | |
actualPath, | |
'export default {}', | |
languageVersion | |
); | |
} | |
} else { | |
return baseHost.getSourceFile(fileName, languageVersion, ...args); | |
} | |
}, | |
}; | |
const program = ts.createProgram(fileNames, options, host); | |
const emitResult = program.emit(); | |
let allDiagnostics = ts | |
.getPreEmitDiagnostics(program) | |
.concat(emitResult.diagnostics); | |
console.log( | |
ts.formatDiagnosticsWithColorAndContext(allDiagnostics, baseHost) | |
); | |
const exitCode = allDiagnostics.length > 0 ? 1 : 0; | |
process.exit(exitCode); | |
} | |
const configPath = ts.findConfigFile(process.cwd(), ts.sys.fileExists); | |
if (!configPath) { | |
console.error('No .tsconfig file found'); | |
process.exit(1); | |
} | |
const config = ts.readConfigFile(configPath, ts.sys.readFile); | |
compile([path.join(process.cwd(), '.arrow/main.ts')], { | |
...(config as any).compilerOptions, | |
noEmit: true, | |
rootDir: process.cwd(), | |
skipLibCheck: true, | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment