Typescript: noImplicitAny on single file

Created on 27 May 2016  Â·  8Comments  Â·  Source: microsoft/TypeScript

Is it possible to enable noImplicitAny for a single file? This would help us as we are gradually migrating and, when a file is complete, we can begin to use noImplicitAny.

Suggestion Won't Fix

Most helpful comment

@basarat we're incrementally adopting TypeScript - a use-case I imagine is shared by many! In this case opt-in is preferable. We start off files as noImplicitAny and would like to move them out of that state one by one.

All 8 comments

Is it possible to enable noImplicitAny for a single file

Individual file compiler flags aren't supported at the moment. Figuring out how different files compiled with different flags interact would be a problem.

You probably want something like _disable certain errors_ per file. There is an issue request for that somewhere (I'm on a train) :rose:

You could patch the existing CompilerHost or create your own that suppresses arbitrary diagnostics from arbitrary files, but I don't believe there's anything in-built.

@basarat we're incrementally adopting TypeScript - a use-case I imagine is shared by many! In this case opt-in is preferable. We start off files as noImplicitAny and would like to move them out of that state one by one.

The issue here is that types could leak into the compilation context. there is no grantee that an implicit any has a local effect. and thus there are no guarantees about refactoring, find all refes, etc..

in general if it is a point-in-time, e.g. migrating to TS or from implicit anys to noImplicitAny, etc, i would recommend doing it all in one shot, or splitting the compilation into two chunks, each with a different flag, and moving files/modules from one chunk to the other.

You can see a similar response for --strictNullChecks in https://github.com/Microsoft/TypeScript/issues/8405#issuecomment-219782002.

i would recommend doing it all in one shot, or splitting the compilation into two chunks, each with a different flag, and moving files/modules from one chunk to the other.

This is really difficult for a large code base sadly :-( We did think about maintaining two graphs, one strict and one unstrict, however this means modules can't be shared between the two which makes it hard.

I might have a crack at wrapping tsc and just filter out implicit any errors for a given whitelist.

<OliverJAsh> I want to write a wrapper around tsc which allows me to filter out errors for certain files, e.g. I only want `noImplicitAny` to apply for `strict.ts,` not `unstrict.ts`. Any tips how I might go about this? My instinct is to try and parse the error output from tsc (split by new line??) and filter out that way
<OliverJAsh> Should I be using some Node API instead to receive parsed errors instead of trying to parse them myself?

Does https://github.com/Microsoft/TypeScript/issues/8855#issuecomment-222880027 not work for you?

Edit: i.e. ts.createCompilerHost() + ts.createProgram(host) + program.get*Diagnostics() - each Diagnostic has a filename so you can filter on that when emitting them.

@Arnavion

Great, that works! See below. Now I am wondering how I could wrap/configure IDE plugins so they give they filter errors in the same way. Any ideas on how I might do that? Seems ambitious…

// main.ts
// ts-node --project main.ts
// https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API

import ts = require('typescript');

const options: ts.CompilerOptions = {
    // TODO: Consume project config somehow
    // project: `server/tsconfig.json`,
    outDir: 'tmp',
    // Strict only
    noImplicitAny: true
};
const program = ts.createProgram([`main.ts`]);
const emitResult = program.emit();

const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);

// We only care about no implicit any errors on "strict files"
const strictFiles = [
    'strict-file.ts'
].map(str => `${__dirname}/${str}`)

const errors = allDiagnostics
    .filter(diagnostic => {
        const isStrictFile = strictFiles.indexOf(diagnostic.file.fileName) !== -1;
        const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
        const isImplicitAnyError = / implicitly has an 'any(\[\])?' type.$/.test(message);
                return isStrictFile ? true : !isImplicitAnyError;
    });

const errorStr = errors
    .map(diagnostic => {
        const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
        const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
        return `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
    })
    .join('\n');

if (errorStr) {
    process.stderr.write(errorStr);
    process.stderr.write('\n\r');
    process.exit(1);
}

How about doing it on a per-type basis See #18540. It avoids the need to create two graphs, and now the check becomes a property of the type. A potential suggestion is to use comments to indicate strictness.

/* @strict */
interface MyType {
....
}

At any point during compilation, the use of type implicitly converts to any or vice versa, throw a compiler error.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bgrieder picture bgrieder  Â·  3Comments

DanielRosenwasser picture DanielRosenwasser  Â·  3Comments

wmaurer picture wmaurer  Â·  3Comments

CyrusNajmabadi picture CyrusNajmabadi  Â·  3Comments

blendsdk picture blendsdk  Â·  3Comments