fix(25770): add diagnostic message for the possible mapped type used as an index (#39973)

This commit is contained in:
Alexander T
2020-08-21 10:42:48 -07:00
committed by GitHub
parent 6ec3629ef4
commit 9569198df6
7 changed files with 251 additions and 4 deletions
+20 -4
View File
@@ -2243,16 +2243,32 @@ namespace ts {
}
const symbol = resolveSymbol(resolveName(errorLocation, name, SymbolFlags.Type & ~SymbolFlags.Value, /*nameNotFoundMessage*/undefined, /*nameArg*/ undefined, /*isUse*/ false));
if (symbol && !(symbol.flags & SymbolFlags.NamespaceModule)) {
const message = isES2015OrLaterConstructorName(name)
? Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later
: Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here;
error(errorLocation, message, unescapeLeadingUnderscores(name));
const rawName = unescapeLeadingUnderscores(name);
if (isES2015OrLaterConstructorName(name)) {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, rawName);
}
else if (maybeMappedType(errorLocation, symbol)) {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, rawName, rawName === "K" ? "P" : "K");
}
else {
error(errorLocation, Diagnostics._0_only_refers_to_a_type_but_is_being_used_as_a_value_here, rawName);
}
return true;
}
}
return false;
}
function maybeMappedType(node: Node, symbol: Symbol) {
const container = findAncestor(node.parent, n =>
isComputedPropertyName(n) || isPropertySignature(n) ? false : isTypeLiteralNode(n) || "quit") as TypeLiteralNode | undefined;
if (container && container.members.length === 1) {
const type = getDeclaredTypeOfSymbol(symbol);
return !!(type.flags & TypeFlags.Union) && allTypesAssignableToKind(type, TypeFlags.StringOrNumberLiteral, /*strict*/ true);
}
return false;
}
function isES2015OrLaterConstructorName(n: __String) {
switch (n) {
case "Promise":
+4
View File
@@ -2607,6 +2607,10 @@
"category": "Error",
"code": 2689
},
"'{0}' only refers to a type, but is being used as a value here. Did you mean to use '{1} in {0}'?": {
"category": "Error",
"code": 2690
},
"An import path cannot end with a '{0}' extension. Consider importing '{1}' instead.": {
"category": "Error",
"code": 2691
@@ -0,0 +1,53 @@
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(3,5): error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(3,6): error TS2690: 'K' only refers to a type, but is being used as a value here. Did you mean to use 'P in K'?
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(13,5): error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(13,6): error TS2690: 'K2' only refers to a type, but is being used as a value here. Did you mean to use 'K in K2'?
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(18,5): error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(18,6): error TS2690: 'K3' only refers to a type, but is being used as a value here. Did you mean to use 'K in K3'?
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(23,5): error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts(23,6): error TS2693: 'K4' only refers to a type, but is being used as a value here.
==== tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts (8 errors) ====
type K = number | string;
type T = {
[K]: number; // Did you mean to use 'P in K'?
~~~
!!! error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
~
!!! error TS2690: 'K' only refers to a type, but is being used as a value here. Did you mean to use 'P in K'?
}
const K1 = Symbol();
type T1 = {
[K1]: number;
}
type K2 = "x" | "y";
type T2 = {
[K2]: number; // Did you mean to use 'K in K2'?
~~~~
!!! error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
~~
!!! error TS2690: 'K2' only refers to a type, but is being used as a value here. Did you mean to use 'K in K2'?
}
type K3 = number | string;
type T3 = {
[K3]: number; // Did you mean to use 'K in K3'?
~~~~
!!! error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
~~
!!! error TS2690: 'K3' only refers to a type, but is being used as a value here. Did you mean to use 'K in K3'?
}
type K4 = number | string;
type T4 = {
[K4]: number;
~~~~
!!! error TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
~~
!!! error TS2693: 'K4' only refers to a type, but is being used as a value here.
k4: string;
}
@@ -0,0 +1,30 @@
//// [typeUsedAsTypeLiteralIndex.ts]
type K = number | string;
type T = {
[K]: number; // Did you mean to use 'P in K'?
}
const K1 = Symbol();
type T1 = {
[K1]: number;
}
type K2 = "x" | "y";
type T2 = {
[K2]: number; // Did you mean to use 'K in K2'?
}
type K3 = number | string;
type T3 = {
[K3]: number; // Did you mean to use 'K in K3'?
}
type K4 = number | string;
type T4 = {
[K4]: number;
k4: string;
}
//// [typeUsedAsTypeLiteralIndex.js]
const K1 = Symbol();
@@ -0,0 +1,56 @@
=== tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts ===
type K = number | string;
>K : Symbol(K, Decl(typeUsedAsTypeLiteralIndex.ts, 0, 0))
type T = {
>T : Symbol(T, Decl(typeUsedAsTypeLiteralIndex.ts, 0, 25))
[K]: number; // Did you mean to use 'P in K'?
>[K] : Symbol([K], Decl(typeUsedAsTypeLiteralIndex.ts, 1, 10))
}
const K1 = Symbol();
>K1 : Symbol(K1, Decl(typeUsedAsTypeLiteralIndex.ts, 5, 5))
>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --))
type T1 = {
>T1 : Symbol(T1, Decl(typeUsedAsTypeLiteralIndex.ts, 5, 20))
[K1]: number;
>[K1] : Symbol([K1], Decl(typeUsedAsTypeLiteralIndex.ts, 6, 11))
>K1 : Symbol(K1, Decl(typeUsedAsTypeLiteralIndex.ts, 5, 5))
}
type K2 = "x" | "y";
>K2 : Symbol(K2, Decl(typeUsedAsTypeLiteralIndex.ts, 8, 1))
type T2 = {
>T2 : Symbol(T2, Decl(typeUsedAsTypeLiteralIndex.ts, 10, 20))
[K2]: number; // Did you mean to use 'K in K2'?
>[K2] : Symbol([K2], Decl(typeUsedAsTypeLiteralIndex.ts, 11, 11))
}
type K3 = number | string;
>K3 : Symbol(K3, Decl(typeUsedAsTypeLiteralIndex.ts, 13, 1))
type T3 = {
>T3 : Symbol(T3, Decl(typeUsedAsTypeLiteralIndex.ts, 15, 26))
[K3]: number; // Did you mean to use 'K in K3'?
>[K3] : Symbol([K3], Decl(typeUsedAsTypeLiteralIndex.ts, 16, 11))
}
type K4 = number | string;
>K4 : Symbol(K4, Decl(typeUsedAsTypeLiteralIndex.ts, 18, 1))
type T4 = {
>T4 : Symbol(T4, Decl(typeUsedAsTypeLiteralIndex.ts, 20, 26))
[K4]: number;
>[K4] : Symbol([K4], Decl(typeUsedAsTypeLiteralIndex.ts, 21, 11))
k4: string;
>k4 : Symbol(k4, Decl(typeUsedAsTypeLiteralIndex.ts, 22, 17))
}
@@ -0,0 +1,61 @@
=== tests/cases/compiler/typeUsedAsTypeLiteralIndex.ts ===
type K = number | string;
>K : K
type T = {
>T : T
[K]: number; // Did you mean to use 'P in K'?
>[K] : number
>K : any
}
const K1 = Symbol();
>K1 : unique symbol
>Symbol() : unique symbol
>Symbol : SymbolConstructor
type T1 = {
>T1 : T1
[K1]: number;
>[K1] : number
>K1 : unique symbol
}
type K2 = "x" | "y";
>K2 : K2
type T2 = {
>T2 : T2
[K2]: number; // Did you mean to use 'K in K2'?
>[K2] : number
>K2 : any
}
type K3 = number | string;
>K3 : K
type T3 = {
>T3 : T3
[K3]: number; // Did you mean to use 'K in K3'?
>[K3] : number
>K3 : any
}
type K4 = number | string;
>K4 : K
type T4 = {
>T4 : T4
[K4]: number;
>[K4] : number
>K4 : any
k4: string;
>k4 : string
}
@@ -0,0 +1,27 @@
// @target: esnext
type K = number | string;
type T = {
[K]: number; // Did you mean to use 'P in K'?
}
const K1 = Symbol();
type T1 = {
[K1]: number;
}
type K2 = "x" | "y";
type T2 = {
[K2]: number; // Did you mean to use 'K in K2'?
}
type K3 = number | string;
type T3 = {
[K3]: number; // Did you mean to use 'K in K3'?
}
type K4 = number | string;
type T4 = {
[K4]: number;
k4: string;
}