Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New --strictAny mode #24423

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ namespace ts {
const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks");
const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization");
const strictAny = getStrictOptionValue(compilerOptions, "strictAny");
const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
const keyofStringsOnly = !!compilerOptions.keyofStringsOnly;
Expand Down Expand Up @@ -7494,7 +7495,8 @@ namespace ts {
if (signature.hasRestParameter) {
const type = getTypeOfSymbol(last(signature.parameters));
if (getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType) {
return (<TypeReference>type).typeArguments![0];
const t = (<TypeReference>type).typeArguments![0];
return strictAny && t.flags & TypeFlags.Any ? unknownType : t;
}
}
return anyType;
Expand Down Expand Up @@ -8579,16 +8581,19 @@ namespace ts {
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
// for intersections of types with signatures can be deterministic.
function getIntersectionType(types: Type[], aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
if (types.length === 0) {
return emptyObjectType;
}
const typeSet: Type[] = [];
const includes = addTypesToIntersection(typeSet, 0, types);
if (includes & TypeFlags.Never) {
return neverType;
}
if (includes & TypeFlags.Any) {
return includes & TypeFlags.Wildcard ? wildcardType : anyType;
if (includes & TypeFlags.Wildcard) {
return wildcardType;
}
if (!strictAny && includes & TypeFlags.Any) {
return anyType;
}
if (!strictNullChecks && includes & TypeFlags.Nullable) {
return includes & TypeFlags.Undefined ? undefinedType : nullType;
}
if (includes & TypeFlags.String && includes & TypeFlags.StringLiteral ||
includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral ||
Expand All @@ -8598,6 +8603,9 @@ namespace ts {
if (includes & TypeFlags.EmptyObject && !(includes & TypeFlags.Object)) {
typeSet.push(emptyObjectType);
}
if (typeSet.length === 0) {
return anyType;
}
if (typeSet.length === 1) {
return typeSet[0];
}
Expand Down Expand Up @@ -10293,7 +10301,7 @@ namespace ts {
if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true;
if (s & TypeFlags.UniqueESSymbol || t & TypeFlags.UniqueESSymbol) return false;
if (relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) {
if (s & TypeFlags.Any) return true;
if (s & TypeFlags.Any && (!strictAny || source === unknownType || t & TypeFlags.Object && isEmptyObjectType(target))) return true;
// Type number or any numeric literal type is assignable to any numeric enum type or any
// numeric enum literal type. This rule exists for backwards compatibility reasons because
// bit-flag enum types sometimes look like literal enum types with numeric literal values.
Expand Down Expand Up @@ -20023,7 +20031,7 @@ namespace ts {
if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbolLike))) {
error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
}
if (!isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) {
if (!(rightType.flags & TypeFlags.Any || isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive))) {
error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
}
return booleanType;
Expand Down Expand Up @@ -23498,7 +23506,7 @@ namespace ts {

// unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
// in this case error about missing name is already reported - do not report extra one
if (rightType === neverType || !isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive)) {
if (rightType === neverType || !(rightType.flags & TypeFlags.Any || isTypeAssignableToKind(rightType, TypeFlags.NonPrimitive | TypeFlags.InstantiableNonPrimitive))) {
error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter_but_here_has_type_0, typeToString(rightType));
}

Expand Down
7 changes: 7 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,13 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Raise_error_on_expressions_and_declarations_with_an_implied_any_type,
},
{
name: "strictAny",
type: "boolean",
showInSimplifiedHelpView: true,
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_any_type
},
{
name: "strictNullChecks",
type: "boolean",
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2032,7 +2032,7 @@ namespace ts {
return !!(compilerOptions.declaration || compilerOptions.composite);
}

export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict";
export type StrictOptionName = "noImplicitAny" | "noImplicitThis" | "strictNullChecks" | "strictFunctionTypes" | "strictPropertyInitialization" | "alwaysStrict" | "strictAny";

export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean {
return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag];
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -3567,6 +3567,10 @@
"code": 6199,
"reportsUnnecessary": true
},
"Enable strict checking of 'any' type.": {
"category": "Message",
"code": 6200
},

"Projects to reference": {
"category": "Message",
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4351,6 +4351,7 @@ namespace ts {
sourceMap?: boolean;
sourceRoot?: string;
strict?: boolean;
strictAny?: boolean; // Always combine with strict property
strictFunctionTypes?: boolean; // Always combine with strict property
strictNullChecks?: boolean; // Always combine with strict property
strictPropertyInitialization?: boolean; // Always combine with strict property
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/tsserverlibrary.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2454,6 +2454,7 @@ declare namespace ts {
sourceMap?: boolean;
sourceRoot?: string;
strict?: boolean;
strictAny?: boolean;
strictFunctionTypes?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
Expand Down
1 change: 1 addition & 0 deletions tests/baselines/reference/api/typescript.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2454,6 +2454,7 @@ declare namespace ts {
sourceMap?: boolean;
sourceRoot?: string;
strict?: boolean;
strictAny?: boolean;
strictFunctionTypes?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictAny": true, /* Enable strict checking of 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
Expand Down
1 change: 1 addition & 0 deletions tests/cases/compiler/APISample_jsdoc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// @skipLibCheck: true
// @includebuiltfile: typescript_standalone.d.ts
// @strict:true
// @strictAny:false

/*
* Note: This test is a public API sample. The original sources can be found
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// @target: es5
// @lib: es6
// @strict: true
// @strictAny: false

// repro for: https://github.com/Microsoft/TypeScript/issues/23661
export interface IValidationError {
Expand Down
1 change: 1 addition & 0 deletions tests/cases/compiler/invariantGenericErrorElaboration.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @strict: true
// @strictAny: false

// Repro from #19746

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @strict: true
// @strictAny: false
// @declaration: true

interface Covariant<T> {
Expand Down
1 change: 1 addition & 0 deletions tests/cases/conformance/types/conditional/inferTypes1.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @strict: true
// @strictAny: false
// @declaration: true

type Unpacked<T> =
Expand Down
1 change: 1 addition & 0 deletions tests/cases/conformance/types/mapped/mappedTypeWithAny.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @strict: true
// @strictAny: false
// @declaration: true

type Item = { value: string };
Expand Down
1 change: 1 addition & 0 deletions tests/cases/conformance/types/mapped/mappedTypes5.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// @strict: true
// @strictAny: false

function f<T>(p: Partial<T>, r: Readonly<T>, pr: Partial<Readonly<T>>, rp: Readonly<Partial<T>>) {
let a1: Partial<T> = p;
Expand Down