Skip to content

Commit cda741d

Browse files
committed
Introduce --strict compiler option
1 parent 5abb8f3 commit cda741d

File tree

7 files changed

+40
-27
lines changed

7 files changed

+40
-27
lines changed

src/compiler/binder.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ namespace ts {
182182
return bindSourceFile;
183183

184184
function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean {
185-
if (opts.alwaysStrict && !isDeclarationFile(file)) {
185+
if ((opts.alwaysStrict === undefined ? opts.strict : opts.alwaysStrict) && !isDeclarationFile(file)) {
186186
// bind in strict mode source files with alwaysStrict option
187187
return true;
188188
}

src/compiler/checker.ts

+21-19
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ namespace ts {
5656
const modulekind = getEmitModuleKind(compilerOptions);
5757
const noUnusedIdentifiers = !!compilerOptions.noUnusedLocals || !!compilerOptions.noUnusedParameters;
5858
const allowSyntheticDefaultImports = typeof compilerOptions.allowSyntheticDefaultImports !== "undefined" ? compilerOptions.allowSyntheticDefaultImports : modulekind === ModuleKind.System;
59-
const strictNullChecks = compilerOptions.strictNullChecks;
59+
const strictNullChecks = compilerOptions.strictNullChecks === undefined ? compilerOptions.strict : compilerOptions.strictNullChecks;
60+
const noImplicitAny = compilerOptions.noImplicitAny === undefined ? compilerOptions.strict : compilerOptions.noImplicitAny;
61+
const noImplicitThis = compilerOptions.noImplicitThis === undefined ? compilerOptions.strict : compilerOptions.noImplicitThis;
6062

6163
const emitResolver = createResolver();
6264

@@ -1564,7 +1566,7 @@ namespace ts {
15641566
error(errorNode, diag, moduleReference, resolvedModule.resolvedFileName);
15651567
return undefined;
15661568
}
1567-
else if (compilerOptions.noImplicitAny && moduleNotFoundError) {
1569+
else if (noImplicitAny && moduleNotFoundError) {
15681570
error(errorNode,
15691571
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type,
15701572
moduleReference,
@@ -3407,7 +3409,7 @@ namespace ts {
34073409
return addOptionality(declaredType, /*optional*/ declaration.questionToken && includeOptionality);
34083410
}
34093411

3410-
if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
3412+
if ((noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
34113413
declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) &&
34123414
!(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !isInAmbientContext(declaration)) {
34133415
// If --noImplicitAny is on or the declaration is in a Javascript file,
@@ -3509,7 +3511,7 @@ namespace ts {
35093511
if (isBindingPattern(element.name)) {
35103512
return getTypeFromBindingPattern(<BindingPattern>element.name, includePatternInType, reportErrors);
35113513
}
3512-
if (reportErrors && compilerOptions.noImplicitAny && !declarationBelongsToPrivateAmbientMember(element)) {
3514+
if (reportErrors && noImplicitAny && !declarationBelongsToPrivateAmbientMember(element)) {
35133515
reportImplicitAnyError(element, anyType);
35143516
}
35153517
return anyType;
@@ -3607,7 +3609,7 @@ namespace ts {
36073609
type = declaration.dotDotDotToken ? anyArrayType : anyType;
36083610

36093611
// Report implicit any errors unless this is a private property within an ambient declaration
3610-
if (reportErrors && compilerOptions.noImplicitAny) {
3612+
if (reportErrors && noImplicitAny) {
36113613
if (!declarationBelongsToPrivateAmbientMember(declaration)) {
36123614
reportImplicitAnyError(declaration, type);
36133615
}
@@ -3726,7 +3728,7 @@ namespace ts {
37263728
}
37273729
// Otherwise, fall back to 'any'.
37283730
else {
3729-
if (compilerOptions.noImplicitAny) {
3731+
if (noImplicitAny) {
37303732
if (setter) {
37313733
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol));
37323734
}
@@ -3741,7 +3743,7 @@ namespace ts {
37413743
}
37423744
if (!popTypeResolution()) {
37433745
type = anyType;
3744-
if (compilerOptions.noImplicitAny) {
3746+
if (noImplicitAny) {
37453747
const getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
37463748
error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol));
37473749
}
@@ -3824,7 +3826,7 @@ namespace ts {
38243826
return unknownType;
38253827
}
38263828
// Otherwise variable has initializer that circularly references the variable itself
3827-
if (compilerOptions.noImplicitAny) {
3829+
if (noImplicitAny) {
38283830
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer,
38293831
symbolToString(symbol));
38303832
}
@@ -5585,7 +5587,7 @@ namespace ts {
55855587
}
55865588
if (!popTypeResolution()) {
55875589
type = anyType;
5588-
if (compilerOptions.noImplicitAny) {
5590+
if (noImplicitAny) {
55895591
const declaration = <Declaration>signature.declaration;
55905592
if (declaration.name) {
55915593
error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, declarationNameToString(declaration.name));
@@ -6540,7 +6542,7 @@ namespace ts {
65406542
return indexInfo.type;
65416543
}
65426544
if (accessExpression && !isConstEnumObjectType(objectType)) {
6543-
if (compilerOptions.noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
6545+
if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors) {
65446546
if (getIndexTypeOfType(objectType, IndexKind.Number)) {
65456547
error(accessExpression.argumentExpression, Diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number);
65466548
}
@@ -9126,7 +9128,7 @@ namespace ts {
91269128
}
91279129

91289130
function reportErrorsFromWidening(declaration: Declaration, type: Type) {
9129-
if (produceDiagnostics && compilerOptions.noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
9131+
if (produceDiagnostics && noImplicitAny && type.flags & TypeFlags.ContainsWideningType) {
91309132
// Report implicit any error within type if possible, otherwise report error on declaration
91319133
if (!reportWideningErrorsInType(type)) {
91329134
reportImplicitAnyError(declaration, type);
@@ -11007,7 +11009,7 @@ namespace ts {
1100711009
// control flow based type does include undefined.
1100811010
if (type === autoType || type === autoArrayType) {
1100911011
if (flowType === autoType || flowType === autoArrayType) {
11010-
if (compilerOptions.noImplicitAny) {
11012+
if (noImplicitAny) {
1101111013
error(declaration.name, Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType));
1101211014
error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType));
1101311015
}
@@ -11277,7 +11279,7 @@ namespace ts {
1127711279
}
1127811280
}
1127911281

11280-
if (compilerOptions.noImplicitThis) {
11282+
if (noImplicitThis) {
1128111283
// With noImplicitThis, functions may not reference 'this' if it has type 'any'
1128211284
error(node, Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation);
1128311285
}
@@ -12531,7 +12533,7 @@ namespace ts {
1253112533
return links.resolvedSymbol = unknownSymbol;
1253212534
}
1253312535
else {
12534-
if (compilerOptions.noImplicitAny) {
12536+
if (noImplicitAny) {
1253512537
error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements);
1253612538
}
1253712539
return links.resolvedSymbol = unknownSymbol;
@@ -12919,7 +12921,7 @@ namespace ts {
1291912921
}
1292012922

1292112923
if (jsxElementType === undefined) {
12922-
if (compilerOptions.noImplicitAny) {
12924+
if (noImplicitAny) {
1292312925
error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist);
1292412926
}
1292512927
}
@@ -14742,7 +14744,7 @@ namespace ts {
1474214744
if (funcSymbol && funcSymbol.members && funcSymbol.flags & SymbolFlags.Function) {
1474314745
return getInferredClassType(funcSymbol);
1474414746
}
14745-
else if (compilerOptions.noImplicitAny) {
14747+
else if (noImplicitAny) {
1474614748
error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type);
1474714749
}
1474814750
return anyType;
@@ -15002,7 +15004,7 @@ namespace ts {
1500215004
const iterableIteratorAny = functionFlags & FunctionFlags.Async
1500315005
? createAsyncIterableIteratorType(anyType) // AsyncGenerator function
1500415006
: createIterableIteratorType(anyType); // Generator function
15005-
if (compilerOptions.noImplicitAny) {
15007+
if (noImplicitAny) {
1500615008
error(func.asteriskToken,
1500715009
Diagnostics.Generator_implicitly_has_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type, typeToString(iterableIteratorAny));
1500815010
}
@@ -16544,7 +16546,7 @@ namespace ts {
1654416546

1654516547
if (produceDiagnostics) {
1654616548
checkCollisionWithArgumentsInGeneratedCode(node);
16547-
if (compilerOptions.noImplicitAny && !node.type) {
16549+
if (noImplicitAny && !node.type) {
1654816550
switch (node.kind) {
1654916551
case SyntaxKind.ConstructSignature:
1655016552
error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type);
@@ -17856,7 +17858,7 @@ namespace ts {
1785617858
if (produceDiagnostics && !node.type) {
1785717859
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
1785817860
// in an ambient context
17859-
if (compilerOptions.noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) {
17861+
if (noImplicitAny && nodeIsMissing(node.body) && !isPrivateWithinAmbient(node)) {
1786017862
reportImplicitAnyError(node, anyType);
1786117863
}
1786217864

src/compiler/commandLineParser.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,11 @@ namespace ts {
467467
type: "boolean",
468468
description: Diagnostics.Parse_in_strict_mode_and_emit_use_strict_for_each_source_file
469469
},
470+
{
471+
name: "strict",
472+
type: "boolean",
473+
description: Diagnostics.Enable_all_strict_type_checks
474+
},
470475
{
471476
// A list of plugins to load in the language service
472477
name: "plugins",
@@ -520,7 +525,7 @@ namespace ts {
520525
export const defaultInitCompilerOptions: CompilerOptions = {
521526
module: ModuleKind.CommonJS,
522527
target: ScriptTarget.ES5,
523-
noImplicitAny: false,
528+
strict: false,
524529
sourceMap: false,
525530
};
526531

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -3045,6 +3045,10 @@
30453045
"category": "Message",
30463046
"code": 6149
30473047
},
3048+
"Enable all strict type checks.": {
3049+
"category": "Message",
3050+
"code": 6150
3051+
},
30483052
"Variable '{0}' implicitly has an '{1}' type.": {
30493053
"category": "Error",
30503054
"code": 7005

src/compiler/program.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1630,7 +1630,7 @@ namespace ts {
16301630
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
16311631
}
16321632

1633-
if (options.noImplicitUseStrict && options.alwaysStrict) {
1633+
if (options.noImplicitUseStrict && (options.alwaysStrict === undefined ? options.strict : options.alwaysStrict)) {
16341634
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"));
16351635
}
16361636

src/compiler/transformers/ts.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,8 @@ namespace ts {
472472
}
473473

474474
function visitSourceFile(node: SourceFile) {
475-
const alwaysStrict = compilerOptions.alwaysStrict && !(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
475+
const alwaysStrict = (compilerOptions.alwaysStrict === undefined ? compilerOptions.strict : compilerOptions.alwaysStrict) &&
476+
!(isExternalModule(node) && moduleKind === ModuleKind.ES2015);
476477
return updateSourceFileNode(
477478
node,
478479
visitLexicalEnvironment(node.statements, sourceElementVisitor, context, /*start*/ 0, alwaysStrict));

src/compiler/types.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -3308,7 +3308,7 @@
33083308
allowSyntheticDefaultImports?: boolean;
33093309
allowUnreachableCode?: boolean;
33103310
allowUnusedLabels?: boolean;
3311-
alwaysStrict?: boolean;
3311+
alwaysStrict?: boolean; // Always combine with strict property
33123312
baseUrl?: string;
33133313
charset?: string;
33143314
/* @internal */ configFilePath?: string;
@@ -3344,9 +3344,9 @@
33443344
noEmitOnError?: boolean;
33453345
noErrorTruncation?: boolean;
33463346
noFallthroughCasesInSwitch?: boolean;
3347-
noImplicitAny?: boolean;
3347+
noImplicitAny?: boolean; // Always combine with strict property
33483348
noImplicitReturns?: boolean;
3349-
noImplicitThis?: boolean;
3349+
noImplicitThis?: boolean; // Always combine with strict property
33503350
noUnusedLocals?: boolean;
33513351
noUnusedParameters?: boolean;
33523352
noImplicitUseStrict?: boolean;
@@ -3369,7 +3369,8 @@
33693369
skipDefaultLibCheck?: boolean;
33703370
sourceMap?: boolean;
33713371
sourceRoot?: string;
3372-
strictNullChecks?: boolean;
3372+
strict?: boolean;
3373+
strictNullChecks?: boolean; // Always combine with strict property
33733374
/* @internal */ stripInternal?: boolean;
33743375
suppressExcessPropertyErrors?: boolean;
33753376
suppressImplicitAnyIndexErrors?: boolean;

0 commit comments

Comments
 (0)