From 661740fefea4ef63032931a724567762272ae699 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 10 Jul 2020 20:42:04 -0700 Subject: [PATCH 1/9] Initial implementation + tests --- src/compiler/checker.ts | 22 +- src/compiler/commandLineParser.ts | 10 +- src/compiler/diagnosticMessages.json | 5 + src/compiler/types.ts | 1 + .../reference/api/tsserverlibrary.d.ts | 1 + tests/baselines/reference/api/typescript.d.ts | 1 + .../pedanticIndexSignatures.errors.txt | 202 ++++++++++++ .../reference/pedanticIndexSignatures.js | 137 ++++++++ .../reference/pedanticIndexSignatures.symbols | 240 ++++++++++++++ .../reference/pedanticIndexSignatures.types | 294 ++++++++++++++++++ .../pedanticIndexSignatures/tsconfig.json | 5 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../tsconfig.json | 1 + .../declarationDir-is-specified.js | 1 + ...-outDir-and-declarationDir-is-specified.js | 1 + .../when-outDir-is-specified.js | 1 + .../with-outFile.js | 1 + ...e-is-specified-with-declaration-enabled.js | 1 + .../without-outDir-or-outFile-is-specified.js | 1 + .../pedantic/pedanticIndexSignatures.ts | 74 +++++ 27 files changed, 1001 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/pedanticIndexSignatures.errors.txt create mode 100644 tests/baselines/reference/pedanticIndexSignatures.js create mode 100644 tests/baselines/reference/pedanticIndexSignatures.symbols create mode 100644 tests/baselines/reference/pedanticIndexSignatures.types create mode 100644 tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json create mode 100644 tests/cases/conformance/pedantic/pedanticIndexSignatures.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5e49fc6af071e..9ebe5276214d5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -185,6 +185,7 @@ namespace ts { Writing = 1 << 1, CacheSymbol = 1 << 2, NoTupleBoundsCheck = 1 << 3, + ExpressionPosition = 1 << 4, } const enum SignatureCheckMode { @@ -13760,6 +13761,11 @@ namespace ts { if (objectType === wildcardType || indexType === wildcardType) { return wildcardType; } + + const shouldIncludeUndefined = + compilerOptions.pedanticIndexSignatures && + (accessFlags & (AccessFlags.Writing | AccessFlags.ExpressionPosition)) === AccessFlags.ExpressionPosition; + // If the object type has a string index signature and no other members we know that the result will // always be the type of that index signature and we can simplify accordingly. if (isStringIndexSignatureOnlyType(objectType) && !(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { @@ -13783,7 +13789,8 @@ namespace ts { if (!type) { indexedAccessTypes.set(id, type = createIndexedAccessType(objectType, indexType, aliasSymbol, aliasTypeArguments)); } - return type; + + return shouldIncludeUndefined ? getUnionType([type, undefinedType]) : type; } // In the following we resolve T[K] to the type of the property in T selected by K. // We treat boolean as different from other unions to improve errors; @@ -13809,9 +13816,13 @@ namespace ts { if (wasMissingProp) { return undefined; } - return accessFlags & AccessFlags.Writing ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments) : getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + return accessFlags & AccessFlags.Writing ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments) : + shouldIncludeUndefined ? + getUnionType([getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments), undefinedType]) : + getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } - return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, /* supressNoImplicitAnyError */ false, accessNode, accessFlags | AccessFlags.CacheSymbol, /* reportDeprecated */ true); + const type = getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, /* supressNoImplicitAnyError */ false, accessNode, accessFlags | AccessFlags.CacheSymbol, /* reportDeprecated */ true); + return type && (shouldIncludeUndefined ? getUnionType([type, undefinedType]) : type); } function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) { @@ -25219,7 +25230,8 @@ namespace ts { if (indexInfo.isReadonly && (isAssignmentTarget(node) || isDeleteTarget(node))) { error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - propType = indexInfo.type; + + propType = (compilerOptions.pedanticIndexSignatures && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; } else { if (prop.valueDeclaration?.flags & NodeFlags.Deprecated && isUncalledFunctionReference(node, prop)) { @@ -25659,7 +25671,7 @@ namespace ts { const accessFlags = isAssignmentTarget(node) ? AccessFlags.Writing | (isGenericObjectType(objectType) && !isThisTypeParameter(objectType) ? AccessFlags.NoIndexSignatures : 0) : AccessFlags.None; - const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, node, accessFlags) || errorType; + const indexedAccessType = getIndexedAccessTypeOrUndefined(objectType, effectiveIndexType, node, accessFlags | AccessFlags.ExpressionPosition) || errorType; return checkIndexedAccessIndexType(getFlowTypeOfAccessExpression(node, indexedAccessType.symbol, indexedAccessType, indexExpression), node); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 3095c9d7dc82e..eeaf50be1a303 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -606,7 +606,15 @@ namespace ts { category: Diagnostics.Additional_Checks, description: Diagnostics.Report_errors_for_fallthrough_cases_in_switch_statement }, - + { + name: "pedanticIndexSignatures", + type: "boolean", + affectsSemanticDiagnostics: true, + showInSimplifiedHelpView: false, + category: Diagnostics.Additional_Checks, + description: Diagnostics.Include_undefined_in_index_signature_results + }, + // Module Resolution { name: "moduleResolution", diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 22d8c6113a408..a8b4bd3a2ae32 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4698,6 +4698,11 @@ "code": 6504 }, + "Include 'undefined' in index signature results": { + "category": "Message", + "code": 6800 + }, + "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 86596b9a3048d..1d3317a455fd9 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5716,6 +5716,7 @@ namespace ts { outDir?: string; outFile?: string; paths?: MapLike; + pedanticIndexSignatures?: boolean; /*@internal*/ plugins?: PluginImport[]; preserveConstEnums?: boolean; preserveSymlinks?: boolean; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 142dc3a9e7d29..c8336d6d6a0bc 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2800,6 +2800,7 @@ declare namespace ts { outDir?: string; outFile?: string; paths?: MapLike; + pedanticIndexSignatures?: boolean; preserveConstEnums?: boolean; preserveSymlinks?: boolean; project?: string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 86432ff0efad4..0c05f502dbb81 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2800,6 +2800,7 @@ declare namespace ts { outDir?: string; outFile?: string; paths?: MapLike; + pedanticIndexSignatures?: boolean; preserveConstEnums?: boolean; preserveSymlinks?: boolean; project?: string; diff --git a/tests/baselines/reference/pedanticIndexSignatures.errors.txt b/tests/baselines/reference/pedanticIndexSignatures.errors.txt new file mode 100644 index 0000000000000..68dc2a7668948 --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatures.errors.txt @@ -0,0 +1,202 @@ +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(3,32): error TS2344: Type 'boolean | undefined' does not satisfy the constraint 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(12,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(13,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(14,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(15,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(16,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(17,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(18,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(19,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(20,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(21,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(22,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(23,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(24,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(25,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(38,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(39,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(40,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(41,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(46,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(47,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(48,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(49,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(50,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(55,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(63,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(70,7): error TS2322: Type 'number | boolean | undefined' is not assignable to type 'number | boolean'. + Type 'undefined' is not assignable to type 'number | boolean'. + + +==== tests/cases/conformance/pedantic/pedanticIndexSignatures.ts (27 errors) ==== + type CheckBooleanOnly = any; + // Validate CheckBooleanOnly works - should error + type T_ERR1 = CheckBooleanOnly; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'boolean | undefined' does not satisfy the constraint 'boolean'. +!!! error TS2344: Type 'undefined' is not assignable to type 'boolean'. + + enum NumericEnum1 { A, B, C } + enum NumericEnum2 { A = 0, B = 1 , C = 2 } + enum StringEnum1 { A = "Alpha", B = "Beta" } + + declare const strMap: { [s: string]: boolean }; + + // All of these should be errors + const e1: boolean = strMap["foo"]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e2: boolean = strMap.bar; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e3: boolean = strMap[0]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e4: boolean = strMap[0 as string | number]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e5: boolean = strMap[0 as string | 0 | 1]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e6: boolean = strMap[0 as 0 | 1]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e7: boolean = strMap["foo" as "foo" | "baz"]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e8: boolean = strMap[NumericEnum1.A]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e9: boolean = strMap[NumericEnum2.A]; + ~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e10: boolean = strMap[StringEnum1.A]; + ~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e11: boolean = strMap[StringEnum1.A as StringEnum1]; + ~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; + ~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; + ~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const e14: boolean = strMap[null as any]; + ~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + + // Should be OK + const ok1: boolean | undefined = strMap["foo"]; + const ok2: boolean | undefined = strMap.bar; + + type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; + type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; + type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; + type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; + type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; + + // Writes don't allow 'undefined'; all should be errors + strMap["baz"] = undefined; + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + strMap.qua = undefined; + ~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + strMap[0] = undefined; + ~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + strMap[null as any] = undefined; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + + // Numeric lookups are unaffected + declare const numMap: { [s: number]: boolean }; + // All of these should be ok + const num_ok1: boolean = numMap[0]; + ~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const num_ok2: boolean = numMap[0 as number]; + ~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const num_ok3: boolean = numMap[0 as 0 | 1]; + ~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const num_ok4: boolean = numMap[NumericEnum1.A]; + ~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + const num_ok5: boolean = numMap[NumericEnum2.A]; + ~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + + // Generics + function generic1(arg: T): boolean { + // Should error + return arg["blah"]; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + } + function generic2(arg: T): boolean { + // Should OK + return arg["blah"]!; + } + function generic3(arg: T): boolean { + // Should error + return strMap[arg]; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + } + + + // Distributivity cases + declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; + // Should error + const f1: boolean | number = strMapUnion["foo"]; + ~~ +!!! error TS2322: Type 'number | boolean | undefined' is not assignable to type 'number | boolean'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number | boolean'. + + \ No newline at end of file diff --git a/tests/baselines/reference/pedanticIndexSignatures.js b/tests/baselines/reference/pedanticIndexSignatures.js new file mode 100644 index 0000000000000..c59c93a84818d --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatures.js @@ -0,0 +1,137 @@ +//// [pedanticIndexSignatures.ts] +type CheckBooleanOnly = any; +// Validate CheckBooleanOnly works - should error +type T_ERR1 = CheckBooleanOnly; + +enum NumericEnum1 { A, B, C } +enum NumericEnum2 { A = 0, B = 1 , C = 2 } +enum StringEnum1 { A = "Alpha", B = "Beta" } + +declare const strMap: { [s: string]: boolean }; + +// All of these should be errors +const e1: boolean = strMap["foo"]; +const e2: boolean = strMap.bar; +const e3: boolean = strMap[0]; +const e4: boolean = strMap[0 as string | number]; +const e5: boolean = strMap[0 as string | 0 | 1]; +const e6: boolean = strMap[0 as 0 | 1]; +const e7: boolean = strMap["foo" as "foo" | "baz"]; +const e8: boolean = strMap[NumericEnum1.A]; +const e9: boolean = strMap[NumericEnum2.A]; +const e10: boolean = strMap[StringEnum1.A]; +const e11: boolean = strMap[StringEnum1.A as StringEnum1]; +const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; +const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; +const e14: boolean = strMap[null as any]; + +// Should be OK +const ok1: boolean | undefined = strMap["foo"]; +const ok2: boolean | undefined = strMap.bar; + +type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; +type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; +type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; +type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; +type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; + +// Writes don't allow 'undefined'; all should be errors +strMap["baz"] = undefined; +strMap.qua = undefined; +strMap[0] = undefined; +strMap[null as any] = undefined; + +// Numeric lookups are unaffected +declare const numMap: { [s: number]: boolean }; +// All of these should be ok +const num_ok1: boolean = numMap[0]; +const num_ok2: boolean = numMap[0 as number]; +const num_ok3: boolean = numMap[0 as 0 | 1]; +const num_ok4: boolean = numMap[NumericEnum1.A]; +const num_ok5: boolean = numMap[NumericEnum2.A]; + +// Generics +function generic1(arg: T): boolean { + // Should error + return arg["blah"]; +} +function generic2(arg: T): boolean { + // Should OK + return arg["blah"]!; +} +function generic3(arg: T): boolean { + // Should error + return strMap[arg]; +} + + +// Distributivity cases +declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; +// Should error +const f1: boolean | number = strMapUnion["foo"]; + + + +//// [pedanticIndexSignatures.js] +"use strict"; +var NumericEnum1; +(function (NumericEnum1) { + NumericEnum1[NumericEnum1["A"] = 0] = "A"; + NumericEnum1[NumericEnum1["B"] = 1] = "B"; + NumericEnum1[NumericEnum1["C"] = 2] = "C"; +})(NumericEnum1 || (NumericEnum1 = {})); +var NumericEnum2; +(function (NumericEnum2) { + NumericEnum2[NumericEnum2["A"] = 0] = "A"; + NumericEnum2[NumericEnum2["B"] = 1] = "B"; + NumericEnum2[NumericEnum2["C"] = 2] = "C"; +})(NumericEnum2 || (NumericEnum2 = {})); +var StringEnum1; +(function (StringEnum1) { + StringEnum1["A"] = "Alpha"; + StringEnum1["B"] = "Beta"; +})(StringEnum1 || (StringEnum1 = {})); +// All of these should be errors +var e1 = strMap["foo"]; +var e2 = strMap.bar; +var e3 = strMap[0]; +var e4 = strMap[0]; +var e5 = strMap[0]; +var e6 = strMap[0]; +var e7 = strMap["foo"]; +var e8 = strMap[NumericEnum1.A]; +var e9 = strMap[NumericEnum2.A]; +var e10 = strMap[StringEnum1.A]; +var e11 = strMap[StringEnum1.A]; +var e12 = strMap[NumericEnum1.A]; +var e13 = strMap[NumericEnum2.A]; +var e14 = strMap[null]; +// Should be OK +var ok1 = strMap["foo"]; +var ok2 = strMap.bar; +// Writes don't allow 'undefined'; all should be errors +strMap["baz"] = undefined; +strMap.qua = undefined; +strMap[0] = undefined; +strMap[null] = undefined; +// All of these should be ok +var num_ok1 = numMap[0]; +var num_ok2 = numMap[0]; +var num_ok3 = numMap[0]; +var num_ok4 = numMap[NumericEnum1.A]; +var num_ok5 = numMap[NumericEnum2.A]; +// Generics +function generic1(arg) { + // Should error + return arg["blah"]; +} +function generic2(arg) { + // Should OK + return arg["blah"]; +} +function generic3(arg) { + // Should error + return strMap[arg]; +} +// Should error +var f1 = strMapUnion["foo"]; diff --git a/tests/baselines/reference/pedanticIndexSignatures.symbols b/tests/baselines/reference/pedanticIndexSignatures.symbols new file mode 100644 index 0000000000000..4741dd75ec57d --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatures.symbols @@ -0,0 +1,240 @@ +=== tests/cases/conformance/pedantic/pedanticIndexSignatures.ts === +type CheckBooleanOnly = any; +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 0, 22)) + +// Validate CheckBooleanOnly works - should error +type T_ERR1 = CheckBooleanOnly; +>T_ERR1 : Symbol(T_ERR1, Decl(pedanticIndexSignatures.ts, 0, 47)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) + +enum NumericEnum1 { A, B, C } +>NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) +>B : Symbol(NumericEnum1.B, Decl(pedanticIndexSignatures.ts, 4, 22)) +>C : Symbol(NumericEnum1.C, Decl(pedanticIndexSignatures.ts, 4, 25)) + +enum NumericEnum2 { A = 0, B = 1 , C = 2 } +>NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) +>B : Symbol(NumericEnum2.B, Decl(pedanticIndexSignatures.ts, 5, 26)) +>C : Symbol(NumericEnum2.C, Decl(pedanticIndexSignatures.ts, 5, 34)) + +enum StringEnum1 { A = "Alpha", B = "Beta" } +>StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) +>A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) +>B : Symbol(StringEnum1.B, Decl(pedanticIndexSignatures.ts, 6, 31)) + +declare const strMap: { [s: string]: boolean }; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 8, 25)) + +// All of these should be errors +const e1: boolean = strMap["foo"]; +>e1 : Symbol(e1, Decl(pedanticIndexSignatures.ts, 11, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e2: boolean = strMap.bar; +>e2 : Symbol(e2, Decl(pedanticIndexSignatures.ts, 12, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e3: boolean = strMap[0]; +>e3 : Symbol(e3, Decl(pedanticIndexSignatures.ts, 13, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e4: boolean = strMap[0 as string | number]; +>e4 : Symbol(e4, Decl(pedanticIndexSignatures.ts, 14, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e5: boolean = strMap[0 as string | 0 | 1]; +>e5 : Symbol(e5, Decl(pedanticIndexSignatures.ts, 15, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e6: boolean = strMap[0 as 0 | 1]; +>e6 : Symbol(e6, Decl(pedanticIndexSignatures.ts, 16, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e7: boolean = strMap["foo" as "foo" | "baz"]; +>e7 : Symbol(e7, Decl(pedanticIndexSignatures.ts, 17, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const e8: boolean = strMap[NumericEnum1.A]; +>e8 : Symbol(e8, Decl(pedanticIndexSignatures.ts, 18, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>NumericEnum1.A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) + +const e9: boolean = strMap[NumericEnum2.A]; +>e9 : Symbol(e9, Decl(pedanticIndexSignatures.ts, 19, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>NumericEnum2.A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) + +const e10: boolean = strMap[StringEnum1.A]; +>e10 : Symbol(e10, Decl(pedanticIndexSignatures.ts, 20, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>StringEnum1.A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) +>StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) +>A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) + +const e11: boolean = strMap[StringEnum1.A as StringEnum1]; +>e11 : Symbol(e11, Decl(pedanticIndexSignatures.ts, 21, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>StringEnum1.A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) +>StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) +>A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) +>StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) + +const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; +>e12 : Symbol(e12, Decl(pedanticIndexSignatures.ts, 22, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>NumericEnum1.A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) + +const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; +>e13 : Symbol(e13, Decl(pedanticIndexSignatures.ts, 23, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>NumericEnum2.A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) + +const e14: boolean = strMap[null as any]; +>e14 : Symbol(e14, Decl(pedanticIndexSignatures.ts, 24, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +// Should be OK +const ok1: boolean | undefined = strMap["foo"]; +>ok1 : Symbol(ok1, Decl(pedanticIndexSignatures.ts, 27, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +const ok2: boolean | undefined = strMap.bar; +>ok2 : Symbol(ok2, Decl(pedanticIndexSignatures.ts, 28, 5)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; +>T_OK1 : Symbol(T_OK1, Decl(pedanticIndexSignatures.ts, 28, 44)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; +>T_OK2 : Symbol(T_OK2, Decl(pedanticIndexSignatures.ts, 30, 55)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; +>T_OK3 : Symbol(T_OK3, Decl(pedanticIndexSignatures.ts, 31, 54)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; +>T_OK4 : Symbol(T_OK4, Decl(pedanticIndexSignatures.ts, 32, 62)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; +>T_OK5 : Symbol(T_OK5, Decl(pedanticIndexSignatures.ts, 33, 55)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) + +// Writes don't allow 'undefined'; all should be errors +strMap["baz"] = undefined; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>undefined : Symbol(undefined) + +strMap.qua = undefined; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>undefined : Symbol(undefined) + +strMap[0] = undefined; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>undefined : Symbol(undefined) + +strMap[null as any] = undefined; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>undefined : Symbol(undefined) + +// Numeric lookups are unaffected +declare const numMap: { [s: number]: boolean }; +>numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 43, 25)) + +// All of these should be ok +const num_ok1: boolean = numMap[0]; +>num_ok1 : Symbol(num_ok1, Decl(pedanticIndexSignatures.ts, 45, 5)) +>numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) + +const num_ok2: boolean = numMap[0 as number]; +>num_ok2 : Symbol(num_ok2, Decl(pedanticIndexSignatures.ts, 46, 5)) +>numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) + +const num_ok3: boolean = numMap[0 as 0 | 1]; +>num_ok3 : Symbol(num_ok3, Decl(pedanticIndexSignatures.ts, 47, 5)) +>numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) + +const num_ok4: boolean = numMap[NumericEnum1.A]; +>num_ok4 : Symbol(num_ok4, Decl(pedanticIndexSignatures.ts, 48, 5)) +>numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) +>NumericEnum1.A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) + +const num_ok5: boolean = numMap[NumericEnum2.A]; +>num_ok5 : Symbol(num_ok5, Decl(pedanticIndexSignatures.ts, 49, 5)) +>numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) +>NumericEnum2.A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) + +// Generics +function generic1(arg: T): boolean { +>generic1 : Symbol(generic1, Decl(pedanticIndexSignatures.ts, 49, 48)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 52, 18)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 52, 31)) +>arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 52, 54)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 52, 18)) + + // Should error + return arg["blah"]; +>arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 52, 54)) +} +function generic2(arg: T): boolean { +>generic2 : Symbol(generic2, Decl(pedanticIndexSignatures.ts, 55, 1)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 56, 18)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 56, 31)) +>arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 56, 54)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 56, 18)) + + // Should OK + return arg["blah"]!; +>arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 56, 54)) +} +function generic3(arg: T): boolean { +>generic3 : Symbol(generic3, Decl(pedanticIndexSignatures.ts, 59, 1)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 60, 18)) +>arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 60, 36)) +>T : Symbol(T, Decl(pedanticIndexSignatures.ts, 60, 18)) + + // Should error + return strMap[arg]; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) +>arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 60, 36)) +} + + +// Distributivity cases +declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; +>strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 67, 13)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 67, 30)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 67, 57)) + +// Should error +const f1: boolean | number = strMapUnion["foo"]; +>f1 : Symbol(f1, Decl(pedanticIndexSignatures.ts, 69, 5)) +>strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 67, 13)) + + diff --git a/tests/baselines/reference/pedanticIndexSignatures.types b/tests/baselines/reference/pedanticIndexSignatures.types new file mode 100644 index 0000000000000..13e1a03b1bf70 --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatures.types @@ -0,0 +1,294 @@ +=== tests/cases/conformance/pedantic/pedanticIndexSignatures.ts === +type CheckBooleanOnly = any; +>CheckBooleanOnly : any + +// Validate CheckBooleanOnly works - should error +type T_ERR1 = CheckBooleanOnly; +>T_ERR1 : any + +enum NumericEnum1 { A, B, C } +>NumericEnum1 : NumericEnum1 +>A : NumericEnum1.A +>B : NumericEnum1.B +>C : NumericEnum1.C + +enum NumericEnum2 { A = 0, B = 1 , C = 2 } +>NumericEnum2 : NumericEnum2 +>A : NumericEnum2.A +>0 : 0 +>B : NumericEnum2.B +>1 : 1 +>C : NumericEnum2.C +>2 : 2 + +enum StringEnum1 { A = "Alpha", B = "Beta" } +>StringEnum1 : StringEnum1 +>A : StringEnum1.A +>"Alpha" : "Alpha" +>B : StringEnum1.B +>"Beta" : "Beta" + +declare const strMap: { [s: string]: boolean }; +>strMap : { [s: string]: boolean; } +>s : string + +// All of these should be errors +const e1: boolean = strMap["foo"]; +>e1 : boolean +>strMap["foo"] : boolean | undefined +>strMap : { [s: string]: boolean; } +>"foo" : "foo" + +const e2: boolean = strMap.bar; +>e2 : boolean +>strMap.bar : boolean | undefined +>strMap : { [s: string]: boolean; } +>bar : boolean | undefined + +const e3: boolean = strMap[0]; +>e3 : boolean +>strMap[0] : boolean | undefined +>strMap : { [s: string]: boolean; } +>0 : 0 + +const e4: boolean = strMap[0 as string | number]; +>e4 : boolean +>strMap[0 as string | number] : boolean | undefined +>strMap : { [s: string]: boolean; } +>0 as string | number : string | number +>0 : 0 + +const e5: boolean = strMap[0 as string | 0 | 1]; +>e5 : boolean +>strMap[0 as string | 0 | 1] : boolean | undefined +>strMap : { [s: string]: boolean; } +>0 as string | 0 | 1 : string | 0 | 1 +>0 : 0 + +const e6: boolean = strMap[0 as 0 | 1]; +>e6 : boolean +>strMap[0 as 0 | 1] : boolean | undefined +>strMap : { [s: string]: boolean; } +>0 as 0 | 1 : 0 | 1 +>0 : 0 + +const e7: boolean = strMap["foo" as "foo" | "baz"]; +>e7 : boolean +>strMap["foo" as "foo" | "baz"] : boolean | undefined +>strMap : { [s: string]: boolean; } +>"foo" as "foo" | "baz" : "foo" | "baz" +>"foo" : "foo" + +const e8: boolean = strMap[NumericEnum1.A]; +>e8 : boolean +>strMap[NumericEnum1.A] : boolean | undefined +>strMap : { [s: string]: boolean; } +>NumericEnum1.A : NumericEnum1.A +>NumericEnum1 : typeof NumericEnum1 +>A : NumericEnum1.A + +const e9: boolean = strMap[NumericEnum2.A]; +>e9 : boolean +>strMap[NumericEnum2.A] : boolean | undefined +>strMap : { [s: string]: boolean; } +>NumericEnum2.A : NumericEnum2.A +>NumericEnum2 : typeof NumericEnum2 +>A : NumericEnum2.A + +const e10: boolean = strMap[StringEnum1.A]; +>e10 : boolean +>strMap[StringEnum1.A] : boolean | undefined +>strMap : { [s: string]: boolean; } +>StringEnum1.A : StringEnum1.A +>StringEnum1 : typeof StringEnum1 +>A : StringEnum1.A + +const e11: boolean = strMap[StringEnum1.A as StringEnum1]; +>e11 : boolean +>strMap[StringEnum1.A as StringEnum1] : boolean | undefined +>strMap : { [s: string]: boolean; } +>StringEnum1.A as StringEnum1 : StringEnum1 +>StringEnum1.A : StringEnum1.A +>StringEnum1 : typeof StringEnum1 +>A : StringEnum1.A + +const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; +>e12 : boolean +>strMap[NumericEnum1.A as NumericEnum1] : boolean | undefined +>strMap : { [s: string]: boolean; } +>NumericEnum1.A as NumericEnum1 : NumericEnum1 +>NumericEnum1.A : NumericEnum1.A +>NumericEnum1 : typeof NumericEnum1 +>A : NumericEnum1.A + +const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; +>e13 : boolean +>strMap[NumericEnum2.A as NumericEnum2] : boolean | undefined +>strMap : { [s: string]: boolean; } +>NumericEnum2.A as NumericEnum2 : NumericEnum2 +>NumericEnum2.A : NumericEnum2.A +>NumericEnum2 : typeof NumericEnum2 +>A : NumericEnum2.A + +const e14: boolean = strMap[null as any]; +>e14 : boolean +>strMap[null as any] : boolean | undefined +>strMap : { [s: string]: boolean; } +>null as any : any +>null : null + +// Should be OK +const ok1: boolean | undefined = strMap["foo"]; +>ok1 : boolean | undefined +>strMap["foo"] : boolean | undefined +>strMap : { [s: string]: boolean; } +>"foo" : "foo" + +const ok2: boolean | undefined = strMap.bar; +>ok2 : boolean | undefined +>strMap.bar : boolean | undefined +>strMap : { [s: string]: boolean; } +>bar : boolean | undefined + +type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; +>T_OK1 : any +>strMap : { [s: string]: boolean; } + +type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; +>T_OK2 : any +>strMap : { [s: string]: boolean; } + +type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; +>T_OK3 : any +>strMap : { [s: string]: boolean; } + +type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; +>T_OK4 : any +>strMap : { [s: string]: boolean; } + +type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; +>T_OK5 : any +>strMap : { [s: string]: boolean; } + +// Writes don't allow 'undefined'; all should be errors +strMap["baz"] = undefined; +>strMap["baz"] = undefined : undefined +>strMap["baz"] : boolean +>strMap : { [s: string]: boolean; } +>"baz" : "baz" +>undefined : undefined + +strMap.qua = undefined; +>strMap.qua = undefined : undefined +>strMap.qua : boolean +>strMap : { [s: string]: boolean; } +>qua : boolean +>undefined : undefined + +strMap[0] = undefined; +>strMap[0] = undefined : undefined +>strMap[0] : boolean +>strMap : { [s: string]: boolean; } +>0 : 0 +>undefined : undefined + +strMap[null as any] = undefined; +>strMap[null as any] = undefined : undefined +>strMap[null as any] : boolean +>strMap : { [s: string]: boolean; } +>null as any : any +>null : null +>undefined : undefined + +// Numeric lookups are unaffected +declare const numMap: { [s: number]: boolean }; +>numMap : { [s: number]: boolean; } +>s : number + +// All of these should be ok +const num_ok1: boolean = numMap[0]; +>num_ok1 : boolean +>numMap[0] : boolean | undefined +>numMap : { [s: number]: boolean; } +>0 : 0 + +const num_ok2: boolean = numMap[0 as number]; +>num_ok2 : boolean +>numMap[0 as number] : boolean | undefined +>numMap : { [s: number]: boolean; } +>0 as number : number +>0 : 0 + +const num_ok3: boolean = numMap[0 as 0 | 1]; +>num_ok3 : boolean +>numMap[0 as 0 | 1] : boolean | undefined +>numMap : { [s: number]: boolean; } +>0 as 0 | 1 : 0 | 1 +>0 : 0 + +const num_ok4: boolean = numMap[NumericEnum1.A]; +>num_ok4 : boolean +>numMap[NumericEnum1.A] : boolean | undefined +>numMap : { [s: number]: boolean; } +>NumericEnum1.A : NumericEnum1.A +>NumericEnum1 : typeof NumericEnum1 +>A : NumericEnum1.A + +const num_ok5: boolean = numMap[NumericEnum2.A]; +>num_ok5 : boolean +>numMap[NumericEnum2.A] : boolean | undefined +>numMap : { [s: number]: boolean; } +>NumericEnum2.A : NumericEnum2.A +>NumericEnum2 : typeof NumericEnum2 +>A : NumericEnum2.A + +// Generics +function generic1(arg: T): boolean { +>generic1 : (arg: T) => boolean +>s : string +>arg : T + + // Should error + return arg["blah"]; +>arg["blah"] : boolean | undefined +>arg : T +>"blah" : "blah" +} +function generic2(arg: T): boolean { +>generic2 : (arg: T) => boolean +>s : string +>arg : T + + // Should OK + return arg["blah"]!; +>arg["blah"]! : boolean +>arg["blah"] : boolean | undefined +>arg : T +>"blah" : "blah" +} +function generic3(arg: T): boolean { +>generic3 : (arg: T) => boolean +>arg : T + + // Should error + return strMap[arg]; +>strMap[arg] : boolean | undefined +>strMap : { [s: string]: boolean; } +>arg : T +} + + +// Distributivity cases +declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; +>strMapUnion : { [s: string]: boolean; } | { [s: string]: number; } +>s : string +>s : string + +// Should error +const f1: boolean | number = strMapUnion["foo"]; +>f1 : number | boolean +>strMapUnion["foo"] : number | boolean | undefined +>strMapUnion : { [s: string]: boolean; } | { [s: string]: number; } +>"foo" : "foo" + + diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json new file mode 100644 index 0000000000000..1bdf01a277166 --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "pedanticIndexSignatures": true + } +} diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index c9f603c2199ec..23fc21a8414e0 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index 83893736515ea..43fcfd6270bf0 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index f2ff8ef9f0053..07c59988e9acb 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index 286219dae6e96..f628900344519 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 0ec33da9842fc..4d07f29793bb9 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index ea8f60ca0cf8c..cf76560e711e9 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index c9f603c2199ec..23fc21a8414e0 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 7add8d543f8c8..1c622896419ad 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 29a0374fa2688..53b477e7fe55e 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -39,6 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js index 68e55e69a289b..908c943b51802 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js @@ -60,6 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js index 4f58a6cb9209c..b0ab8fcc3025a 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js @@ -60,6 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js index c0390a97918af..ad859947b9f73 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js @@ -60,6 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js index b04d25e8fefc4..04a6d0aafa781 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js @@ -60,6 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js index a95b9006f3cbf..4fad3c7344c98 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js @@ -60,6 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js index 3b98f66e02fde..f5071fa2024c2 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js @@ -60,6 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts b/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts new file mode 100644 index 0000000000000..70d53d9b2cd2c --- /dev/null +++ b/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts @@ -0,0 +1,74 @@ +// @strict: true +// @pedanticIndexSignatures: true + +type CheckBooleanOnly = any; +// Validate CheckBooleanOnly works - should error +type T_ERR1 = CheckBooleanOnly; + +enum NumericEnum1 { A, B, C } +enum NumericEnum2 { A = 0, B = 1 , C = 2 } +enum StringEnum1 { A = "Alpha", B = "Beta" } + +declare const strMap: { [s: string]: boolean }; + +// All of these should be errors +const e1: boolean = strMap["foo"]; +const e2: boolean = strMap.bar; +const e3: boolean = strMap[0]; +const e4: boolean = strMap[0 as string | number]; +const e5: boolean = strMap[0 as string | 0 | 1]; +const e6: boolean = strMap[0 as 0 | 1]; +const e7: boolean = strMap["foo" as "foo" | "baz"]; +const e8: boolean = strMap[NumericEnum1.A]; +const e9: boolean = strMap[NumericEnum2.A]; +const e10: boolean = strMap[StringEnum1.A]; +const e11: boolean = strMap[StringEnum1.A as StringEnum1]; +const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; +const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; +const e14: boolean = strMap[null as any]; + +// Should be OK +const ok1: boolean | undefined = strMap["foo"]; +const ok2: boolean | undefined = strMap.bar; + +type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; +type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; +type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; +type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; +type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; + +// Writes don't allow 'undefined'; all should be errors +strMap["baz"] = undefined; +strMap.qua = undefined; +strMap[0] = undefined; +strMap[null as any] = undefined; + +// Numeric lookups are unaffected +declare const numMap: { [s: number]: boolean }; +// All of these should be ok +const num_ok1: boolean = numMap[0]; +const num_ok2: boolean = numMap[0 as number]; +const num_ok3: boolean = numMap[0 as 0 | 1]; +const num_ok4: boolean = numMap[NumericEnum1.A]; +const num_ok5: boolean = numMap[NumericEnum2.A]; + +// Generics +function generic1(arg: T): boolean { + // Should error + return arg["blah"]; +} +function generic2(arg: T): boolean { + // Should OK + return arg["blah"]!; +} +function generic3(arg: T): boolean { + // Should error + return strMap[arg]; +} + + +// Distributivity cases +declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; +// Should error +const f1: boolean | number = strMapUnion["foo"]; + From 6d1ec2bafac51a3ea60cba0926f0a819520ef14c Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 10 Jul 2020 21:53:03 -0700 Subject: [PATCH 2/9] linty --- src/compiler/commandLineParser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index eeaf50be1a303..1e01daa30f83c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -614,7 +614,7 @@ namespace ts { category: Diagnostics.Additional_Checks, description: Diagnostics.Include_undefined_in_index_signature_results }, - + // Module Resolution { name: "moduleResolution", From 6a1e284233b73b6a01d2eaa8a2a4e86ae6d49324 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Sun, 12 Jul 2020 20:59:27 -0700 Subject: [PATCH 3/9] Support destructuring declarations and assignments --- src/compiler/checker.ts | 50 +++-- ...nticIndexSignatureDestructuring.errors.txt | 106 ++++++++++ .../pedanticIndexSignatureDestructuring.js | 114 ++++++++++ ...edanticIndexSignatureDestructuring.symbols | 162 +++++++++++++++ .../pedanticIndexSignatureDestructuring.types | 195 ++++++++++++++++++ .../pedanticIndexSignatureDestructuring.ts | 64 ++++++ 6 files changed, 673 insertions(+), 18 deletions(-) create mode 100644 tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt create mode 100644 tests/baselines/reference/pedanticIndexSignatureDestructuring.js create mode 100644 tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols create mode 100644 tests/baselines/reference/pedanticIndexSignatureDestructuring.types create mode 100644 tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9ebe5276214d5..a929e30da622a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16,6 +16,7 @@ namespace ts { YieldStarFlag = 1 << 4, SpreadFlag = 1 << 5, DestructuringFlag = 1 << 6, + PossiblyOutOfBounds = 1 << 7, // Spread, Destructuring, Array element assignment Element = AllowsSyncIterablesFlag, @@ -7800,7 +7801,7 @@ namespace ts { // Use explicitly specified property name ({ p: xxx } form), or otherwise the implied name ({ p } form) const name = declaration.propertyName || declaration.name; const indexType = getLiteralTypeFromPropertyName(name); - const declaredType = getConstraintForLocation(getIndexedAccessType(parentType, indexType, name), declaration.name); + const declaredType = getConstraintForLocation(getIndexedAccessType(parentType, indexType, name, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, AccessFlags.ExpressionPosition), declaration.name); type = getFlowTypeOfDestructuring(declaration, declaredType); } } @@ -7808,7 +7809,7 @@ namespace ts { // This elementType will be used if the specific property corresponding to this index is not // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). - const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring, parentType, undefinedType, pattern); + const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring | (declaration.dotDotDotToken ? 0 : IterationUse.PossiblyOutOfBounds), parentType, undefinedType, pattern); const index = pattern.elements.indexOf(declaration); if (declaration.dotDotDotToken) { // If the parent is a tuple type, the rest element has a tuple type of the @@ -7821,7 +7822,7 @@ namespace ts { else if (isArrayLikeType(parentType)) { const indexType = getLiteralType(index); const accessFlags = hasDefaultValue(declaration) ? AccessFlags.NoTupleBoundsCheck : 0; - const declaredType = getConstraintForLocation(getIndexedAccessTypeOrUndefined(parentType, indexType, declaration.name, accessFlags) || errorType, declaration.name); + const declaredType = getConstraintForLocation(getIndexedAccessTypeOrUndefined(parentType, indexType, declaration.name, accessFlags | AccessFlags.ExpressionPosition) || errorType, declaration.name); type = getFlowTypeOfDestructuring(declaration, declaredType); } else { @@ -13740,8 +13741,8 @@ namespace ts { return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper); } - function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type { - return getIndexedAccessTypeOrUndefined(objectType, indexType, accessNode, AccessFlags.None, aliasSymbol, aliasTypeArguments) || (accessNode ? errorType : unknownType); + function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[], accessFlags = AccessFlags.None): Type { + return getIndexedAccessTypeOrUndefined(objectType, indexType, accessNode, accessFlags, aliasSymbol, aliasTypeArguments) || (accessNode ? errorType : unknownType); } function indexTypeLessThan(indexType: Type, limit: number) { @@ -20478,17 +20479,24 @@ namespace ts { if (!isTypeUsableAsPropertyName(nameType)) return errorType; const text = getPropertyNameFromType(nameType); return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) || - isNumericLiteralName(text) && getIndexTypeOfType(type, IndexKind.Number) || - getIndexTypeOfType(type, IndexKind.String) || + isNumericLiteralName(text) && includeUndefinedInPedanticIndexSignature(getIndexTypeOfType(type, IndexKind.Number)) || + includeUndefinedInPedanticIndexSignature(getIndexTypeOfType(type, IndexKind.String)) || errorType; } function getTypeOfDestructuredArrayElement(type: Type, index: number) { return everyType(type, isTupleLikeType) && getTupleElementType(type, index) || - checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined) || + includeUndefinedInPedanticIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) || errorType; } + function includeUndefinedInPedanticIndexSignature(type: Type | undefined): Type | undefined { + if (!type) return type; + return compilerOptions.pedanticIndexSignatures ? + getUnionType([type, undefinedType]) : + type; + } + function getTypeOfDestructuredSpreadExpression(type: Type) { return createArrayType(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined) || errorType); } @@ -29133,7 +29141,7 @@ namespace ts { checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop); } } - const elementType = getIndexedAccessType(objectLiteralType, exprType, name); + const elementType = getIndexedAccessType(objectLiteralType, exprType, name, undefined, undefined, AccessFlags.ExpressionPosition); const type = getFlowTypeOfDestructuring(property, elementType); return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type); } @@ -29171,9 +29179,14 @@ namespace ts { // This elementType will be used if the specific property corresponding to this index is not // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). - const elementType = checkIteratedTypeOrElementType(IterationUse.Destructuring, sourceType, undefinedType, node) || errorType; + const possiblyOutOfBoundsType = checkIteratedTypeOrElementType(IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, sourceType, undefinedType, node) || errorType; + let inBoundsType: Type | undefined = compilerOptions.pedanticIndexSignatures ? undefined: possiblyOutOfBoundsType; for (let i = 0; i < elements.length; i++) { - checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, checkMode); + let type = possiblyOutOfBoundsType; + if (node.elements[i].kind === SyntaxKind.SpreadElement) { + type = inBoundsType = inBoundsType ?? (checkIteratedTypeOrElementType(IterationUse.Destructuring, sourceType, undefinedType, node) || errorType); + } + checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, type, checkMode); } return sourceType; } @@ -29188,7 +29201,7 @@ namespace ts { if (isArrayLikeType(sourceType)) { // We create a synthetic expression so that getIndexedAccessType doesn't get confused // when the element is a SyntaxKind.ElementAccessExpression. - const accessFlags = hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0; + const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0); const elementType = getIndexedAccessTypeOrUndefined(sourceType, indexType, createSyntheticExpression(element, indexType), accessFlags) || errorType; const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) : elementType; const type = getFlowTypeOfDestructuring(element, assignedType); @@ -33400,6 +33413,7 @@ namespace ts { const uplevelIteration = languageVersion >= ScriptTarget.ES2015; const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; + const possibleOutOfBounds = compilerOptions.pedanticIndexSignatures && !!(use & IterationUse.PossiblyOutOfBounds); // Get the iterated type of an `Iterable` or `IterableIterator` only in ES2015 // or higher, when inside of an async generator or for-await-if, or when @@ -33421,7 +33435,7 @@ namespace ts { } } if (iterationTypes || uplevelIteration) { - return iterationTypes && iterationTypes.yieldType; + return possibleOutOfBounds ? includeUndefinedInPedanticIndexSignature(iterationTypes && iterationTypes.yieldType) : (iterationTypes && iterationTypes.yieldType); } } @@ -33458,7 +33472,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. if (arrayType.flags & TypeFlags.Never) { - return stringType; + return possibleOutOfBounds ? includeUndefinedInPedanticIndexSignature(stringType) : stringType; } } } @@ -33488,20 +33502,20 @@ namespace ts { defaultDiagnostic, typeToString(arrayType)); } - return hasStringConstituent ? stringType : undefined; + return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInPedanticIndexSignature(stringType) : stringType : undefined; } const arrayElementType = getIndexTypeOfType(arrayType, IndexKind.Number); if (hasStringConstituent && arrayElementType) { // This is just an optimization for the case where arrayOrStringType is string | string[] - if (arrayElementType.flags & TypeFlags.StringLike) { + if (arrayElementType.flags & TypeFlags.StringLike && !compilerOptions.pedanticIndexSignatures) { return stringType; } - return getUnionType([arrayElementType, stringType], UnionReduction.Subtype); + return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], UnionReduction.Subtype); } - return arrayElementType; + return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInPedanticIndexSignature(arrayElementType) : arrayElementType; } /** diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt b/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt new file mode 100644 index 0000000000000..b088592e60db4 --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt @@ -0,0 +1,106 @@ +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(8,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(12,9): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(16,9): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(23,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(26,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(34,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(41,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(50,2): error TS2322: Type 'string | undefined' is not assignable to type 'string'. + Type 'undefined' is not assignable to type 'string'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(57,8): error TS2322: Type 'number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(57,11): error TS2322: Type 'number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(60,8): error TS2322: Type 'number | undefined' is not assignable to type 'number'. + Type 'undefined' is not assignable to type 'number'. + + +==== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts (11 errors) ==== + declare const strArray: string[]; + declare const strStrTuple: [string, string]; + + // Declaration forms for array destructuring + + // Destructuring from a simple array -> include undefined + const [s1] = strArray; + s1.toString(); // Should error, s1 possibly undefined + ~~ +!!! error TS2532: Object is possibly 'undefined'. + + // Destructuring a rest element -> do not include undefined + const [...s2] = strArray; + s2.push(undefined); // Should error, 'undefined' not part of s2's element type + ~~~~~~~~~ +!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. + + // Destructuring a rest element -> do not include undefined + const [, , ...s3] = strArray; + s3.push(undefined); // Should error, 'undefined' not part of s2's element type + ~~~~~~~~~ +!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. + + // Declaration forms for object destructuring + + declare const strMap: { [s: string]: string }; + + const { t1 } = strMap; + t1.toString(); // Should error, t1 possibly undefined + ~~ +!!! error TS2532: Object is possibly 'undefined'. + + const { ...t2 } = strMap; + t2.z.toString(); // Should error + ~~~~ +!!! error TS2532: Object is possibly 'undefined'. + + // Test intersections with declared properties + declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; + { + const { x, y, z } = numMapPoint; + x.toFixed(); // Should OK + y.toFixed(); // Should OK + z.toFixed(); // Should error + ~ +!!! error TS2532: Object is possibly 'undefined'. + } + + { + const { x, ...q } = numMapPoint; + x.toFixed(); // Should OK + q.y.toFixed(); // Should OK + q.z.toFixed(); // Should error + ~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + + + declare let target_string: string; + declare let target_string_undef: string | undefined; + declare let target_string_arr: string[]; + + // Assignment forms + [target_string] = strArray; // Should error + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'. +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. + [target_string_undef] = strArray; // Should OK + [,,, ...target_string_arr] = strArray; // Should OK + + { + let x: number, y: number, z: number | undefined; + // TODO: This doesn't work yet + ({ x, y, z } = numMapPoint); // Should OK + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. + + let q: number; + ({ q } = numMapPoint); // Should error + ~ +!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. +!!! error TS2322: Type 'undefined' is not assignable to type 'number'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.js b/tests/baselines/reference/pedanticIndexSignatureDestructuring.js new file mode 100644 index 0000000000000..c8276dc8abfd4 --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.js @@ -0,0 +1,114 @@ +//// [pedanticIndexSignatureDestructuring.ts] +declare const strArray: string[]; +declare const strStrTuple: [string, string]; + +// Declaration forms for array destructuring + +// Destructuring from a simple array -> include undefined +const [s1] = strArray; +s1.toString(); // Should error, s1 possibly undefined + +// Destructuring a rest element -> do not include undefined +const [...s2] = strArray; +s2.push(undefined); // Should error, 'undefined' not part of s2's element type + +// Destructuring a rest element -> do not include undefined +const [, , ...s3] = strArray; +s3.push(undefined); // Should error, 'undefined' not part of s2's element type + +// Declaration forms for object destructuring + +declare const strMap: { [s: string]: string }; + +const { t1 } = strMap; +t1.toString(); // Should error, t1 possibly undefined + +const { ...t2 } = strMap; +t2.z.toString(); // Should error + +// Test intersections with declared properties +declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; +{ + const { x, y, z } = numMapPoint; + x.toFixed(); // Should OK + y.toFixed(); // Should OK + z.toFixed(); // Should error +} + +{ + const { x, ...q } = numMapPoint; + x.toFixed(); // Should OK + q.y.toFixed(); // Should OK + q.z.toFixed(); // Should error +} + + +declare let target_string: string; +declare let target_string_undef: string | undefined; +declare let target_string_arr: string[]; + +// Assignment forms +[target_string] = strArray; // Should error +[target_string_undef] = strArray; // Should OK +[,,, ...target_string_arr] = strArray; // Should OK + +{ + let x: number, y: number, z: number | undefined; + // TODO: This doesn't work yet + ({ x, y, z } = numMapPoint); // Should OK + + let q: number; + ({ q } = numMapPoint); // Should error +} + + +//// [pedanticIndexSignatureDestructuring.js] +"use strict"; +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { + if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) + t[p[i]] = s[p[i]]; + } + return t; +}; +// Declaration forms for array destructuring +// Destructuring from a simple array -> include undefined +var s1 = strArray[0]; +s1.toString(); // Should error, s1 possibly undefined +// Destructuring a rest element -> do not include undefined +var s2 = strArray.slice(0); +s2.push(undefined); // Should error, 'undefined' not part of s2's element type +// Destructuring a rest element -> do not include undefined +var s3 = strArray.slice(2); +s3.push(undefined); // Should error, 'undefined' not part of s2's element type +var t1 = strMap.t1; +t1.toString(); // Should error, t1 possibly undefined +var t2 = __rest(strMap, []); +t2.z.toString(); // Should error +{ + var x = numMapPoint.x, y = numMapPoint.y, z = numMapPoint.z; + x.toFixed(); // Should OK + y.toFixed(); // Should OK + z.toFixed(); // Should error +} +{ + var x = numMapPoint.x, q = __rest(numMapPoint, ["x"]); + x.toFixed(); // Should OK + q.y.toFixed(); // Should OK + q.z.toFixed(); // Should error +} +// Assignment forms +target_string = strArray[0]; // Should error +target_string_undef = strArray[0]; // Should OK +target_string_arr = strArray.slice(3); // Should OK +{ + var x = void 0, y = void 0, z = void 0; + // TODO: This doesn't work yet + (x = numMapPoint.x, y = numMapPoint.y, z = numMapPoint.z); // Should OK + var q = void 0; + (q = numMapPoint.q); // Should error +} diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols b/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols new file mode 100644 index 0000000000000..e12e64b7871e5 --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols @@ -0,0 +1,162 @@ +=== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts === +declare const strArray: string[]; +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +declare const strStrTuple: [string, string]; +>strStrTuple : Symbol(strStrTuple, Decl(pedanticIndexSignatureDestructuring.ts, 1, 13)) + +// Declaration forms for array destructuring + +// Destructuring from a simple array -> include undefined +const [s1] = strArray; +>s1 : Symbol(s1, Decl(pedanticIndexSignatureDestructuring.ts, 6, 7)) +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +s1.toString(); // Should error, s1 possibly undefined +>s1.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>s1 : Symbol(s1, Decl(pedanticIndexSignatureDestructuring.ts, 6, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + +// Destructuring a rest element -> do not include undefined +const [...s2] = strArray; +>s2 : Symbol(s2, Decl(pedanticIndexSignatureDestructuring.ts, 10, 7)) +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +s2.push(undefined); // Should error, 'undefined' not part of s2's element type +>s2.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>s2 : Symbol(s2, Decl(pedanticIndexSignatureDestructuring.ts, 10, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>undefined : Symbol(undefined) + +// Destructuring a rest element -> do not include undefined +const [, , ...s3] = strArray; +>s3 : Symbol(s3, Decl(pedanticIndexSignatureDestructuring.ts, 14, 10)) +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +s3.push(undefined); // Should error, 'undefined' not part of s2's element type +>s3.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>s3 : Symbol(s3, Decl(pedanticIndexSignatureDestructuring.ts, 14, 10)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>undefined : Symbol(undefined) + +// Declaration forms for object destructuring + +declare const strMap: { [s: string]: string }; +>strMap : Symbol(strMap, Decl(pedanticIndexSignatureDestructuring.ts, 19, 13)) +>s : Symbol(s, Decl(pedanticIndexSignatureDestructuring.ts, 19, 25)) + +const { t1 } = strMap; +>t1 : Symbol(t1, Decl(pedanticIndexSignatureDestructuring.ts, 21, 7)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatureDestructuring.ts, 19, 13)) + +t1.toString(); // Should error, t1 possibly undefined +>t1.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>t1 : Symbol(t1, Decl(pedanticIndexSignatureDestructuring.ts, 21, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + +const { ...t2 } = strMap; +>t2 : Symbol(t2, Decl(pedanticIndexSignatureDestructuring.ts, 24, 7)) +>strMap : Symbol(strMap, Decl(pedanticIndexSignatureDestructuring.ts, 19, 13)) + +t2.z.toString(); // Should error +>t2.z.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>t2 : Symbol(t2, Decl(pedanticIndexSignatureDestructuring.ts, 24, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + +// Test intersections with declared properties +declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; +>numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 28, 28)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 28, 39)) +>s : Symbol(s, Decl(pedanticIndexSignatureDestructuring.ts, 28, 56)) +{ + const { x, y, z } = numMapPoint; +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 30, 11)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 30, 14)) +>z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 30, 17)) +>numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) + + x.toFixed(); // Should OK +>x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 30, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + y.toFixed(); // Should OK +>y.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 30, 14)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + z.toFixed(); // Should error +>z.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 30, 17)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + +{ + const { x, ...q } = numMapPoint; +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 37, 11)) +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 37, 14)) +>numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) + + x.toFixed(); // Should OK +>x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 37, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + q.y.toFixed(); // Should OK +>q.y.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>q.y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 28, 39)) +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 37, 14)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 28, 39)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + q.z.toFixed(); // Should error +>q.z.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 37, 14)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + + +declare let target_string: string; +>target_string : Symbol(target_string, Decl(pedanticIndexSignatureDestructuring.ts, 44, 11)) + +declare let target_string_undef: string | undefined; +>target_string_undef : Symbol(target_string_undef, Decl(pedanticIndexSignatureDestructuring.ts, 45, 11)) + +declare let target_string_arr: string[]; +>target_string_arr : Symbol(target_string_arr, Decl(pedanticIndexSignatureDestructuring.ts, 46, 11)) + +// Assignment forms +[target_string] = strArray; // Should error +>target_string : Symbol(target_string, Decl(pedanticIndexSignatureDestructuring.ts, 44, 11)) +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +[target_string_undef] = strArray; // Should OK +>target_string_undef : Symbol(target_string_undef, Decl(pedanticIndexSignatureDestructuring.ts, 45, 11)) +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +[,,, ...target_string_arr] = strArray; // Should OK +>target_string_arr : Symbol(target_string_arr, Decl(pedanticIndexSignatureDestructuring.ts, 46, 11)) +>strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) + +{ + let x: number, y: number, z: number | undefined; +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 54, 7)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 54, 18)) +>z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 54, 29)) + + // TODO: This doesn't work yet + ({ x, y, z } = numMapPoint); // Should OK +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 56, 6)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 56, 9)) +>z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 56, 12)) +>numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) + + let q: number; +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 58, 7)) + + ({ q } = numMapPoint); // Should error +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 59, 6)) +>numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) +} + diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.types b/tests/baselines/reference/pedanticIndexSignatureDestructuring.types new file mode 100644 index 0000000000000..0d81ea563e7bb --- /dev/null +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.types @@ -0,0 +1,195 @@ +=== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts === +declare const strArray: string[]; +>strArray : string[] + +declare const strStrTuple: [string, string]; +>strStrTuple : [string, string] + +// Declaration forms for array destructuring + +// Destructuring from a simple array -> include undefined +const [s1] = strArray; +>s1 : string | undefined +>strArray : string[] + +s1.toString(); // Should error, s1 possibly undefined +>s1.toString() : string +>s1.toString : () => string +>s1 : string | undefined +>toString : () => string + +// Destructuring a rest element -> do not include undefined +const [...s2] = strArray; +>s2 : string[] +>strArray : string[] + +s2.push(undefined); // Should error, 'undefined' not part of s2's element type +>s2.push(undefined) : number +>s2.push : (...items: string[]) => number +>s2 : string[] +>push : (...items: string[]) => number +>undefined : undefined + +// Destructuring a rest element -> do not include undefined +const [, , ...s3] = strArray; +> : undefined +> : undefined +>s3 : string[] +>strArray : string[] + +s3.push(undefined); // Should error, 'undefined' not part of s2's element type +>s3.push(undefined) : number +>s3.push : (...items: string[]) => number +>s3 : string[] +>push : (...items: string[]) => number +>undefined : undefined + +// Declaration forms for object destructuring + +declare const strMap: { [s: string]: string }; +>strMap : { [s: string]: string; } +>s : string + +const { t1 } = strMap; +>t1 : string | undefined +>strMap : { [s: string]: string; } + +t1.toString(); // Should error, t1 possibly undefined +>t1.toString() : string +>t1.toString : () => string +>t1 : string | undefined +>toString : () => string + +const { ...t2 } = strMap; +>t2 : { [s: string]: string; } +>strMap : { [s: string]: string; } + +t2.z.toString(); // Should error +>t2.z.toString() : string +>t2.z.toString : () => string +>t2.z : string | undefined +>t2 : { [s: string]: string; } +>z : string | undefined +>toString : () => string + +// Test intersections with declared properties +declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; +>numMapPoint : { x: number; y: number; } & { [s: string]: number; } +>x : number +>y : number +>s : string +{ + const { x, y, z } = numMapPoint; +>x : number | undefined +>y : number | undefined +>z : number | undefined +>numMapPoint : { x: number; y: number; } & { [s: string]: number; } + + x.toFixed(); // Should OK +>x.toFixed() : string +>x.toFixed : (fractionDigits?: number | undefined) => string +>x : number +>toFixed : (fractionDigits?: number | undefined) => string + + y.toFixed(); // Should OK +>y.toFixed() : string +>y.toFixed : (fractionDigits?: number | undefined) => string +>y : number +>toFixed : (fractionDigits?: number | undefined) => string + + z.toFixed(); // Should error +>z.toFixed() : string +>z.toFixed : (fractionDigits?: number | undefined) => string +>z : number | undefined +>toFixed : (fractionDigits?: number | undefined) => string +} + +{ + const { x, ...q } = numMapPoint; +>x : number | undefined +>q : { [s: string]: number; y: number; } +>numMapPoint : { x: number; y: number; } & { [s: string]: number; } + + x.toFixed(); // Should OK +>x.toFixed() : string +>x.toFixed : (fractionDigits?: number | undefined) => string +>x : number +>toFixed : (fractionDigits?: number | undefined) => string + + q.y.toFixed(); // Should OK +>q.y.toFixed() : string +>q.y.toFixed : (fractionDigits?: number | undefined) => string +>q.y : number +>q : { [s: string]: number; y: number; } +>y : number +>toFixed : (fractionDigits?: number | undefined) => string + + q.z.toFixed(); // Should error +>q.z.toFixed() : string +>q.z.toFixed : (fractionDigits?: number | undefined) => string +>q.z : number | undefined +>q : { [s: string]: number; y: number; } +>z : number | undefined +>toFixed : (fractionDigits?: number | undefined) => string +} + + +declare let target_string: string; +>target_string : string + +declare let target_string_undef: string | undefined; +>target_string_undef : string | undefined + +declare let target_string_arr: string[]; +>target_string_arr : string[] + +// Assignment forms +[target_string] = strArray; // Should error +>[target_string] = strArray : string[] +>[target_string] : [string] +>target_string : string +>strArray : string[] + +[target_string_undef] = strArray; // Should OK +>[target_string_undef] = strArray : string[] +>[target_string_undef] : [string | undefined] +>target_string_undef : string | undefined +>strArray : string[] + +[,,, ...target_string_arr] = strArray; // Should OK +>[,,, ...target_string_arr] = strArray : string[] +>[,,, ...target_string_arr] : [undefined, undefined, undefined, ...string[]] +> : undefined +> : undefined +> : undefined +>...target_string_arr : string +>target_string_arr : string[] +>strArray : string[] + +{ + let x: number, y: number, z: number | undefined; +>x : number +>y : number +>z : number | undefined + + // TODO: This doesn't work yet + ({ x, y, z } = numMapPoint); // Should OK +>({ x, y, z } = numMapPoint) : { x: number; y: number; } & { [s: string]: number; } +>{ x, y, z } = numMapPoint : { x: number; y: number; } & { [s: string]: number; } +>{ x, y, z } : { x: number; y: number; z: number | undefined; } +>x : number +>y : number +>z : number | undefined +>numMapPoint : { x: number; y: number; } & { [s: string]: number; } + + let q: number; +>q : number + + ({ q } = numMapPoint); // Should error +>({ q } = numMapPoint) : { x: number; y: number; } & { [s: string]: number; } +>{ q } = numMapPoint : { x: number; y: number; } & { [s: string]: number; } +>{ q } : { q: number; } +>q : number +>numMapPoint : { x: number; y: number; } & { [s: string]: number; } +} + diff --git a/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts b/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts new file mode 100644 index 0000000000000..249b669ac0208 --- /dev/null +++ b/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts @@ -0,0 +1,64 @@ +// @strict: true +// @pedanticIndexSignatures: true + +declare const strArray: string[]; +declare const strStrTuple: [string, string]; + +// Declaration forms for array destructuring + +// Destructuring from a simple array -> include undefined +const [s1] = strArray; +s1.toString(); // Should error, s1 possibly undefined + +// Destructuring a rest element -> do not include undefined +const [...s2] = strArray; +s2.push(undefined); // Should error, 'undefined' not part of s2's element type + +// Destructuring a rest element -> do not include undefined +const [, , ...s3] = strArray; +s3.push(undefined); // Should error, 'undefined' not part of s2's element type + +// Declaration forms for object destructuring + +declare const strMap: { [s: string]: string }; + +const { t1 } = strMap; +t1.toString(); // Should error, t1 possibly undefined + +const { ...t2 } = strMap; +t2.z.toString(); // Should error + +// Test intersections with declared properties +declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; +{ + const { x, y, z } = numMapPoint; + x.toFixed(); // Should OK + y.toFixed(); // Should OK + z.toFixed(); // Should error +} + +{ + const { x, ...q } = numMapPoint; + x.toFixed(); // Should OK + q.y.toFixed(); // Should OK + q.z.toFixed(); // Should error +} + + +declare let target_string: string; +declare let target_string_undef: string | undefined; +declare let target_string_arr: string[]; + +// Assignment forms +[target_string] = strArray; // Should error +[target_string_undef] = strArray; // Should OK +[,,, ...target_string_arr] = strArray; // Should OK + +{ + let x: number, y: number, z: number | undefined; + // TODO: This doesn't work yet + ({ x, y, z } = numMapPoint); // Should OK + + let q: number; + ({ q } = numMapPoint); // Should error +} From 6218d975e7271e1cbfe524fa387712e20b3df6bb Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Sun, 12 Jul 2020 21:03:42 -0700 Subject: [PATCH 4/9] lint --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a929e30da622a..e930ca1a56889 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -29141,7 +29141,7 @@ namespace ts { checkPropertyAccessibility(property, /*isSuper*/ false, objectLiteralType, prop); } } - const elementType = getIndexedAccessType(objectLiteralType, exprType, name, undefined, undefined, AccessFlags.ExpressionPosition); + const elementType = getIndexedAccessType(objectLiteralType, exprType, name, /*aliasSymbol*/ undefined, /*aliasTypeArguments*/ undefined, AccessFlags.ExpressionPosition); const type = getFlowTypeOfDestructuring(property, elementType); return checkDestructuringAssignment(property.kind === SyntaxKind.ShorthandPropertyAssignment ? property : property.initializer, type); } From 186d9d358ce87e92cec7cd9b2399751886efc988 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 2 Sep 2020 12:49:21 -0700 Subject: [PATCH 5/9] Fix destructuring assignment and element access into known properties --- src/compiler/checker.ts | 17 +++++++++-------- ...danticIndexSignatureDestructuring.errors.txt | 15 ++------------- .../pedanticIndexSignatureDestructuring.js | 2 -- .../pedanticIndexSignatureDestructuring.symbols | 11 +++++------ .../pedanticIndexSignatureDestructuring.types | 7 +++---- .../pedanticIndexSignatureDestructuring.ts | 1 - .../pedantic/pedanticIndexSignatures.ts | 9 +++++++++ 7 files changed, 28 insertions(+), 34 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e930ca1a56889..4fab22efc03b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13493,13 +13493,16 @@ namespace ts { } return undefined; } + const shouldIncludeUndefined = + compilerOptions.pedanticIndexSignatures && + (accessFlags & (AccessFlags.Writing | AccessFlags.ExpressionPosition)) === AccessFlags.ExpressionPosition; if (accessNode && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { const indexNode = getIndexNodeForAccessExpression(accessNode); error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType)); - return indexInfo.type; + return shouldIncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; } errorIfWritingToReadonlyIndex(indexInfo); - return indexInfo.type; + return shouldIncludeUndefined ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; } if (indexType.flags & TypeFlags.Never) { return neverType; @@ -13817,13 +13820,11 @@ namespace ts { if (wasMissingProp) { return undefined; } - return accessFlags & AccessFlags.Writing ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments) : - shouldIncludeUndefined ? - getUnionType([getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments), undefinedType]) : - getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments); + return accessFlags & AccessFlags.Writing + ? getIntersectionType(propTypes, aliasSymbol, aliasTypeArguments) + : getUnionType(propTypes, UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } - const type = getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, /* supressNoImplicitAnyError */ false, accessNode, accessFlags | AccessFlags.CacheSymbol, /* reportDeprecated */ true); - return type && (shouldIncludeUndefined ? getUnionType([type, undefinedType]) : type); + return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, indexType, /* supressNoImplicitAnyError */ false, accessNode, accessFlags | AccessFlags.CacheSymbol, /* reportDeprecated */ true); } function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) { diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt b/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt index b088592e60db4..4a4430e2cd9a0 100644 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt @@ -7,15 +7,11 @@ tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(34,5): e tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(41,5): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(50,2): error TS2322: Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(57,8): error TS2322: Type 'number | undefined' is not assignable to type 'number'. - Type 'undefined' is not assignable to type 'number'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(57,11): error TS2322: Type 'number | undefined' is not assignable to type 'number'. - Type 'undefined' is not assignable to type 'number'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(60,8): error TS2322: Type 'number | undefined' is not assignable to type 'number'. +tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(59,8): error TS2322: Type 'number | undefined' is not assignable to type 'number'. Type 'undefined' is not assignable to type 'number'. -==== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts (11 errors) ==== +==== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts (9 errors) ==== declare const strArray: string[]; declare const strStrTuple: [string, string]; @@ -88,14 +84,7 @@ tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(60,8): e { let x: number, y: number, z: number | undefined; - // TODO: This doesn't work yet ({ x, y, z } = numMapPoint); // Should OK - ~ -!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. -!!! error TS2322: Type 'undefined' is not assignable to type 'number'. - ~ -!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. -!!! error TS2322: Type 'undefined' is not assignable to type 'number'. let q: number; ({ q } = numMapPoint); // Should error diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.js b/tests/baselines/reference/pedanticIndexSignatureDestructuring.js index c8276dc8abfd4..678444b58dfa0 100644 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.js +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.js @@ -54,7 +54,6 @@ declare let target_string_arr: string[]; { let x: number, y: number, z: number | undefined; - // TODO: This doesn't work yet ({ x, y, z } = numMapPoint); // Should OK let q: number; @@ -107,7 +106,6 @@ target_string_undef = strArray[0]; // Should OK target_string_arr = strArray.slice(3); // Should OK { var x = void 0, y = void 0, z = void 0; - // TODO: This doesn't work yet (x = numMapPoint.x, y = numMapPoint.y, z = numMapPoint.z); // Should OK var q = void 0; (q = numMapPoint.q); // Should error diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols b/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols index e12e64b7871e5..b1c16aafe7fa2 100644 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols @@ -145,18 +145,17 @@ declare let target_string_arr: string[]; >y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 54, 18)) >z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 54, 29)) - // TODO: This doesn't work yet ({ x, y, z } = numMapPoint); // Should OK ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 56, 6)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 56, 9)) ->z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 56, 12)) +>x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 55, 6)) +>y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 55, 9)) +>z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 55, 12)) >numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) let q: number; ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 58, 7)) +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 57, 7)) ({ q } = numMapPoint); // Should error ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 59, 6)) +>q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 58, 6)) >numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) } diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.types b/tests/baselines/reference/pedanticIndexSignatureDestructuring.types index 0d81ea563e7bb..53506355e9576 100644 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.types +++ b/tests/baselines/reference/pedanticIndexSignatureDestructuring.types @@ -80,8 +80,8 @@ declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; >s : string { const { x, y, z } = numMapPoint; ->x : number | undefined ->y : number | undefined +>x : number +>y : number >z : number | undefined >numMapPoint : { x: number; y: number; } & { [s: string]: number; } @@ -106,7 +106,7 @@ declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; { const { x, ...q } = numMapPoint; ->x : number | undefined +>x : number >q : { [s: string]: number; y: number; } >numMapPoint : { x: number; y: number; } & { [s: string]: number; } @@ -172,7 +172,6 @@ declare let target_string_arr: string[]; >y : number >z : number | undefined - // TODO: This doesn't work yet ({ x, y, z } = numMapPoint); // Should OK >({ x, y, z } = numMapPoint) : { x: number; y: number; } & { [s: string]: number; } >{ x, y, z } = numMapPoint : { x: number; y: number; } & { [s: string]: number; } diff --git a/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts b/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts index 249b669ac0208..b67912f9deeee 100644 --- a/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts +++ b/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts @@ -56,7 +56,6 @@ declare let target_string_arr: string[]; { let x: number, y: number, z: number | undefined; - // TODO: This doesn't work yet ({ x, y, z } = numMapPoint); // Should OK let q: number; diff --git a/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts b/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts index 70d53d9b2cd2c..364702de9b6cb 100644 --- a/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts +++ b/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts @@ -66,6 +66,15 @@ function generic3(arg: T): boolean { return strMap[arg]; } +// Element access into known properties is ok +declare const obj1: { x: string, y: number, [key: string]: string | number }; +obj1["x"]; +const y = "y"; +obj1[y]; +let yy = "y"; +obj1[yy]; +let z = "z"; +obj1[z]; // Distributivity cases declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; From 8366df30e7feaeb2756fe281792ee6abb0ce1938 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Wed, 2 Sep 2020 13:07:45 -0700 Subject: [PATCH 6/9] Update baselines --- .../pedanticIndexSignatures.errors.txt | 11 ++++- .../reference/pedanticIndexSignatures.js | 16 ++++++++ .../reference/pedanticIndexSignatures.symbols | 41 ++++++++++++++++--- .../reference/pedanticIndexSignatures.types | 38 +++++++++++++++++ 4 files changed, 100 insertions(+), 6 deletions(-) diff --git a/tests/baselines/reference/pedanticIndexSignatures.errors.txt b/tests/baselines/reference/pedanticIndexSignatures.errors.txt index 68dc2a7668948..45d859ea78f1a 100644 --- a/tests/baselines/reference/pedanticIndexSignatures.errors.txt +++ b/tests/baselines/reference/pedanticIndexSignatures.errors.txt @@ -46,7 +46,7 @@ tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(55,5): error TS2322: Type 'undefined' is not assignable to type 'boolean'. tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(63,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(70,7): error TS2322: Type 'number | boolean | undefined' is not assignable to type 'number | boolean'. +tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(79,7): error TS2322: Type 'number | boolean | undefined' is not assignable to type 'number | boolean'. Type 'undefined' is not assignable to type 'number | boolean'. @@ -190,6 +190,15 @@ tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(70,7): error TS2322: !!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. } + // Element access into known properties is ok + declare const obj1: { x: string, y: number, [key: string]: string | number }; + obj1["x"]; + const y = "y"; + obj1[y]; + let yy = "y"; + obj1[yy]; + let z = "z"; + obj1[z]; // Distributivity cases declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; diff --git a/tests/baselines/reference/pedanticIndexSignatures.js b/tests/baselines/reference/pedanticIndexSignatures.js index c59c93a84818d..bdc49d7afced7 100644 --- a/tests/baselines/reference/pedanticIndexSignatures.js +++ b/tests/baselines/reference/pedanticIndexSignatures.js @@ -64,6 +64,15 @@ function generic3(arg: T): boolean { return strMap[arg]; } +// Element access into known properties is ok +declare const obj1: { x: string, y: number, [key: string]: string | number }; +obj1["x"]; +const y = "y"; +obj1[y]; +let yy = "y"; +obj1[yy]; +let z = "z"; +obj1[z]; // Distributivity cases declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; @@ -133,5 +142,12 @@ function generic3(arg) { // Should error return strMap[arg]; } +obj1["x"]; +var y = "y"; +obj1[y]; +var yy = "y"; +obj1[yy]; +var z = "z"; +obj1[z]; // Should error var f1 = strMapUnion["foo"]; diff --git a/tests/baselines/reference/pedanticIndexSignatures.symbols b/tests/baselines/reference/pedanticIndexSignatures.symbols index 4741dd75ec57d..6c28f683317b2 100644 --- a/tests/baselines/reference/pedanticIndexSignatures.symbols +++ b/tests/baselines/reference/pedanticIndexSignatures.symbols @@ -225,16 +225,47 @@ function generic3(arg: T): boolean { >arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 60, 36)) } +// Element access into known properties is ok +declare const obj1: { x: string, y: number, [key: string]: string | number }; +>obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) +>x : Symbol(x, Decl(pedanticIndexSignatures.ts, 66, 21)) +>y : Symbol(y, Decl(pedanticIndexSignatures.ts, 66, 32)) +>key : Symbol(key, Decl(pedanticIndexSignatures.ts, 66, 45)) + +obj1["x"]; +>obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) +>"x" : Symbol(x, Decl(pedanticIndexSignatures.ts, 66, 21)) + +const y = "y"; +>y : Symbol(y, Decl(pedanticIndexSignatures.ts, 68, 5)) + +obj1[y]; +>obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) +>y : Symbol(y, Decl(pedanticIndexSignatures.ts, 68, 5)) + +let yy = "y"; +>yy : Symbol(yy, Decl(pedanticIndexSignatures.ts, 70, 3)) + +obj1[yy]; +>obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) +>yy : Symbol(yy, Decl(pedanticIndexSignatures.ts, 70, 3)) + +let z = "z"; +>z : Symbol(z, Decl(pedanticIndexSignatures.ts, 72, 3)) + +obj1[z]; +>obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) +>z : Symbol(z, Decl(pedanticIndexSignatures.ts, 72, 3)) // Distributivity cases declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; ->strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 67, 13)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 67, 30)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 67, 57)) +>strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 76, 13)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 76, 30)) +>s : Symbol(s, Decl(pedanticIndexSignatures.ts, 76, 57)) // Should error const f1: boolean | number = strMapUnion["foo"]; ->f1 : Symbol(f1, Decl(pedanticIndexSignatures.ts, 69, 5)) ->strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 67, 13)) +>f1 : Symbol(f1, Decl(pedanticIndexSignatures.ts, 78, 5)) +>strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 76, 13)) diff --git a/tests/baselines/reference/pedanticIndexSignatures.types b/tests/baselines/reference/pedanticIndexSignatures.types index 13e1a03b1bf70..2fa9bc420dac7 100644 --- a/tests/baselines/reference/pedanticIndexSignatures.types +++ b/tests/baselines/reference/pedanticIndexSignatures.types @@ -277,6 +277,44 @@ function generic3(arg: T): boolean { >arg : T } +// Element access into known properties is ok +declare const obj1: { x: string, y: number, [key: string]: string | number }; +>obj1 : { [key: string]: string | number; x: string; y: number; } +>x : string +>y : number +>key : string + +obj1["x"]; +>obj1["x"] : string +>obj1 : { [key: string]: string | number; x: string; y: number; } +>"x" : "x" + +const y = "y"; +>y : "y" +>"y" : "y" + +obj1[y]; +>obj1[y] : number +>obj1 : { [key: string]: string | number; x: string; y: number; } +>y : "y" + +let yy = "y"; +>yy : string +>"y" : "y" + +obj1[yy]; +>obj1[yy] : string | number | undefined +>obj1 : { [key: string]: string | number; x: string; y: number; } +>yy : string + +let z = "z"; +>z : string +>"z" : "z" + +obj1[z]; +>obj1[z] : string | number | undefined +>obj1 : { [key: string]: string | number; x: string; y: number; } +>z : string // Distributivity cases declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; From 0f25ce914d3d0e6c8ead00d48ec803213bb77b58 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 10 Sep 2020 09:11:10 -0700 Subject: [PATCH 7/9] Rename flag to unUncheckedIndexedAccess --- src/compiler/checker.ts | 30 +- src/compiler/commandLineParser.ts | 2 +- src/compiler/types.ts | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- .../noUncheckedIndexedAccess.errors.txt | 101 +++++++ ...natures.js => noUncheckedIndexedAccess.js} | 4 +- .../noUncheckedIndexedAccess.symbols | 271 ++++++++++++++++++ ...s.types => noUncheckedIndexedAccess.types} | 60 ++-- ...eckedIndexedAccessDestructuring.errors.txt | 70 +++++ ... noUncheckedIndexedAccessDestructuring.js} | 4 +- ...ncheckedIndexedAccessDestructuring.symbols | 161 +++++++++++ ...UncheckedIndexedAccessDestructuring.types} | 22 +- ...nticIndexSignatureDestructuring.errors.txt | 95 ------ ...edanticIndexSignatureDestructuring.symbols | 161 ----------- .../pedanticIndexSignatures.errors.txt | 211 -------------- .../reference/pedanticIndexSignatures.symbols | 271 ------------------ .../noUncheckedIndexedAccess/tsconfig.json | 5 + .../pedanticIndexSignatures/tsconfig.json | 5 - .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../tsconfig.json | 2 +- .../declarationDir-is-specified.js | 2 +- ...-outDir-and-declarationDir-is-specified.js | 2 +- .../when-outDir-is-specified.js | 2 +- .../with-outFile.js | 2 +- ...e-is-specified-with-declaration-enabled.js | 2 +- .../without-outDir-or-outFile-is-specified.js | 2 +- ...natures.ts => noUncheckedIndexedAccess.ts} | 2 +- ... noUncheckedIndexedAccessDestructuring.ts} | 2 +- 36 files changed, 689 insertions(+), 824 deletions(-) create mode 100644 tests/baselines/reference/noUncheckedIndexedAccess.errors.txt rename tests/baselines/reference/{pedanticIndexSignatures.js => noUncheckedIndexedAccess.js} (96%) create mode 100644 tests/baselines/reference/noUncheckedIndexedAccess.symbols rename tests/baselines/reference/{pedanticIndexSignatures.types => noUncheckedIndexedAccess.types} (81%) create mode 100644 tests/baselines/reference/noUncheckedIndexedAccessDestructuring.errors.txt rename tests/baselines/reference/{pedanticIndexSignatureDestructuring.js => noUncheckedIndexedAccessDestructuring.js} (95%) create mode 100644 tests/baselines/reference/noUncheckedIndexedAccessDestructuring.symbols rename tests/baselines/reference/{pedanticIndexSignatureDestructuring.types => noUncheckedIndexedAccessDestructuring.types} (90%) delete mode 100644 tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt delete mode 100644 tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols delete mode 100644 tests/baselines/reference/pedanticIndexSignatures.errors.txt delete mode 100644 tests/baselines/reference/pedanticIndexSignatures.symbols create mode 100644 tests/baselines/reference/showConfig/Shows tsconfig for single option/noUncheckedIndexedAccess/tsconfig.json delete mode 100644 tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json rename tests/cases/conformance/pedantic/{pedanticIndexSignatures.ts => noUncheckedIndexedAccess.ts} (95%) rename tests/cases/conformance/pedantic/{pedanticIndexSignatureDestructuring.ts => noUncheckedIndexedAccessDestructuring.ts} (94%) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4fab22efc03b9..c4d91dbda59a3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13494,7 +13494,7 @@ namespace ts { return undefined; } const shouldIncludeUndefined = - compilerOptions.pedanticIndexSignatures && + compilerOptions.noUncheckedIndexSignatures && (accessFlags & (AccessFlags.Writing | AccessFlags.ExpressionPosition)) === AccessFlags.ExpressionPosition; if (accessNode && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) { const indexNode = getIndexNodeForAccessExpression(accessNode); @@ -13767,7 +13767,7 @@ namespace ts { } const shouldIncludeUndefined = - compilerOptions.pedanticIndexSignatures && + compilerOptions.noUncheckedIndexSignatures && (accessFlags & (AccessFlags.Writing | AccessFlags.ExpressionPosition)) === AccessFlags.ExpressionPosition; // If the object type has a string index signature and no other members we know that the result will @@ -20480,20 +20480,20 @@ namespace ts { if (!isTypeUsableAsPropertyName(nameType)) return errorType; const text = getPropertyNameFromType(nameType); return getConstraintForLocation(getTypeOfPropertyOfType(type, text), name) || - isNumericLiteralName(text) && includeUndefinedInPedanticIndexSignature(getIndexTypeOfType(type, IndexKind.Number)) || - includeUndefinedInPedanticIndexSignature(getIndexTypeOfType(type, IndexKind.String)) || + isNumericLiteralName(text) && includeUndefinedInIndexSignature(getIndexTypeOfType(type, IndexKind.Number)) || + includeUndefinedInIndexSignature(getIndexTypeOfType(type, IndexKind.String)) || errorType; } function getTypeOfDestructuredArrayElement(type: Type, index: number) { return everyType(type, isTupleLikeType) && getTupleElementType(type, index) || - includeUndefinedInPedanticIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) || + includeUndefinedInIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) || errorType; } - function includeUndefinedInPedanticIndexSignature(type: Type | undefined): Type | undefined { + function includeUndefinedInIndexSignature(type: Type | undefined): Type | undefined { if (!type) return type; - return compilerOptions.pedanticIndexSignatures ? + return compilerOptions.noUncheckedIndexSignatures ? getUnionType([type, undefinedType]) : type; } @@ -25240,7 +25240,7 @@ namespace ts { error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - propType = (compilerOptions.pedanticIndexSignatures && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; + propType = (compilerOptions.noUncheckedIndexSignatures && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; } else { if (prop.valueDeclaration?.flags & NodeFlags.Deprecated && isUncalledFunctionReference(node, prop)) { @@ -29181,7 +29181,7 @@ namespace ts { // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). const possiblyOutOfBoundsType = checkIteratedTypeOrElementType(IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, sourceType, undefinedType, node) || errorType; - let inBoundsType: Type | undefined = compilerOptions.pedanticIndexSignatures ? undefined: possiblyOutOfBoundsType; + let inBoundsType: Type | undefined = compilerOptions.noUncheckedIndexSignatures ? undefined: possiblyOutOfBoundsType; for (let i = 0; i < elements.length; i++) { let type = possiblyOutOfBoundsType; if (node.elements[i].kind === SyntaxKind.SpreadElement) { @@ -33414,7 +33414,7 @@ namespace ts { const uplevelIteration = languageVersion >= ScriptTarget.ES2015; const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; - const possibleOutOfBounds = compilerOptions.pedanticIndexSignatures && !!(use & IterationUse.PossiblyOutOfBounds); + const possibleOutOfBounds = compilerOptions.noUncheckedIndexSignatures && !!(use & IterationUse.PossiblyOutOfBounds); // Get the iterated type of an `Iterable` or `IterableIterator` only in ES2015 // or higher, when inside of an async generator or for-await-if, or when @@ -33436,7 +33436,7 @@ namespace ts { } } if (iterationTypes || uplevelIteration) { - return possibleOutOfBounds ? includeUndefinedInPedanticIndexSignature(iterationTypes && iterationTypes.yieldType) : (iterationTypes && iterationTypes.yieldType); + return possibleOutOfBounds ? includeUndefinedInIndexSignature(iterationTypes && iterationTypes.yieldType) : (iterationTypes && iterationTypes.yieldType); } } @@ -33473,7 +33473,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. if (arrayType.flags & TypeFlags.Never) { - return possibleOutOfBounds ? includeUndefinedInPedanticIndexSignature(stringType) : stringType; + return possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType; } } } @@ -33503,20 +33503,20 @@ namespace ts { defaultDiagnostic, typeToString(arrayType)); } - return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInPedanticIndexSignature(stringType) : stringType : undefined; + return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType : undefined; } const arrayElementType = getIndexTypeOfType(arrayType, IndexKind.Number); if (hasStringConstituent && arrayElementType) { // This is just an optimization for the case where arrayOrStringType is string | string[] - if (arrayElementType.flags & TypeFlags.StringLike && !compilerOptions.pedanticIndexSignatures) { + if (arrayElementType.flags & TypeFlags.StringLike && !compilerOptions.noUncheckedIndexSignatures) { return stringType; } return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], UnionReduction.Subtype); } - return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInPedanticIndexSignature(arrayElementType) : arrayElementType; + return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) : arrayElementType; } /** diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 1e01daa30f83c..3e902b1578231 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -607,7 +607,7 @@ namespace ts { description: Diagnostics.Report_errors_for_fallthrough_cases_in_switch_statement }, { - name: "pedanticIndexSignatures", + name: "noUncheckedIndexedAccess", type: "boolean", affectsSemanticDiagnostics: true, showInSimplifiedHelpView: false, diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 1d3317a455fd9..25683c0242f6a 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -5716,7 +5716,7 @@ namespace ts { outDir?: string; outFile?: string; paths?: MapLike; - pedanticIndexSignatures?: boolean; + noUncheckedIndexSignatures?: boolean; /*@internal*/ plugins?: PluginImport[]; preserveConstEnums?: boolean; preserveSymlinks?: boolean; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index c8336d6d6a0bc..50212b23dbebd 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2800,7 +2800,7 @@ declare namespace ts { outDir?: string; outFile?: string; paths?: MapLike; - pedanticIndexSignatures?: boolean; + noUncheckedIndexSignatures?: boolean; preserveConstEnums?: boolean; preserveSymlinks?: boolean; project?: string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 0c05f502dbb81..47f9a0feb93f1 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2800,7 +2800,7 @@ declare namespace ts { outDir?: string; outFile?: string; paths?: MapLike; - pedanticIndexSignatures?: boolean; + noUncheckedIndexSignatures?: boolean; preserveConstEnums?: boolean; preserveSymlinks?: boolean; project?: string; diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt b/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt new file mode 100644 index 0000000000000..a5fa9ce94e754 --- /dev/null +++ b/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt @@ -0,0 +1,101 @@ +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(3,32): error TS2344: Type 'boolean | undefined' does not satisfy the constraint 'boolean'. + Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(38,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(39,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(40,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(41,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. + + +==== tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts (5 errors) ==== + type CheckBooleanOnly = any; + // Validate CheckBooleanOnly works - should error + type T_ERR1 = CheckBooleanOnly; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2344: Type 'boolean | undefined' does not satisfy the constraint 'boolean'. +!!! error TS2344: Type 'undefined' is not assignable to type 'boolean'. + + enum NumericEnum1 { A, B, C } + enum NumericEnum2 { A = 0, B = 1 , C = 2 } + enum StringEnum1 { A = "Alpha", B = "Beta" } + + declare const strMap: { [s: string]: boolean }; + + // All of these should be errors + const e1: boolean = strMap["foo"]; + const e2: boolean = strMap.bar; + const e3: boolean = strMap[0]; + const e4: boolean = strMap[0 as string | number]; + const e5: boolean = strMap[0 as string | 0 | 1]; + const e6: boolean = strMap[0 as 0 | 1]; + const e7: boolean = strMap["foo" as "foo" | "baz"]; + const e8: boolean = strMap[NumericEnum1.A]; + const e9: boolean = strMap[NumericEnum2.A]; + const e10: boolean = strMap[StringEnum1.A]; + const e11: boolean = strMap[StringEnum1.A as StringEnum1]; + const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; + const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; + const e14: boolean = strMap[null as any]; + + // Should be OK + const ok1: boolean | undefined = strMap["foo"]; + const ok2: boolean | undefined = strMap.bar; + + type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; + type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; + type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; + type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; + type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; + + // Writes don't allow 'undefined'; all should be errors + strMap["baz"] = undefined; + ~~~~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + strMap.qua = undefined; + ~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + strMap[0] = undefined; + ~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + strMap[null as any] = undefined; + ~~~~~~~~~~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. + + // Numeric lookups are unaffected + declare const numMap: { [s: number]: boolean }; + // All of these should be ok + const num_ok1: boolean = numMap[0]; + const num_ok2: boolean = numMap[0 as number]; + const num_ok3: boolean = numMap[0 as 0 | 1]; + const num_ok4: boolean = numMap[NumericEnum1.A]; + const num_ok5: boolean = numMap[NumericEnum2.A]; + + // Generics + function generic1(arg: T): boolean { + // Should error + return arg["blah"]; + } + function generic2(arg: T): boolean { + // Should OK + return arg["blah"]!; + } + function generic3(arg: T): boolean { + // Should error + return strMap[arg]; + } + + // Element access into known properties is ok + declare const obj1: { x: string, y: number, [key: string]: string | number }; + obj1["x"]; + const y = "y"; + obj1[y]; + let yy = "y"; + obj1[yy]; + let z = "z"; + obj1[z]; + + // Distributivity cases + declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; + // Should error + const f1: boolean | number = strMapUnion["foo"]; + + \ No newline at end of file diff --git a/tests/baselines/reference/pedanticIndexSignatures.js b/tests/baselines/reference/noUncheckedIndexedAccess.js similarity index 96% rename from tests/baselines/reference/pedanticIndexSignatures.js rename to tests/baselines/reference/noUncheckedIndexedAccess.js index bdc49d7afced7..5fc004d9c5956 100644 --- a/tests/baselines/reference/pedanticIndexSignatures.js +++ b/tests/baselines/reference/noUncheckedIndexedAccess.js @@ -1,4 +1,4 @@ -//// [pedanticIndexSignatures.ts] +//// [noUncheckedIndexedAccess.ts] type CheckBooleanOnly = any; // Validate CheckBooleanOnly works - should error type T_ERR1 = CheckBooleanOnly; @@ -81,7 +81,7 @@ const f1: boolean | number = strMapUnion["foo"]; -//// [pedanticIndexSignatures.js] +//// [noUncheckedIndexedAccess.js] "use strict"; var NumericEnum1; (function (NumericEnum1) { diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.symbols b/tests/baselines/reference/noUncheckedIndexedAccess.symbols new file mode 100644 index 0000000000000..21d52164dbc12 --- /dev/null +++ b/tests/baselines/reference/noUncheckedIndexedAccess.symbols @@ -0,0 +1,271 @@ +=== tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts === +type CheckBooleanOnly = any; +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 0, 22)) + +// Validate CheckBooleanOnly works - should error +type T_ERR1 = CheckBooleanOnly; +>T_ERR1 : Symbol(T_ERR1, Decl(noUncheckedIndexedAccess.ts, 0, 47)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) + +enum NumericEnum1 { A, B, C } +>NumericEnum1 : Symbol(NumericEnum1, Decl(noUncheckedIndexedAccess.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) +>B : Symbol(NumericEnum1.B, Decl(noUncheckedIndexedAccess.ts, 4, 22)) +>C : Symbol(NumericEnum1.C, Decl(noUncheckedIndexedAccess.ts, 4, 25)) + +enum NumericEnum2 { A = 0, B = 1 , C = 2 } +>NumericEnum2 : Symbol(NumericEnum2, Decl(noUncheckedIndexedAccess.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) +>B : Symbol(NumericEnum2.B, Decl(noUncheckedIndexedAccess.ts, 5, 26)) +>C : Symbol(NumericEnum2.C, Decl(noUncheckedIndexedAccess.ts, 5, 34)) + +enum StringEnum1 { A = "Alpha", B = "Beta" } +>StringEnum1 : Symbol(StringEnum1, Decl(noUncheckedIndexedAccess.ts, 5, 42)) +>A : Symbol(StringEnum1.A, Decl(noUncheckedIndexedAccess.ts, 6, 18)) +>B : Symbol(StringEnum1.B, Decl(noUncheckedIndexedAccess.ts, 6, 31)) + +declare const strMap: { [s: string]: boolean }; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 8, 25)) + +// All of these should be errors +const e1: boolean = strMap["foo"]; +>e1 : Symbol(e1, Decl(noUncheckedIndexedAccess.ts, 11, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e2: boolean = strMap.bar; +>e2 : Symbol(e2, Decl(noUncheckedIndexedAccess.ts, 12, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e3: boolean = strMap[0]; +>e3 : Symbol(e3, Decl(noUncheckedIndexedAccess.ts, 13, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e4: boolean = strMap[0 as string | number]; +>e4 : Symbol(e4, Decl(noUncheckedIndexedAccess.ts, 14, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e5: boolean = strMap[0 as string | 0 | 1]; +>e5 : Symbol(e5, Decl(noUncheckedIndexedAccess.ts, 15, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e6: boolean = strMap[0 as 0 | 1]; +>e6 : Symbol(e6, Decl(noUncheckedIndexedAccess.ts, 16, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e7: boolean = strMap["foo" as "foo" | "baz"]; +>e7 : Symbol(e7, Decl(noUncheckedIndexedAccess.ts, 17, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const e8: boolean = strMap[NumericEnum1.A]; +>e8 : Symbol(e8, Decl(noUncheckedIndexedAccess.ts, 18, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>NumericEnum1.A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(noUncheckedIndexedAccess.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) + +const e9: boolean = strMap[NumericEnum2.A]; +>e9 : Symbol(e9, Decl(noUncheckedIndexedAccess.ts, 19, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>NumericEnum2.A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(noUncheckedIndexedAccess.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) + +const e10: boolean = strMap[StringEnum1.A]; +>e10 : Symbol(e10, Decl(noUncheckedIndexedAccess.ts, 20, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>StringEnum1.A : Symbol(StringEnum1.A, Decl(noUncheckedIndexedAccess.ts, 6, 18)) +>StringEnum1 : Symbol(StringEnum1, Decl(noUncheckedIndexedAccess.ts, 5, 42)) +>A : Symbol(StringEnum1.A, Decl(noUncheckedIndexedAccess.ts, 6, 18)) + +const e11: boolean = strMap[StringEnum1.A as StringEnum1]; +>e11 : Symbol(e11, Decl(noUncheckedIndexedAccess.ts, 21, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>StringEnum1.A : Symbol(StringEnum1.A, Decl(noUncheckedIndexedAccess.ts, 6, 18)) +>StringEnum1 : Symbol(StringEnum1, Decl(noUncheckedIndexedAccess.ts, 5, 42)) +>A : Symbol(StringEnum1.A, Decl(noUncheckedIndexedAccess.ts, 6, 18)) +>StringEnum1 : Symbol(StringEnum1, Decl(noUncheckedIndexedAccess.ts, 5, 42)) + +const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; +>e12 : Symbol(e12, Decl(noUncheckedIndexedAccess.ts, 22, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>NumericEnum1.A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(noUncheckedIndexedAccess.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(noUncheckedIndexedAccess.ts, 2, 52)) + +const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; +>e13 : Symbol(e13, Decl(noUncheckedIndexedAccess.ts, 23, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>NumericEnum2.A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(noUncheckedIndexedAccess.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(noUncheckedIndexedAccess.ts, 4, 29)) + +const e14: boolean = strMap[null as any]; +>e14 : Symbol(e14, Decl(noUncheckedIndexedAccess.ts, 24, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +// Should be OK +const ok1: boolean | undefined = strMap["foo"]; +>ok1 : Symbol(ok1, Decl(noUncheckedIndexedAccess.ts, 27, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +const ok2: boolean | undefined = strMap.bar; +>ok2 : Symbol(ok2, Decl(noUncheckedIndexedAccess.ts, 28, 5)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; +>T_OK1 : Symbol(T_OK1, Decl(noUncheckedIndexedAccess.ts, 28, 44)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; +>T_OK2 : Symbol(T_OK2, Decl(noUncheckedIndexedAccess.ts, 30, 55)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; +>T_OK3 : Symbol(T_OK3, Decl(noUncheckedIndexedAccess.ts, 31, 54)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; +>T_OK4 : Symbol(T_OK4, Decl(noUncheckedIndexedAccess.ts, 32, 62)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; +>T_OK5 : Symbol(T_OK5, Decl(noUncheckedIndexedAccess.ts, 33, 55)) +>CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(noUncheckedIndexedAccess.ts, 0, 0)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) + +// Writes don't allow 'undefined'; all should be errors +strMap["baz"] = undefined; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>undefined : Symbol(undefined) + +strMap.qua = undefined; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>undefined : Symbol(undefined) + +strMap[0] = undefined; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>undefined : Symbol(undefined) + +strMap[null as any] = undefined; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>undefined : Symbol(undefined) + +// Numeric lookups are unaffected +declare const numMap: { [s: number]: boolean }; +>numMap : Symbol(numMap, Decl(noUncheckedIndexedAccess.ts, 43, 13)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 43, 25)) + +// All of these should be ok +const num_ok1: boolean = numMap[0]; +>num_ok1 : Symbol(num_ok1, Decl(noUncheckedIndexedAccess.ts, 45, 5)) +>numMap : Symbol(numMap, Decl(noUncheckedIndexedAccess.ts, 43, 13)) + +const num_ok2: boolean = numMap[0 as number]; +>num_ok2 : Symbol(num_ok2, Decl(noUncheckedIndexedAccess.ts, 46, 5)) +>numMap : Symbol(numMap, Decl(noUncheckedIndexedAccess.ts, 43, 13)) + +const num_ok3: boolean = numMap[0 as 0 | 1]; +>num_ok3 : Symbol(num_ok3, Decl(noUncheckedIndexedAccess.ts, 47, 5)) +>numMap : Symbol(numMap, Decl(noUncheckedIndexedAccess.ts, 43, 13)) + +const num_ok4: boolean = numMap[NumericEnum1.A]; +>num_ok4 : Symbol(num_ok4, Decl(noUncheckedIndexedAccess.ts, 48, 5)) +>numMap : Symbol(numMap, Decl(noUncheckedIndexedAccess.ts, 43, 13)) +>NumericEnum1.A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) +>NumericEnum1 : Symbol(NumericEnum1, Decl(noUncheckedIndexedAccess.ts, 2, 52)) +>A : Symbol(NumericEnum1.A, Decl(noUncheckedIndexedAccess.ts, 4, 19)) + +const num_ok5: boolean = numMap[NumericEnum2.A]; +>num_ok5 : Symbol(num_ok5, Decl(noUncheckedIndexedAccess.ts, 49, 5)) +>numMap : Symbol(numMap, Decl(noUncheckedIndexedAccess.ts, 43, 13)) +>NumericEnum2.A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) +>NumericEnum2 : Symbol(NumericEnum2, Decl(noUncheckedIndexedAccess.ts, 4, 29)) +>A : Symbol(NumericEnum2.A, Decl(noUncheckedIndexedAccess.ts, 5, 19)) + +// Generics +function generic1(arg: T): boolean { +>generic1 : Symbol(generic1, Decl(noUncheckedIndexedAccess.ts, 49, 48)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 52, 18)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 52, 31)) +>arg : Symbol(arg, Decl(noUncheckedIndexedAccess.ts, 52, 54)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 52, 18)) + + // Should error + return arg["blah"]; +>arg : Symbol(arg, Decl(noUncheckedIndexedAccess.ts, 52, 54)) +} +function generic2(arg: T): boolean { +>generic2 : Symbol(generic2, Decl(noUncheckedIndexedAccess.ts, 55, 1)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 56, 18)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 56, 31)) +>arg : Symbol(arg, Decl(noUncheckedIndexedAccess.ts, 56, 54)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 56, 18)) + + // Should OK + return arg["blah"]!; +>arg : Symbol(arg, Decl(noUncheckedIndexedAccess.ts, 56, 54)) +} +function generic3(arg: T): boolean { +>generic3 : Symbol(generic3, Decl(noUncheckedIndexedAccess.ts, 59, 1)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 60, 18)) +>arg : Symbol(arg, Decl(noUncheckedIndexedAccess.ts, 60, 36)) +>T : Symbol(T, Decl(noUncheckedIndexedAccess.ts, 60, 18)) + + // Should error + return strMap[arg]; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccess.ts, 8, 13)) +>arg : Symbol(arg, Decl(noUncheckedIndexedAccess.ts, 60, 36)) +} + +// Element access into known properties is ok +declare const obj1: { x: string, y: number, [key: string]: string | number }; +>obj1 : Symbol(obj1, Decl(noUncheckedIndexedAccess.ts, 66, 13)) +>x : Symbol(x, Decl(noUncheckedIndexedAccess.ts, 66, 21)) +>y : Symbol(y, Decl(noUncheckedIndexedAccess.ts, 66, 32)) +>key : Symbol(key, Decl(noUncheckedIndexedAccess.ts, 66, 45)) + +obj1["x"]; +>obj1 : Symbol(obj1, Decl(noUncheckedIndexedAccess.ts, 66, 13)) +>"x" : Symbol(x, Decl(noUncheckedIndexedAccess.ts, 66, 21)) + +const y = "y"; +>y : Symbol(y, Decl(noUncheckedIndexedAccess.ts, 68, 5)) + +obj1[y]; +>obj1 : Symbol(obj1, Decl(noUncheckedIndexedAccess.ts, 66, 13)) +>y : Symbol(y, Decl(noUncheckedIndexedAccess.ts, 68, 5)) + +let yy = "y"; +>yy : Symbol(yy, Decl(noUncheckedIndexedAccess.ts, 70, 3)) + +obj1[yy]; +>obj1 : Symbol(obj1, Decl(noUncheckedIndexedAccess.ts, 66, 13)) +>yy : Symbol(yy, Decl(noUncheckedIndexedAccess.ts, 70, 3)) + +let z = "z"; +>z : Symbol(z, Decl(noUncheckedIndexedAccess.ts, 72, 3)) + +obj1[z]; +>obj1 : Symbol(obj1, Decl(noUncheckedIndexedAccess.ts, 66, 13)) +>z : Symbol(z, Decl(noUncheckedIndexedAccess.ts, 72, 3)) + +// Distributivity cases +declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; +>strMapUnion : Symbol(strMapUnion, Decl(noUncheckedIndexedAccess.ts, 76, 13)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 76, 30)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 76, 57)) + +// Should error +const f1: boolean | number = strMapUnion["foo"]; +>f1 : Symbol(f1, Decl(noUncheckedIndexedAccess.ts, 78, 5)) +>strMapUnion : Symbol(strMapUnion, Decl(noUncheckedIndexedAccess.ts, 76, 13)) + + diff --git a/tests/baselines/reference/pedanticIndexSignatures.types b/tests/baselines/reference/noUncheckedIndexedAccess.types similarity index 81% rename from tests/baselines/reference/pedanticIndexSignatures.types rename to tests/baselines/reference/noUncheckedIndexedAccess.types index 2fa9bc420dac7..9a32cc7574100 100644 --- a/tests/baselines/reference/pedanticIndexSignatures.types +++ b/tests/baselines/reference/noUncheckedIndexedAccess.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/pedantic/pedanticIndexSignatures.ts === +=== tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts === type CheckBooleanOnly = any; >CheckBooleanOnly : any @@ -35,53 +35,53 @@ declare const strMap: { [s: string]: boolean }; // All of these should be errors const e1: boolean = strMap["foo"]; >e1 : boolean ->strMap["foo"] : boolean | undefined +>strMap["foo"] : boolean >strMap : { [s: string]: boolean; } >"foo" : "foo" const e2: boolean = strMap.bar; >e2 : boolean ->strMap.bar : boolean | undefined +>strMap.bar : boolean >strMap : { [s: string]: boolean; } ->bar : boolean | undefined +>bar : boolean const e3: boolean = strMap[0]; >e3 : boolean ->strMap[0] : boolean | undefined +>strMap[0] : boolean >strMap : { [s: string]: boolean; } >0 : 0 const e4: boolean = strMap[0 as string | number]; >e4 : boolean ->strMap[0 as string | number] : boolean | undefined +>strMap[0 as string | number] : boolean >strMap : { [s: string]: boolean; } >0 as string | number : string | number >0 : 0 const e5: boolean = strMap[0 as string | 0 | 1]; >e5 : boolean ->strMap[0 as string | 0 | 1] : boolean | undefined +>strMap[0 as string | 0 | 1] : boolean >strMap : { [s: string]: boolean; } >0 as string | 0 | 1 : string | 0 | 1 >0 : 0 const e6: boolean = strMap[0 as 0 | 1]; >e6 : boolean ->strMap[0 as 0 | 1] : boolean | undefined +>strMap[0 as 0 | 1] : boolean >strMap : { [s: string]: boolean; } >0 as 0 | 1 : 0 | 1 >0 : 0 const e7: boolean = strMap["foo" as "foo" | "baz"]; >e7 : boolean ->strMap["foo" as "foo" | "baz"] : boolean | undefined +>strMap["foo" as "foo" | "baz"] : boolean >strMap : { [s: string]: boolean; } >"foo" as "foo" | "baz" : "foo" | "baz" >"foo" : "foo" const e8: boolean = strMap[NumericEnum1.A]; >e8 : boolean ->strMap[NumericEnum1.A] : boolean | undefined +>strMap[NumericEnum1.A] : boolean >strMap : { [s: string]: boolean; } >NumericEnum1.A : NumericEnum1.A >NumericEnum1 : typeof NumericEnum1 @@ -89,7 +89,7 @@ const e8: boolean = strMap[NumericEnum1.A]; const e9: boolean = strMap[NumericEnum2.A]; >e9 : boolean ->strMap[NumericEnum2.A] : boolean | undefined +>strMap[NumericEnum2.A] : boolean >strMap : { [s: string]: boolean; } >NumericEnum2.A : NumericEnum2.A >NumericEnum2 : typeof NumericEnum2 @@ -97,7 +97,7 @@ const e9: boolean = strMap[NumericEnum2.A]; const e10: boolean = strMap[StringEnum1.A]; >e10 : boolean ->strMap[StringEnum1.A] : boolean | undefined +>strMap[StringEnum1.A] : boolean >strMap : { [s: string]: boolean; } >StringEnum1.A : StringEnum1.A >StringEnum1 : typeof StringEnum1 @@ -105,7 +105,7 @@ const e10: boolean = strMap[StringEnum1.A]; const e11: boolean = strMap[StringEnum1.A as StringEnum1]; >e11 : boolean ->strMap[StringEnum1.A as StringEnum1] : boolean | undefined +>strMap[StringEnum1.A as StringEnum1] : boolean >strMap : { [s: string]: boolean; } >StringEnum1.A as StringEnum1 : StringEnum1 >StringEnum1.A : StringEnum1.A @@ -114,7 +114,7 @@ const e11: boolean = strMap[StringEnum1.A as StringEnum1]; const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; >e12 : boolean ->strMap[NumericEnum1.A as NumericEnum1] : boolean | undefined +>strMap[NumericEnum1.A as NumericEnum1] : boolean >strMap : { [s: string]: boolean; } >NumericEnum1.A as NumericEnum1 : NumericEnum1 >NumericEnum1.A : NumericEnum1.A @@ -123,7 +123,7 @@ const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; >e13 : boolean ->strMap[NumericEnum2.A as NumericEnum2] : boolean | undefined +>strMap[NumericEnum2.A as NumericEnum2] : boolean >strMap : { [s: string]: boolean; } >NumericEnum2.A as NumericEnum2 : NumericEnum2 >NumericEnum2.A : NumericEnum2.A @@ -132,7 +132,7 @@ const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; const e14: boolean = strMap[null as any]; >e14 : boolean ->strMap[null as any] : boolean | undefined +>strMap[null as any] : boolean >strMap : { [s: string]: boolean; } >null as any : any >null : null @@ -140,15 +140,15 @@ const e14: boolean = strMap[null as any]; // Should be OK const ok1: boolean | undefined = strMap["foo"]; >ok1 : boolean | undefined ->strMap["foo"] : boolean | undefined +>strMap["foo"] : boolean >strMap : { [s: string]: boolean; } >"foo" : "foo" const ok2: boolean | undefined = strMap.bar; >ok2 : boolean | undefined ->strMap.bar : boolean | undefined +>strMap.bar : boolean >strMap : { [s: string]: boolean; } ->bar : boolean | undefined +>bar : boolean type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; >T_OK1 : any @@ -208,27 +208,27 @@ declare const numMap: { [s: number]: boolean }; // All of these should be ok const num_ok1: boolean = numMap[0]; >num_ok1 : boolean ->numMap[0] : boolean | undefined +>numMap[0] : boolean >numMap : { [s: number]: boolean; } >0 : 0 const num_ok2: boolean = numMap[0 as number]; >num_ok2 : boolean ->numMap[0 as number] : boolean | undefined +>numMap[0 as number] : boolean >numMap : { [s: number]: boolean; } >0 as number : number >0 : 0 const num_ok3: boolean = numMap[0 as 0 | 1]; >num_ok3 : boolean ->numMap[0 as 0 | 1] : boolean | undefined +>numMap[0 as 0 | 1] : boolean >numMap : { [s: number]: boolean; } >0 as 0 | 1 : 0 | 1 >0 : 0 const num_ok4: boolean = numMap[NumericEnum1.A]; >num_ok4 : boolean ->numMap[NumericEnum1.A] : boolean | undefined +>numMap[NumericEnum1.A] : boolean >numMap : { [s: number]: boolean; } >NumericEnum1.A : NumericEnum1.A >NumericEnum1 : typeof NumericEnum1 @@ -236,7 +236,7 @@ const num_ok4: boolean = numMap[NumericEnum1.A]; const num_ok5: boolean = numMap[NumericEnum2.A]; >num_ok5 : boolean ->numMap[NumericEnum2.A] : boolean | undefined +>numMap[NumericEnum2.A] : boolean >numMap : { [s: number]: boolean; } >NumericEnum2.A : NumericEnum2.A >NumericEnum2 : typeof NumericEnum2 @@ -250,7 +250,7 @@ function generic1(arg: T): boolean { // Should error return arg["blah"]; ->arg["blah"] : boolean | undefined +>arg["blah"] : boolean >arg : T >"blah" : "blah" } @@ -262,7 +262,7 @@ function generic2(arg: T): boolean { // Should OK return arg["blah"]!; >arg["blah"]! : boolean ->arg["blah"] : boolean | undefined +>arg["blah"] : boolean >arg : T >"blah" : "blah" } @@ -272,7 +272,7 @@ function generic3(arg: T): boolean { // Should error return strMap[arg]; ->strMap[arg] : boolean | undefined +>strMap[arg] : boolean >strMap : { [s: string]: boolean; } >arg : T } @@ -303,7 +303,7 @@ let yy = "y"; >"y" : "y" obj1[yy]; ->obj1[yy] : string | number | undefined +>obj1[yy] : string | number >obj1 : { [key: string]: string | number; x: string; y: number; } >yy : string @@ -312,7 +312,7 @@ let z = "z"; >"z" : "z" obj1[z]; ->obj1[z] : string | number | undefined +>obj1[z] : string | number >obj1 : { [key: string]: string | number; x: string; y: number; } >z : string @@ -325,7 +325,7 @@ declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; // Should error const f1: boolean | number = strMapUnion["foo"]; >f1 : number | boolean ->strMapUnion["foo"] : number | boolean | undefined +>strMapUnion["foo"] : number | boolean >strMapUnion : { [s: string]: boolean; } | { [s: string]: number; } >"foo" : "foo" diff --git a/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.errors.txt b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.errors.txt new file mode 100644 index 0000000000000..dfe57451edcf1 --- /dev/null +++ b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.errors.txt @@ -0,0 +1,70 @@ +tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts(12,9): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts(16,9): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. + + +==== tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts (2 errors) ==== + declare const strArray: string[]; + declare const strStrTuple: [string, string]; + + // Declaration forms for array destructuring + + // Destructuring from a simple array -> include undefined + const [s1] = strArray; + s1.toString(); // Should error, s1 possibly undefined + + // Destructuring a rest element -> do not include undefined + const [...s2] = strArray; + s2.push(undefined); // Should error, 'undefined' not part of s2's element type + ~~~~~~~~~ +!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. + + // Destructuring a rest element -> do not include undefined + const [, , ...s3] = strArray; + s3.push(undefined); // Should error, 'undefined' not part of s2's element type + ~~~~~~~~~ +!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. + + // Declaration forms for object destructuring + + declare const strMap: { [s: string]: string }; + + const { t1 } = strMap; + t1.toString(); // Should error, t1 possibly undefined + + const { ...t2 } = strMap; + t2.z.toString(); // Should error + + // Test intersections with declared properties + declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; + { + const { x, y, z } = numMapPoint; + x.toFixed(); // Should OK + y.toFixed(); // Should OK + z.toFixed(); // Should error + } + + { + const { x, ...q } = numMapPoint; + x.toFixed(); // Should OK + q.y.toFixed(); // Should OK + q.z.toFixed(); // Should error + } + + + declare let target_string: string; + declare let target_string_undef: string | undefined; + declare let target_string_arr: string[]; + + // Assignment forms + [target_string] = strArray; // Should error + [target_string_undef] = strArray; // Should OK + [,,, ...target_string_arr] = strArray; // Should OK + + { + let x: number, y: number, z: number | undefined; + ({ x, y, z } = numMapPoint); // Should OK + + let q: number; + ({ q } = numMapPoint); // Should error + } + \ No newline at end of file diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.js b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.js similarity index 95% rename from tests/baselines/reference/pedanticIndexSignatureDestructuring.js rename to tests/baselines/reference/noUncheckedIndexedAccessDestructuring.js index 678444b58dfa0..fd097ecfc5536 100644 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.js +++ b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.js @@ -1,4 +1,4 @@ -//// [pedanticIndexSignatureDestructuring.ts] +//// [noUncheckedIndexedAccessDestructuring.ts] declare const strArray: string[]; declare const strStrTuple: [string, string]; @@ -61,7 +61,7 @@ declare let target_string_arr: string[]; } -//// [pedanticIndexSignatureDestructuring.js] +//// [noUncheckedIndexedAccessDestructuring.js] "use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; diff --git a/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.symbols b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.symbols new file mode 100644 index 0000000000000..fb168915d7bd4 --- /dev/null +++ b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.symbols @@ -0,0 +1,161 @@ +=== tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts === +declare const strArray: string[]; +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +declare const strStrTuple: [string, string]; +>strStrTuple : Symbol(strStrTuple, Decl(noUncheckedIndexedAccessDestructuring.ts, 1, 13)) + +// Declaration forms for array destructuring + +// Destructuring from a simple array -> include undefined +const [s1] = strArray; +>s1 : Symbol(s1, Decl(noUncheckedIndexedAccessDestructuring.ts, 6, 7)) +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +s1.toString(); // Should error, s1 possibly undefined +>s1.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>s1 : Symbol(s1, Decl(noUncheckedIndexedAccessDestructuring.ts, 6, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + +// Destructuring a rest element -> do not include undefined +const [...s2] = strArray; +>s2 : Symbol(s2, Decl(noUncheckedIndexedAccessDestructuring.ts, 10, 7)) +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +s2.push(undefined); // Should error, 'undefined' not part of s2's element type +>s2.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>s2 : Symbol(s2, Decl(noUncheckedIndexedAccessDestructuring.ts, 10, 7)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>undefined : Symbol(undefined) + +// Destructuring a rest element -> do not include undefined +const [, , ...s3] = strArray; +>s3 : Symbol(s3, Decl(noUncheckedIndexedAccessDestructuring.ts, 14, 10)) +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +s3.push(undefined); // Should error, 'undefined' not part of s2's element type +>s3.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>s3 : Symbol(s3, Decl(noUncheckedIndexedAccessDestructuring.ts, 14, 10)) +>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) +>undefined : Symbol(undefined) + +// Declaration forms for object destructuring + +declare const strMap: { [s: string]: string }; +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccessDestructuring.ts, 19, 13)) +>s : Symbol(s, Decl(noUncheckedIndexedAccessDestructuring.ts, 19, 25)) + +const { t1 } = strMap; +>t1 : Symbol(t1, Decl(noUncheckedIndexedAccessDestructuring.ts, 21, 7)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccessDestructuring.ts, 19, 13)) + +t1.toString(); // Should error, t1 possibly undefined +>t1.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>t1 : Symbol(t1, Decl(noUncheckedIndexedAccessDestructuring.ts, 21, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + +const { ...t2 } = strMap; +>t2 : Symbol(t2, Decl(noUncheckedIndexedAccessDestructuring.ts, 24, 7)) +>strMap : Symbol(strMap, Decl(noUncheckedIndexedAccessDestructuring.ts, 19, 13)) + +t2.z.toString(); // Should error +>t2.z.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) +>t2 : Symbol(t2, Decl(noUncheckedIndexedAccessDestructuring.ts, 24, 7)) +>toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) + +// Test intersections with declared properties +declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; +>numMapPoint : Symbol(numMapPoint, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 13)) +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 28)) +>y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 39)) +>s : Symbol(s, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 56)) +{ + const { x, y, z } = numMapPoint; +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 30, 11)) +>y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 30, 14)) +>z : Symbol(z, Decl(noUncheckedIndexedAccessDestructuring.ts, 30, 17)) +>numMapPoint : Symbol(numMapPoint, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 13)) + + x.toFixed(); // Should OK +>x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 30, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + y.toFixed(); // Should OK +>y.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 30, 14)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + z.toFixed(); // Should error +>z.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>z : Symbol(z, Decl(noUncheckedIndexedAccessDestructuring.ts, 30, 17)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + +{ + const { x, ...q } = numMapPoint; +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 37, 11)) +>q : Symbol(q, Decl(noUncheckedIndexedAccessDestructuring.ts, 37, 14)) +>numMapPoint : Symbol(numMapPoint, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 13)) + + x.toFixed(); // Should OK +>x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 37, 11)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + q.y.toFixed(); // Should OK +>q.y.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>q.y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 39)) +>q : Symbol(q, Decl(noUncheckedIndexedAccessDestructuring.ts, 37, 14)) +>y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 39)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) + + q.z.toFixed(); // Should error +>q.z.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +>q : Symbol(q, Decl(noUncheckedIndexedAccessDestructuring.ts, 37, 14)) +>toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) +} + + +declare let target_string: string; +>target_string : Symbol(target_string, Decl(noUncheckedIndexedAccessDestructuring.ts, 44, 11)) + +declare let target_string_undef: string | undefined; +>target_string_undef : Symbol(target_string_undef, Decl(noUncheckedIndexedAccessDestructuring.ts, 45, 11)) + +declare let target_string_arr: string[]; +>target_string_arr : Symbol(target_string_arr, Decl(noUncheckedIndexedAccessDestructuring.ts, 46, 11)) + +// Assignment forms +[target_string] = strArray; // Should error +>target_string : Symbol(target_string, Decl(noUncheckedIndexedAccessDestructuring.ts, 44, 11)) +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +[target_string_undef] = strArray; // Should OK +>target_string_undef : Symbol(target_string_undef, Decl(noUncheckedIndexedAccessDestructuring.ts, 45, 11)) +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +[,,, ...target_string_arr] = strArray; // Should OK +>target_string_arr : Symbol(target_string_arr, Decl(noUncheckedIndexedAccessDestructuring.ts, 46, 11)) +>strArray : Symbol(strArray, Decl(noUncheckedIndexedAccessDestructuring.ts, 0, 13)) + +{ + let x: number, y: number, z: number | undefined; +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 54, 7)) +>y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 54, 18)) +>z : Symbol(z, Decl(noUncheckedIndexedAccessDestructuring.ts, 54, 29)) + + ({ x, y, z } = numMapPoint); // Should OK +>x : Symbol(x, Decl(noUncheckedIndexedAccessDestructuring.ts, 55, 6)) +>y : Symbol(y, Decl(noUncheckedIndexedAccessDestructuring.ts, 55, 9)) +>z : Symbol(z, Decl(noUncheckedIndexedAccessDestructuring.ts, 55, 12)) +>numMapPoint : Symbol(numMapPoint, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 13)) + + let q: number; +>q : Symbol(q, Decl(noUncheckedIndexedAccessDestructuring.ts, 57, 7)) + + ({ q } = numMapPoint); // Should error +>q : Symbol(q, Decl(noUncheckedIndexedAccessDestructuring.ts, 58, 6)) +>numMapPoint : Symbol(numMapPoint, Decl(noUncheckedIndexedAccessDestructuring.ts, 28, 13)) +} + diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.types b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.types similarity index 90% rename from tests/baselines/reference/pedanticIndexSignatureDestructuring.types rename to tests/baselines/reference/noUncheckedIndexedAccessDestructuring.types index 53506355e9576..5b28543d0c575 100644 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.types +++ b/tests/baselines/reference/noUncheckedIndexedAccessDestructuring.types @@ -1,4 +1,4 @@ -=== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts === +=== tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts === declare const strArray: string[]; >strArray : string[] @@ -9,13 +9,13 @@ declare const strStrTuple: [string, string]; // Destructuring from a simple array -> include undefined const [s1] = strArray; ->s1 : string | undefined +>s1 : string >strArray : string[] s1.toString(); // Should error, s1 possibly undefined >s1.toString() : string >s1.toString : () => string ->s1 : string | undefined +>s1 : string >toString : () => string // Destructuring a rest element -> do not include undefined @@ -51,13 +51,13 @@ declare const strMap: { [s: string]: string }; >s : string const { t1 } = strMap; ->t1 : string | undefined +>t1 : string >strMap : { [s: string]: string; } t1.toString(); // Should error, t1 possibly undefined >t1.toString() : string >t1.toString : () => string ->t1 : string | undefined +>t1 : string >toString : () => string const { ...t2 } = strMap; @@ -67,9 +67,9 @@ const { ...t2 } = strMap; t2.z.toString(); // Should error >t2.z.toString() : string >t2.z.toString : () => string ->t2.z : string | undefined +>t2.z : string >t2 : { [s: string]: string; } ->z : string | undefined +>z : string >toString : () => string // Test intersections with declared properties @@ -82,7 +82,7 @@ declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; const { x, y, z } = numMapPoint; >x : number >y : number ->z : number | undefined +>z : number >numMapPoint : { x: number; y: number; } & { [s: string]: number; } x.toFixed(); // Should OK @@ -100,7 +100,7 @@ declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; z.toFixed(); // Should error >z.toFixed() : string >z.toFixed : (fractionDigits?: number | undefined) => string ->z : number | undefined +>z : number >toFixed : (fractionDigits?: number | undefined) => string } @@ -127,9 +127,9 @@ declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; q.z.toFixed(); // Should error >q.z.toFixed() : string >q.z.toFixed : (fractionDigits?: number | undefined) => string ->q.z : number | undefined +>q.z : number >q : { [s: string]: number; y: number; } ->z : number | undefined +>z : number >toFixed : (fractionDigits?: number | undefined) => string } diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt b/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt deleted file mode 100644 index 4a4430e2cd9a0..0000000000000 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.errors.txt +++ /dev/null @@ -1,95 +0,0 @@ -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(8,1): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(12,9): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(16,9): error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(23,1): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(26,1): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(34,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(41,5): error TS2532: Object is possibly 'undefined'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(50,2): error TS2322: Type 'string | undefined' is not assignable to type 'string'. - Type 'undefined' is not assignable to type 'string'. -tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts(59,8): error TS2322: Type 'number | undefined' is not assignable to type 'number'. - Type 'undefined' is not assignable to type 'number'. - - -==== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts (9 errors) ==== - declare const strArray: string[]; - declare const strStrTuple: [string, string]; - - // Declaration forms for array destructuring - - // Destructuring from a simple array -> include undefined - const [s1] = strArray; - s1.toString(); // Should error, s1 possibly undefined - ~~ -!!! error TS2532: Object is possibly 'undefined'. - - // Destructuring a rest element -> do not include undefined - const [...s2] = strArray; - s2.push(undefined); // Should error, 'undefined' not part of s2's element type - ~~~~~~~~~ -!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. - - // Destructuring a rest element -> do not include undefined - const [, , ...s3] = strArray; - s3.push(undefined); // Should error, 'undefined' not part of s2's element type - ~~~~~~~~~ -!!! error TS2345: Argument of type 'undefined' is not assignable to parameter of type 'string'. - - // Declaration forms for object destructuring - - declare const strMap: { [s: string]: string }; - - const { t1 } = strMap; - t1.toString(); // Should error, t1 possibly undefined - ~~ -!!! error TS2532: Object is possibly 'undefined'. - - const { ...t2 } = strMap; - t2.z.toString(); // Should error - ~~~~ -!!! error TS2532: Object is possibly 'undefined'. - - // Test intersections with declared properties - declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; - { - const { x, y, z } = numMapPoint; - x.toFixed(); // Should OK - y.toFixed(); // Should OK - z.toFixed(); // Should error - ~ -!!! error TS2532: Object is possibly 'undefined'. - } - - { - const { x, ...q } = numMapPoint; - x.toFixed(); // Should OK - q.y.toFixed(); // Should OK - q.z.toFixed(); // Should error - ~~~ -!!! error TS2532: Object is possibly 'undefined'. - } - - - declare let target_string: string; - declare let target_string_undef: string | undefined; - declare let target_string_arr: string[]; - - // Assignment forms - [target_string] = strArray; // Should error - ~~~~~~~~~~~~~ -!!! error TS2322: Type 'string | undefined' is not assignable to type 'string'. -!!! error TS2322: Type 'undefined' is not assignable to type 'string'. - [target_string_undef] = strArray; // Should OK - [,,, ...target_string_arr] = strArray; // Should OK - - { - let x: number, y: number, z: number | undefined; - ({ x, y, z } = numMapPoint); // Should OK - - let q: number; - ({ q } = numMapPoint); // Should error - ~ -!!! error TS2322: Type 'number | undefined' is not assignable to type 'number'. -!!! error TS2322: Type 'undefined' is not assignable to type 'number'. - } - \ No newline at end of file diff --git a/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols b/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols deleted file mode 100644 index b1c16aafe7fa2..0000000000000 --- a/tests/baselines/reference/pedanticIndexSignatureDestructuring.symbols +++ /dev/null @@ -1,161 +0,0 @@ -=== tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts === -declare const strArray: string[]; ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -declare const strStrTuple: [string, string]; ->strStrTuple : Symbol(strStrTuple, Decl(pedanticIndexSignatureDestructuring.ts, 1, 13)) - -// Declaration forms for array destructuring - -// Destructuring from a simple array -> include undefined -const [s1] = strArray; ->s1 : Symbol(s1, Decl(pedanticIndexSignatureDestructuring.ts, 6, 7)) ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -s1.toString(); // Should error, s1 possibly undefined ->s1.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) ->s1 : Symbol(s1, Decl(pedanticIndexSignatureDestructuring.ts, 6, 7)) ->toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) - -// Destructuring a rest element -> do not include undefined -const [...s2] = strArray; ->s2 : Symbol(s2, Decl(pedanticIndexSignatureDestructuring.ts, 10, 7)) ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -s2.push(undefined); // Should error, 'undefined' not part of s2's element type ->s2.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->s2 : Symbol(s2, Decl(pedanticIndexSignatureDestructuring.ts, 10, 7)) ->push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->undefined : Symbol(undefined) - -// Destructuring a rest element -> do not include undefined -const [, , ...s3] = strArray; ->s3 : Symbol(s3, Decl(pedanticIndexSignatureDestructuring.ts, 14, 10)) ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -s3.push(undefined); // Should error, 'undefined' not part of s2's element type ->s3.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->s3 : Symbol(s3, Decl(pedanticIndexSignatureDestructuring.ts, 14, 10)) ->push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --)) ->undefined : Symbol(undefined) - -// Declaration forms for object destructuring - -declare const strMap: { [s: string]: string }; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatureDestructuring.ts, 19, 13)) ->s : Symbol(s, Decl(pedanticIndexSignatureDestructuring.ts, 19, 25)) - -const { t1 } = strMap; ->t1 : Symbol(t1, Decl(pedanticIndexSignatureDestructuring.ts, 21, 7)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatureDestructuring.ts, 19, 13)) - -t1.toString(); // Should error, t1 possibly undefined ->t1.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) ->t1 : Symbol(t1, Decl(pedanticIndexSignatureDestructuring.ts, 21, 7)) ->toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) - -const { ...t2 } = strMap; ->t2 : Symbol(t2, Decl(pedanticIndexSignatureDestructuring.ts, 24, 7)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatureDestructuring.ts, 19, 13)) - -t2.z.toString(); // Should error ->t2.z.toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) ->t2 : Symbol(t2, Decl(pedanticIndexSignatureDestructuring.ts, 24, 7)) ->toString : Symbol(String.toString, Decl(lib.es5.d.ts, --, --)) - -// Test intersections with declared properties -declare const numMapPoint: { x: number, y: number} & { [s: string]: number }; ->numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 28, 28)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 28, 39)) ->s : Symbol(s, Decl(pedanticIndexSignatureDestructuring.ts, 28, 56)) -{ - const { x, y, z } = numMapPoint; ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 30, 11)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 30, 14)) ->z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 30, 17)) ->numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) - - x.toFixed(); // Should OK ->x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 30, 11)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - y.toFixed(); // Should OK ->y.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 30, 14)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - z.toFixed(); // Should error ->z.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 30, 17)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) -} - -{ - const { x, ...q } = numMapPoint; ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 37, 11)) ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 37, 14)) ->numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) - - x.toFixed(); // Should OK ->x.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 37, 11)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - q.y.toFixed(); // Should OK ->q.y.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->q.y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 28, 39)) ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 37, 14)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 28, 39)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) - - q.z.toFixed(); // Should error ->q.z.toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 37, 14)) ->toFixed : Symbol(Number.toFixed, Decl(lib.es5.d.ts, --, --)) -} - - -declare let target_string: string; ->target_string : Symbol(target_string, Decl(pedanticIndexSignatureDestructuring.ts, 44, 11)) - -declare let target_string_undef: string | undefined; ->target_string_undef : Symbol(target_string_undef, Decl(pedanticIndexSignatureDestructuring.ts, 45, 11)) - -declare let target_string_arr: string[]; ->target_string_arr : Symbol(target_string_arr, Decl(pedanticIndexSignatureDestructuring.ts, 46, 11)) - -// Assignment forms -[target_string] = strArray; // Should error ->target_string : Symbol(target_string, Decl(pedanticIndexSignatureDestructuring.ts, 44, 11)) ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -[target_string_undef] = strArray; // Should OK ->target_string_undef : Symbol(target_string_undef, Decl(pedanticIndexSignatureDestructuring.ts, 45, 11)) ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -[,,, ...target_string_arr] = strArray; // Should OK ->target_string_arr : Symbol(target_string_arr, Decl(pedanticIndexSignatureDestructuring.ts, 46, 11)) ->strArray : Symbol(strArray, Decl(pedanticIndexSignatureDestructuring.ts, 0, 13)) - -{ - let x: number, y: number, z: number | undefined; ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 54, 7)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 54, 18)) ->z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 54, 29)) - - ({ x, y, z } = numMapPoint); // Should OK ->x : Symbol(x, Decl(pedanticIndexSignatureDestructuring.ts, 55, 6)) ->y : Symbol(y, Decl(pedanticIndexSignatureDestructuring.ts, 55, 9)) ->z : Symbol(z, Decl(pedanticIndexSignatureDestructuring.ts, 55, 12)) ->numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) - - let q: number; ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 57, 7)) - - ({ q } = numMapPoint); // Should error ->q : Symbol(q, Decl(pedanticIndexSignatureDestructuring.ts, 58, 6)) ->numMapPoint : Symbol(numMapPoint, Decl(pedanticIndexSignatureDestructuring.ts, 28, 13)) -} - diff --git a/tests/baselines/reference/pedanticIndexSignatures.errors.txt b/tests/baselines/reference/pedanticIndexSignatures.errors.txt deleted file mode 100644 index 45d859ea78f1a..0000000000000 --- a/tests/baselines/reference/pedanticIndexSignatures.errors.txt +++ /dev/null @@ -1,211 +0,0 @@ -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(3,32): error TS2344: Type 'boolean | undefined' does not satisfy the constraint 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(12,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(13,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(14,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(15,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(16,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(17,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(18,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(19,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(20,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(21,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(22,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(23,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(24,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(25,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(38,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(39,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(40,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(41,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(46,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(47,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(48,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(49,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(50,7): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(55,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(63,5): error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. - Type 'undefined' is not assignable to type 'boolean'. -tests/cases/conformance/pedantic/pedanticIndexSignatures.ts(79,7): error TS2322: Type 'number | boolean | undefined' is not assignable to type 'number | boolean'. - Type 'undefined' is not assignable to type 'number | boolean'. - - -==== tests/cases/conformance/pedantic/pedanticIndexSignatures.ts (27 errors) ==== - type CheckBooleanOnly = any; - // Validate CheckBooleanOnly works - should error - type T_ERR1 = CheckBooleanOnly; - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2344: Type 'boolean | undefined' does not satisfy the constraint 'boolean'. -!!! error TS2344: Type 'undefined' is not assignable to type 'boolean'. - - enum NumericEnum1 { A, B, C } - enum NumericEnum2 { A = 0, B = 1 , C = 2 } - enum StringEnum1 { A = "Alpha", B = "Beta" } - - declare const strMap: { [s: string]: boolean }; - - // All of these should be errors - const e1: boolean = strMap["foo"]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e2: boolean = strMap.bar; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e3: boolean = strMap[0]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e4: boolean = strMap[0 as string | number]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e5: boolean = strMap[0 as string | 0 | 1]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e6: boolean = strMap[0 as 0 | 1]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e7: boolean = strMap["foo" as "foo" | "baz"]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e8: boolean = strMap[NumericEnum1.A]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e9: boolean = strMap[NumericEnum2.A]; - ~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e10: boolean = strMap[StringEnum1.A]; - ~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e11: boolean = strMap[StringEnum1.A as StringEnum1]; - ~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; - ~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; - ~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const e14: boolean = strMap[null as any]; - ~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - - // Should be OK - const ok1: boolean | undefined = strMap["foo"]; - const ok2: boolean | undefined = strMap.bar; - - type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; - type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; - type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; - type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; - type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; - - // Writes don't allow 'undefined'; all should be errors - strMap["baz"] = undefined; - ~~~~~~~~~~~~~ -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - strMap.qua = undefined; - ~~~~~~~~~~ -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - strMap[0] = undefined; - ~~~~~~~~~ -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - strMap[null as any] = undefined; - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - - // Numeric lookups are unaffected - declare const numMap: { [s: number]: boolean }; - // All of these should be ok - const num_ok1: boolean = numMap[0]; - ~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const num_ok2: boolean = numMap[0 as number]; - ~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const num_ok3: boolean = numMap[0 as 0 | 1]; - ~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const num_ok4: boolean = numMap[NumericEnum1.A]; - ~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - const num_ok5: boolean = numMap[NumericEnum2.A]; - ~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - - // Generics - function generic1(arg: T): boolean { - // Should error - return arg["blah"]; - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - } - function generic2(arg: T): boolean { - // Should OK - return arg["blah"]!; - } - function generic3(arg: T): boolean { - // Should error - return strMap[arg]; - ~~~~~~~~~~~~~~~~~~~ -!!! error TS2322: Type 'boolean | undefined' is not assignable to type 'boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'boolean'. - } - - // Element access into known properties is ok - declare const obj1: { x: string, y: number, [key: string]: string | number }; - obj1["x"]; - const y = "y"; - obj1[y]; - let yy = "y"; - obj1[yy]; - let z = "z"; - obj1[z]; - - // Distributivity cases - declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; - // Should error - const f1: boolean | number = strMapUnion["foo"]; - ~~ -!!! error TS2322: Type 'number | boolean | undefined' is not assignable to type 'number | boolean'. -!!! error TS2322: Type 'undefined' is not assignable to type 'number | boolean'. - - \ No newline at end of file diff --git a/tests/baselines/reference/pedanticIndexSignatures.symbols b/tests/baselines/reference/pedanticIndexSignatures.symbols deleted file mode 100644 index 6c28f683317b2..0000000000000 --- a/tests/baselines/reference/pedanticIndexSignatures.symbols +++ /dev/null @@ -1,271 +0,0 @@ -=== tests/cases/conformance/pedantic/pedanticIndexSignatures.ts === -type CheckBooleanOnly = any; ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 0, 22)) - -// Validate CheckBooleanOnly works - should error -type T_ERR1 = CheckBooleanOnly; ->T_ERR1 : Symbol(T_ERR1, Decl(pedanticIndexSignatures.ts, 0, 47)) ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) - -enum NumericEnum1 { A, B, C } ->NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) ->A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) ->B : Symbol(NumericEnum1.B, Decl(pedanticIndexSignatures.ts, 4, 22)) ->C : Symbol(NumericEnum1.C, Decl(pedanticIndexSignatures.ts, 4, 25)) - -enum NumericEnum2 { A = 0, B = 1 , C = 2 } ->NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) ->A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) ->B : Symbol(NumericEnum2.B, Decl(pedanticIndexSignatures.ts, 5, 26)) ->C : Symbol(NumericEnum2.C, Decl(pedanticIndexSignatures.ts, 5, 34)) - -enum StringEnum1 { A = "Alpha", B = "Beta" } ->StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) ->A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) ->B : Symbol(StringEnum1.B, Decl(pedanticIndexSignatures.ts, 6, 31)) - -declare const strMap: { [s: string]: boolean }; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 8, 25)) - -// All of these should be errors -const e1: boolean = strMap["foo"]; ->e1 : Symbol(e1, Decl(pedanticIndexSignatures.ts, 11, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e2: boolean = strMap.bar; ->e2 : Symbol(e2, Decl(pedanticIndexSignatures.ts, 12, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e3: boolean = strMap[0]; ->e3 : Symbol(e3, Decl(pedanticIndexSignatures.ts, 13, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e4: boolean = strMap[0 as string | number]; ->e4 : Symbol(e4, Decl(pedanticIndexSignatures.ts, 14, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e5: boolean = strMap[0 as string | 0 | 1]; ->e5 : Symbol(e5, Decl(pedanticIndexSignatures.ts, 15, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e6: boolean = strMap[0 as 0 | 1]; ->e6 : Symbol(e6, Decl(pedanticIndexSignatures.ts, 16, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e7: boolean = strMap["foo" as "foo" | "baz"]; ->e7 : Symbol(e7, Decl(pedanticIndexSignatures.ts, 17, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const e8: boolean = strMap[NumericEnum1.A]; ->e8 : Symbol(e8, Decl(pedanticIndexSignatures.ts, 18, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->NumericEnum1.A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) ->NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) ->A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) - -const e9: boolean = strMap[NumericEnum2.A]; ->e9 : Symbol(e9, Decl(pedanticIndexSignatures.ts, 19, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->NumericEnum2.A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) ->NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) ->A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) - -const e10: boolean = strMap[StringEnum1.A]; ->e10 : Symbol(e10, Decl(pedanticIndexSignatures.ts, 20, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->StringEnum1.A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) ->StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) ->A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) - -const e11: boolean = strMap[StringEnum1.A as StringEnum1]; ->e11 : Symbol(e11, Decl(pedanticIndexSignatures.ts, 21, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->StringEnum1.A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) ->StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) ->A : Symbol(StringEnum1.A, Decl(pedanticIndexSignatures.ts, 6, 18)) ->StringEnum1 : Symbol(StringEnum1, Decl(pedanticIndexSignatures.ts, 5, 42)) - -const e12: boolean = strMap[NumericEnum1.A as NumericEnum1]; ->e12 : Symbol(e12, Decl(pedanticIndexSignatures.ts, 22, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->NumericEnum1.A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) ->NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) ->A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) ->NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) - -const e13: boolean = strMap[NumericEnum2.A as NumericEnum2]; ->e13 : Symbol(e13, Decl(pedanticIndexSignatures.ts, 23, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->NumericEnum2.A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) ->NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) ->A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) ->NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) - -const e14: boolean = strMap[null as any]; ->e14 : Symbol(e14, Decl(pedanticIndexSignatures.ts, 24, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -// Should be OK -const ok1: boolean | undefined = strMap["foo"]; ->ok1 : Symbol(ok1, Decl(pedanticIndexSignatures.ts, 27, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -const ok2: boolean | undefined = strMap.bar; ->ok2 : Symbol(ok2, Decl(pedanticIndexSignatures.ts, 28, 5)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -type T_OK1 = CheckBooleanOnly<(typeof strMap)[string]>; ->T_OK1 : Symbol(T_OK1, Decl(pedanticIndexSignatures.ts, 28, 44)) ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -type T_OK2 = CheckBooleanOnly<(typeof strMap)["foo"]>; ->T_OK2 : Symbol(T_OK2, Decl(pedanticIndexSignatures.ts, 30, 55)) ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -type T_OK3 = CheckBooleanOnly<(typeof strMap)["bar" | "baz"]>; ->T_OK3 : Symbol(T_OK3, Decl(pedanticIndexSignatures.ts, 31, 54)) ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -type T_OK4 = CheckBooleanOnly<(typeof strMap)[number]>; ->T_OK4 : Symbol(T_OK4, Decl(pedanticIndexSignatures.ts, 32, 62)) ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -type T_OK5 = CheckBooleanOnly<(typeof strMap)[any]>; ->T_OK5 : Symbol(T_OK5, Decl(pedanticIndexSignatures.ts, 33, 55)) ->CheckBooleanOnly : Symbol(CheckBooleanOnly, Decl(pedanticIndexSignatures.ts, 0, 0)) ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) - -// Writes don't allow 'undefined'; all should be errors -strMap["baz"] = undefined; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->undefined : Symbol(undefined) - -strMap.qua = undefined; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->undefined : Symbol(undefined) - -strMap[0] = undefined; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->undefined : Symbol(undefined) - -strMap[null as any] = undefined; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->undefined : Symbol(undefined) - -// Numeric lookups are unaffected -declare const numMap: { [s: number]: boolean }; ->numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 43, 25)) - -// All of these should be ok -const num_ok1: boolean = numMap[0]; ->num_ok1 : Symbol(num_ok1, Decl(pedanticIndexSignatures.ts, 45, 5)) ->numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) - -const num_ok2: boolean = numMap[0 as number]; ->num_ok2 : Symbol(num_ok2, Decl(pedanticIndexSignatures.ts, 46, 5)) ->numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) - -const num_ok3: boolean = numMap[0 as 0 | 1]; ->num_ok3 : Symbol(num_ok3, Decl(pedanticIndexSignatures.ts, 47, 5)) ->numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) - -const num_ok4: boolean = numMap[NumericEnum1.A]; ->num_ok4 : Symbol(num_ok4, Decl(pedanticIndexSignatures.ts, 48, 5)) ->numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) ->NumericEnum1.A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) ->NumericEnum1 : Symbol(NumericEnum1, Decl(pedanticIndexSignatures.ts, 2, 52)) ->A : Symbol(NumericEnum1.A, Decl(pedanticIndexSignatures.ts, 4, 19)) - -const num_ok5: boolean = numMap[NumericEnum2.A]; ->num_ok5 : Symbol(num_ok5, Decl(pedanticIndexSignatures.ts, 49, 5)) ->numMap : Symbol(numMap, Decl(pedanticIndexSignatures.ts, 43, 13)) ->NumericEnum2.A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) ->NumericEnum2 : Symbol(NumericEnum2, Decl(pedanticIndexSignatures.ts, 4, 29)) ->A : Symbol(NumericEnum2.A, Decl(pedanticIndexSignatures.ts, 5, 19)) - -// Generics -function generic1(arg: T): boolean { ->generic1 : Symbol(generic1, Decl(pedanticIndexSignatures.ts, 49, 48)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 52, 18)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 52, 31)) ->arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 52, 54)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 52, 18)) - - // Should error - return arg["blah"]; ->arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 52, 54)) -} -function generic2(arg: T): boolean { ->generic2 : Symbol(generic2, Decl(pedanticIndexSignatures.ts, 55, 1)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 56, 18)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 56, 31)) ->arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 56, 54)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 56, 18)) - - // Should OK - return arg["blah"]!; ->arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 56, 54)) -} -function generic3(arg: T): boolean { ->generic3 : Symbol(generic3, Decl(pedanticIndexSignatures.ts, 59, 1)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 60, 18)) ->arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 60, 36)) ->T : Symbol(T, Decl(pedanticIndexSignatures.ts, 60, 18)) - - // Should error - return strMap[arg]; ->strMap : Symbol(strMap, Decl(pedanticIndexSignatures.ts, 8, 13)) ->arg : Symbol(arg, Decl(pedanticIndexSignatures.ts, 60, 36)) -} - -// Element access into known properties is ok -declare const obj1: { x: string, y: number, [key: string]: string | number }; ->obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) ->x : Symbol(x, Decl(pedanticIndexSignatures.ts, 66, 21)) ->y : Symbol(y, Decl(pedanticIndexSignatures.ts, 66, 32)) ->key : Symbol(key, Decl(pedanticIndexSignatures.ts, 66, 45)) - -obj1["x"]; ->obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) ->"x" : Symbol(x, Decl(pedanticIndexSignatures.ts, 66, 21)) - -const y = "y"; ->y : Symbol(y, Decl(pedanticIndexSignatures.ts, 68, 5)) - -obj1[y]; ->obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) ->y : Symbol(y, Decl(pedanticIndexSignatures.ts, 68, 5)) - -let yy = "y"; ->yy : Symbol(yy, Decl(pedanticIndexSignatures.ts, 70, 3)) - -obj1[yy]; ->obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) ->yy : Symbol(yy, Decl(pedanticIndexSignatures.ts, 70, 3)) - -let z = "z"; ->z : Symbol(z, Decl(pedanticIndexSignatures.ts, 72, 3)) - -obj1[z]; ->obj1 : Symbol(obj1, Decl(pedanticIndexSignatures.ts, 66, 13)) ->z : Symbol(z, Decl(pedanticIndexSignatures.ts, 72, 3)) - -// Distributivity cases -declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; ->strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 76, 13)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 76, 30)) ->s : Symbol(s, Decl(pedanticIndexSignatures.ts, 76, 57)) - -// Should error -const f1: boolean | number = strMapUnion["foo"]; ->f1 : Symbol(f1, Decl(pedanticIndexSignatures.ts, 78, 5)) ->strMapUnion : Symbol(strMapUnion, Decl(pedanticIndexSignatures.ts, 76, 13)) - - diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/noUncheckedIndexedAccess/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/noUncheckedIndexedAccess/tsconfig.json new file mode 100644 index 0000000000000..32ae1e181cb05 --- /dev/null +++ b/tests/baselines/reference/showConfig/Shows tsconfig for single option/noUncheckedIndexedAccess/tsconfig.json @@ -0,0 +1,5 @@ +{ + "compilerOptions": { + "noUncheckedIndexedAccess": true + } +} diff --git a/tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json b/tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json deleted file mode 100644 index 1bdf01a277166..0000000000000 --- a/tests/baselines/reference/showConfig/Shows tsconfig for single option/pedanticIndexSignatures/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "pedanticIndexSignatures": true - } -} diff --git a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json index 23fc21a8414e0..5dcbbbcf920d7 100644 --- a/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Default initialized TSConfig/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json index 43fcfd6270bf0..6584a17cb1c6a 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with advanced options/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json index 07c59988e9acb..37b49d4c2c32c 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with boolean value compiler options/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json index f628900344519..fc9500915dbd2 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with enum value compiler options/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json index 4d07f29793bb9..46622ef0abb82 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with files options/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json index cf76560e711e9..1105491b9adf7 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option value/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json index 23fc21a8414e0..5dcbbbcf920d7 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with incorrect compiler option/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json index 1c622896419ad..9eb72e47a02e3 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options with enum value/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json index 53b477e7fe55e..7a9027f49da2d 100644 --- a/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json +++ b/tests/baselines/reference/tsConfig/Initialized TSConfig with list compiler options/tsconfig.json @@ -39,7 +39,7 @@ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js index 908c943b51802..fa7dc5795ae36 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js @@ -60,7 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js index b0ab8fcc3025a..036f14ce4d05a 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js @@ -60,7 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js index ad859947b9f73..7391dc46acc23 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js @@ -60,7 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js index 04a6d0aafa781..8c9312cfd0a12 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js @@ -60,7 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js index 4fad3c7344c98..5e5f0ccdfc7d5 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js @@ -60,7 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js index f5071fa2024c2..832ee4fdbfdc4 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js @@ -60,7 +60,7 @@ interface Array { length: number; [n: number]: T; } // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "pedanticIndexSignatures": true, /* Include 'undefined' in index signature results */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ diff --git a/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts b/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts similarity index 95% rename from tests/cases/conformance/pedantic/pedanticIndexSignatures.ts rename to tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts index 364702de9b6cb..21bcc2f3ec466 100644 --- a/tests/cases/conformance/pedantic/pedanticIndexSignatures.ts +++ b/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts @@ -1,5 +1,5 @@ // @strict: true -// @pedanticIndexSignatures: true +// @noUncheckedIndexedAccess: true type CheckBooleanOnly = any; // Validate CheckBooleanOnly works - should error diff --git a/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts b/tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts similarity index 94% rename from tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts rename to tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts index b67912f9deeee..8f50f31c5a9a0 100644 --- a/tests/cases/conformance/pedantic/pedanticIndexSignatureDestructuring.ts +++ b/tests/cases/conformance/pedantic/noUncheckedIndexedAccessDestructuring.ts @@ -1,5 +1,5 @@ // @strict: true -// @pedanticIndexSignatures: true +// @noUncheckedIndexedAccess: true declare const strArray: string[]; declare const strStrTuple: [string, string]; From 82190c1dd7360e18b1470243165463d1985bf4fd Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 10 Sep 2020 09:25:30 -0700 Subject: [PATCH 8/9] Add test for unique symbol indexing --- .../noUncheckedIndexedAccess.errors.txt | 10 ++++++++- .../reference/noUncheckedIndexedAccess.js | 7 +++++++ .../noUncheckedIndexedAccess.symbols | 18 ++++++++++++++++ .../reference/noUncheckedIndexedAccess.types | 21 +++++++++++++++++++ .../pedantic/noUncheckedIndexedAccess.ts | 5 +++++ 5 files changed, 60 insertions(+), 1 deletion(-) diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt b/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt index a5fa9ce94e754..9177245e367f3 100644 --- a/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt +++ b/tests/baselines/reference/noUncheckedIndexedAccess.errors.txt @@ -4,9 +4,10 @@ tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(38,1): error TS2322 tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(39,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(40,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(41,1): error TS2322: Type 'undefined' is not assignable to type 'boolean'. +tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(85,1): error TS2322: Type 'undefined' is not assignable to type 'string'. -==== tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts (5 errors) ==== +==== tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts (6 errors) ==== type CheckBooleanOnly = any; // Validate CheckBooleanOnly works - should error type T_ERR1 = CheckBooleanOnly; @@ -98,4 +99,11 @@ tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts(41,1): error TS2322 // Should error const f1: boolean | number = strMapUnion["foo"]; + // Symbol index signatures + declare const s: unique symbol; + declare const symbolMap: { [s]: string }; + const e15: string = symbolMap[s]; // Should OK + symbolMap[s] = undefined; // Should error + ~~~~~~~~~~~~ +!!! error TS2322: Type 'undefined' is not assignable to type 'string'. \ No newline at end of file diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.js b/tests/baselines/reference/noUncheckedIndexedAccess.js index 5fc004d9c5956..c03f4f76bb706 100644 --- a/tests/baselines/reference/noUncheckedIndexedAccess.js +++ b/tests/baselines/reference/noUncheckedIndexedAccess.js @@ -79,6 +79,11 @@ declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; // Should error const f1: boolean | number = strMapUnion["foo"]; +// Symbol index signatures +declare const s: unique symbol; +declare const symbolMap: { [s]: string }; +const e15: string = symbolMap[s]; // Should OK +symbolMap[s] = undefined; // Should error //// [noUncheckedIndexedAccess.js] @@ -151,3 +156,5 @@ var z = "z"; obj1[z]; // Should error var f1 = strMapUnion["foo"]; +var e15 = symbolMap[s]; // Should OK +symbolMap[s] = undefined; // Should error diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.symbols b/tests/baselines/reference/noUncheckedIndexedAccess.symbols index 21d52164dbc12..f8920d597599b 100644 --- a/tests/baselines/reference/noUncheckedIndexedAccess.symbols +++ b/tests/baselines/reference/noUncheckedIndexedAccess.symbols @@ -268,4 +268,22 @@ const f1: boolean | number = strMapUnion["foo"]; >f1 : Symbol(f1, Decl(noUncheckedIndexedAccess.ts, 78, 5)) >strMapUnion : Symbol(strMapUnion, Decl(noUncheckedIndexedAccess.ts, 76, 13)) +// Symbol index signatures +declare const s: unique symbol; +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 81, 13)) + +declare const symbolMap: { [s]: string }; +>symbolMap : Symbol(symbolMap, Decl(noUncheckedIndexedAccess.ts, 82, 13)) +>[s] : Symbol([s], Decl(noUncheckedIndexedAccess.ts, 82, 26)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 81, 13)) + +const e15: string = symbolMap[s]; // Should OK +>e15 : Symbol(e15, Decl(noUncheckedIndexedAccess.ts, 83, 5)) +>symbolMap : Symbol(symbolMap, Decl(noUncheckedIndexedAccess.ts, 82, 13)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 81, 13)) + +symbolMap[s] = undefined; // Should error +>symbolMap : Symbol(symbolMap, Decl(noUncheckedIndexedAccess.ts, 82, 13)) +>s : Symbol(s, Decl(noUncheckedIndexedAccess.ts, 81, 13)) +>undefined : Symbol(undefined) diff --git a/tests/baselines/reference/noUncheckedIndexedAccess.types b/tests/baselines/reference/noUncheckedIndexedAccess.types index 9a32cc7574100..1aa356cf5d16b 100644 --- a/tests/baselines/reference/noUncheckedIndexedAccess.types +++ b/tests/baselines/reference/noUncheckedIndexedAccess.types @@ -329,4 +329,25 @@ const f1: boolean | number = strMapUnion["foo"]; >strMapUnion : { [s: string]: boolean; } | { [s: string]: number; } >"foo" : "foo" +// Symbol index signatures +declare const s: unique symbol; +>s : unique symbol + +declare const symbolMap: { [s]: string }; +>symbolMap : { [s]: string; } +>[s] : string +>s : unique symbol + +const e15: string = symbolMap[s]; // Should OK +>e15 : string +>symbolMap[s] : string +>symbolMap : { [s]: string; } +>s : unique symbol + +symbolMap[s] = undefined; // Should error +>symbolMap[s] = undefined : undefined +>symbolMap[s] : string +>symbolMap : { [s]: string; } +>s : unique symbol +>undefined : undefined diff --git a/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts b/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts index 21bcc2f3ec466..8db2301566feb 100644 --- a/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts +++ b/tests/cases/conformance/pedantic/noUncheckedIndexedAccess.ts @@ -81,3 +81,8 @@ declare const strMapUnion: { [s: string]: boolean } | { [s: string]: number }; // Should error const f1: boolean | number = strMapUnion["foo"]; +// Symbol index signatures +declare const s: unique symbol; +declare const symbolMap: { [s]: string }; +const e15: string = symbolMap[s]; // Should OK +symbolMap[s] = undefined; // Should error From 544b69a186f632827f5e048dd735d734be613743 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Fri, 11 Sep 2020 14:09:54 -0700 Subject: [PATCH 9/9] Fix flag order in baselines --- tests/baselines/reference/api/tsserverlibrary.d.ts | 2 +- tests/baselines/reference/api/typescript.d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 220727f9b5aee..2e5b82492bac6 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2841,11 +2841,11 @@ declare namespace ts { assumeChangesOnlyAffectDirectDependencies?: boolean; noLib?: boolean; noResolve?: boolean; + noUncheckedIndexSignatures?: boolean; out?: string; outDir?: string; outFile?: string; paths?: MapLike; - noUncheckedIndexSignatures?: boolean; preserveConstEnums?: boolean; preserveSymlinks?: boolean; project?: string; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index bb3c5c9c2cb3c..5810c60b4672b 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2841,11 +2841,11 @@ declare namespace ts { assumeChangesOnlyAffectDirectDependencies?: boolean; noLib?: boolean; noResolve?: boolean; + noUncheckedIndexSignatures?: boolean; out?: string; outDir?: string; outFile?: string; paths?: MapLike; - noUncheckedIndexSignatures?: boolean; preserveConstEnums?: boolean; preserveSymlinks?: boolean; project?: string;