mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-14 19:16:17 -06:00
Merge pull request #12514 from Microsoft/keyofAndForIn
Fix issues related to 'keyof' with 'for-in' and 'in' operator
This commit is contained in:
commit
283c50c183
@ -3205,7 +3205,7 @@ namespace ts {
|
||||
// right hand expression is of a type parameter type.
|
||||
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
|
||||
const indexType = getIndexType(checkNonNullExpression((<ForInStatement>declaration.parent.parent).expression));
|
||||
return indexType.flags & TypeFlags.Index ? indexType : stringType;
|
||||
return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? indexType : stringType;
|
||||
}
|
||||
|
||||
if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
|
||||
@ -5920,6 +5920,11 @@ namespace ts {
|
||||
getLiteralTypeFromPropertyNames(type);
|
||||
}
|
||||
|
||||
function getIndexTypeOrString(type: Type): Type {
|
||||
const indexType = getIndexType(type);
|
||||
return indexType !== neverType ? indexType : stringType;
|
||||
}
|
||||
|
||||
function getTypeFromTypeOperatorNode(node: TypeOperatorNode) {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
@ -6018,8 +6023,7 @@ namespace ts {
|
||||
// meaningfully access the properties of the object type. In those cases, we first check that the
|
||||
// index type is assignable to 'keyof T' for the object type.
|
||||
if (accessNode) {
|
||||
const keyType = indexType.flags & TypeFlags.TypeParameter ? getConstraintOfTypeParameter(<TypeParameter>indexType) || emptyObjectType : indexType;
|
||||
if (!isTypeAssignableTo(keyType, getIndexType(objectType))) {
|
||||
if (!isTypeAssignableTo(indexType, getIndexType(objectType))) {
|
||||
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
|
||||
return unknownType;
|
||||
}
|
||||
@ -14275,7 +14279,7 @@ namespace ts {
|
||||
// The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
|
||||
// and the right operand to be of type Any, an object type, or a type parameter type.
|
||||
// The result is always of the Boolean primitive type.
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
|
||||
if (!(isTypeComparableTo(leftType, stringType) || isTypeOfKind(leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) {
|
||||
error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
|
||||
}
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) {
|
||||
@ -17166,6 +17170,7 @@ namespace ts {
|
||||
// Grammar checking
|
||||
checkGrammarForInOrForOfStatement(node);
|
||||
|
||||
const rightType = checkNonNullExpression(node.expression);
|
||||
// TypeScript 1.0 spec (April 2014): 5.4
|
||||
// In a 'for-in' statement of the form
|
||||
// for (let VarDecl in Expr) Statement
|
||||
@ -17176,7 +17181,6 @@ namespace ts {
|
||||
if (variable && isBindingPattern(variable.name)) {
|
||||
error(variable.name, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
|
||||
}
|
||||
|
||||
checkForInOrForOfVariableDeclaration(node);
|
||||
}
|
||||
else {
|
||||
@ -17189,7 +17193,7 @@ namespace ts {
|
||||
if (varExpr.kind === SyntaxKind.ArrayLiteralExpression || varExpr.kind === SyntaxKind.ObjectLiteralExpression) {
|
||||
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_cannot_be_a_destructuring_pattern);
|
||||
}
|
||||
else if (!isTypeAnyOrAllConstituentTypesHaveKind(leftType, TypeFlags.StringLike)) {
|
||||
else if (!isTypeAssignableTo(getIndexTypeOrString(rightType), leftType)) {
|
||||
error(varExpr, Diagnostics.The_left_hand_side_of_a_for_in_statement_must_be_of_type_string_or_any);
|
||||
}
|
||||
else {
|
||||
@ -17198,7 +17202,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const rightType = checkNonNullExpression(node.expression);
|
||||
// unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
|
||||
// in this case error about missing name is already reported - do not report extra one
|
||||
if (!isTypeAnyOrAllConstituentTypesHaveKind(rightType, TypeFlags.Object | TypeFlags.TypeParameter | TypeFlags.IndexedAccess)) {
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(12,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(13,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(14,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(16,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(17,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(19,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(20,11): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(30,16): error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
|
||||
@ -19,7 +17,7 @@ tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInv
|
||||
tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts(43,17): error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts (19 errors) ====
|
||||
==== tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInvalidOperands.ts (17 errors) ====
|
||||
enum E { a }
|
||||
|
||||
var x: any;
|
||||
@ -42,11 +40,7 @@ tests/cases/conformance/expressions/binaryOperators/inOperator/inOperatorWithInv
|
||||
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
var ra4 = a4 in x;
|
||||
var ra5 = null in x;
|
||||
~~~~
|
||||
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
var ra6 = undefined in x;
|
||||
~~~~~~~~~
|
||||
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
var ra7 = E.a in x;
|
||||
var ra8 = false in x;
|
||||
~~~~~
|
||||
|
||||
81
tests/baselines/reference/keyofAndForIn.js
Normal file
81
tests/baselines/reference/keyofAndForIn.js
Normal file
@ -0,0 +1,81 @@
|
||||
//// [keyofAndForIn.ts]
|
||||
|
||||
// Repro from #12513
|
||||
|
||||
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
|
||||
const b = k in obj;
|
||||
let k1: K;
|
||||
for (k1 in obj) {
|
||||
let x1 = obj[k1];
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
let x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
|
||||
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
|
||||
const b = k in obj;
|
||||
let k1: keyof T;
|
||||
for (k1 in obj) {
|
||||
let x1 = obj[k1];
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
let x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
|
||||
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
|
||||
const b = k in obj;
|
||||
let k1: K;
|
||||
for (k1 in obj) {
|
||||
let x1 = obj[k1];
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
let x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
|
||||
//// [keyofAndForIn.js]
|
||||
// Repro from #12513
|
||||
function f1(obj, k) {
|
||||
var b = k in obj;
|
||||
var k1;
|
||||
for (k1 in obj) {
|
||||
var x1 = obj[k1];
|
||||
}
|
||||
for (var k2 in obj) {
|
||||
var x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
function f2(obj, k) {
|
||||
var b = k in obj;
|
||||
var k1;
|
||||
for (k1 in obj) {
|
||||
var x1 = obj[k1];
|
||||
}
|
||||
for (var k2 in obj) {
|
||||
var x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
function f3(obj, k) {
|
||||
var b = k in obj;
|
||||
var k1;
|
||||
for (k1 in obj) {
|
||||
var x1 = obj[k1];
|
||||
}
|
||||
for (var k2 in obj) {
|
||||
var x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [keyofAndForIn.d.ts]
|
||||
declare function f1<K extends string, T>(obj: {
|
||||
[P in K]: T;
|
||||
}, k: K): void;
|
||||
declare function f2<T>(obj: {
|
||||
[P in keyof T]: T[P];
|
||||
}, k: keyof T): void;
|
||||
declare function f3<T, K extends keyof T>(obj: {
|
||||
[P in K]: T[P];
|
||||
}, k: K): void;
|
||||
125
tests/baselines/reference/keyofAndForIn.symbols
Normal file
125
tests/baselines/reference/keyofAndForIn.symbols
Normal file
@ -0,0 +1,125 @@
|
||||
=== tests/cases/conformance/types/keyof/keyofAndForIn.ts ===
|
||||
|
||||
// Repro from #12513
|
||||
|
||||
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
|
||||
>f1 : Symbol(f1, Decl(keyofAndForIn.ts, 0, 0))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 3, 29))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
|
||||
>P : Symbol(P, Decl(keyofAndForIn.ts, 3, 41))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 3, 29))
|
||||
>k : Symbol(k, Decl(keyofAndForIn.ts, 3, 54))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
|
||||
|
||||
const b = k in obj;
|
||||
>b : Symbol(b, Decl(keyofAndForIn.ts, 4, 9))
|
||||
>k : Symbol(k, Decl(keyofAndForIn.ts, 3, 54))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
|
||||
|
||||
let k1: K;
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 5, 7))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 3, 12))
|
||||
|
||||
for (k1 in obj) {
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 5, 7))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : Symbol(x1, Decl(keyofAndForIn.ts, 7, 11))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 5, 7))
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 9, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : Symbol(x2, Decl(keyofAndForIn.ts, 10, 11))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 3, 33))
|
||||
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 9, 12))
|
||||
}
|
||||
}
|
||||
|
||||
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
|
||||
>f2 : Symbol(f2, Decl(keyofAndForIn.ts, 12, 1))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
|
||||
>P : Symbol(P, Decl(keyofAndForIn.ts, 14, 23))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
|
||||
>P : Symbol(P, Decl(keyofAndForIn.ts, 14, 23))
|
||||
>k : Symbol(k, Decl(keyofAndForIn.ts, 14, 45))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
|
||||
|
||||
const b = k in obj;
|
||||
>b : Symbol(b, Decl(keyofAndForIn.ts, 15, 9))
|
||||
>k : Symbol(k, Decl(keyofAndForIn.ts, 14, 45))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
|
||||
|
||||
let k1: keyof T;
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 16, 7))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 14, 12))
|
||||
|
||||
for (k1 in obj) {
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 16, 7))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : Symbol(x1, Decl(keyofAndForIn.ts, 18, 11))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 16, 7))
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 20, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : Symbol(x2, Decl(keyofAndForIn.ts, 21, 11))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 14, 15))
|
||||
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 20, 12))
|
||||
}
|
||||
}
|
||||
|
||||
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
|
||||
>f3 : Symbol(f3, Decl(keyofAndForIn.ts, 23, 1))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 25, 12))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 25, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
|
||||
>P : Symbol(P, Decl(keyofAndForIn.ts, 25, 42))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
|
||||
>T : Symbol(T, Decl(keyofAndForIn.ts, 25, 12))
|
||||
>P : Symbol(P, Decl(keyofAndForIn.ts, 25, 42))
|
||||
>k : Symbol(k, Decl(keyofAndForIn.ts, 25, 58))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
|
||||
|
||||
const b = k in obj;
|
||||
>b : Symbol(b, Decl(keyofAndForIn.ts, 26, 9))
|
||||
>k : Symbol(k, Decl(keyofAndForIn.ts, 25, 58))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
|
||||
|
||||
let k1: K;
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 27, 7))
|
||||
>K : Symbol(K, Decl(keyofAndForIn.ts, 25, 14))
|
||||
|
||||
for (k1 in obj) {
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 27, 7))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : Symbol(x1, Decl(keyofAndForIn.ts, 29, 11))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
|
||||
>k1 : Symbol(k1, Decl(keyofAndForIn.ts, 27, 7))
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 31, 12))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : Symbol(x2, Decl(keyofAndForIn.ts, 32, 11))
|
||||
>obj : Symbol(obj, Decl(keyofAndForIn.ts, 25, 34))
|
||||
>k2 : Symbol(k2, Decl(keyofAndForIn.ts, 31, 12))
|
||||
}
|
||||
}
|
||||
134
tests/baselines/reference/keyofAndForIn.types
Normal file
134
tests/baselines/reference/keyofAndForIn.types
Normal file
@ -0,0 +1,134 @@
|
||||
=== tests/cases/conformance/types/keyof/keyofAndForIn.ts ===
|
||||
|
||||
// Repro from #12513
|
||||
|
||||
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
|
||||
>f1 : <K extends string, T>(obj: { [P in K]: T; }, k: K) => void
|
||||
>K : K
|
||||
>T : T
|
||||
>obj : { [P in K]: T; }
|
||||
>P : P
|
||||
>K : K
|
||||
>T : T
|
||||
>k : K
|
||||
>K : K
|
||||
|
||||
const b = k in obj;
|
||||
>b : boolean
|
||||
>k in obj : boolean
|
||||
>k : K
|
||||
>obj : { [P in K]: T; }
|
||||
|
||||
let k1: K;
|
||||
>k1 : K
|
||||
>K : K
|
||||
|
||||
for (k1 in obj) {
|
||||
>k1 : K
|
||||
>obj : { [P in K]: T; }
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : T
|
||||
>obj[k1] : T
|
||||
>obj : { [P in K]: T; }
|
||||
>k1 : K
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
>k2 : K
|
||||
>obj : { [P in K]: T; }
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : T
|
||||
>obj[k2] : T
|
||||
>obj : { [P in K]: T; }
|
||||
>k2 : K
|
||||
}
|
||||
}
|
||||
|
||||
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
|
||||
>f2 : <T>(obj: { [P in keyof T]: T[P]; }, k: keyof T) => void
|
||||
>T : T
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
>P : P
|
||||
>T : T
|
||||
>T : T
|
||||
>P : P
|
||||
>k : keyof T
|
||||
>T : T
|
||||
|
||||
const b = k in obj;
|
||||
>b : boolean
|
||||
>k in obj : boolean
|
||||
>k : keyof T
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
|
||||
let k1: keyof T;
|
||||
>k1 : keyof T
|
||||
>T : T
|
||||
|
||||
for (k1 in obj) {
|
||||
>k1 : keyof T
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : T[keyof T]
|
||||
>obj[k1] : T[keyof T]
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
>k1 : keyof T
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
>k2 : keyof T
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : T[keyof T]
|
||||
>obj[k2] : T[keyof T]
|
||||
>obj : { [P in keyof T]: T[P]; }
|
||||
>k2 : keyof T
|
||||
}
|
||||
}
|
||||
|
||||
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
|
||||
>f3 : <T, K extends keyof T>(obj: { [P in K]: T[P]; }, k: K) => void
|
||||
>T : T
|
||||
>K : K
|
||||
>T : T
|
||||
>obj : { [P in K]: T[P]; }
|
||||
>P : P
|
||||
>K : K
|
||||
>T : T
|
||||
>P : P
|
||||
>k : K
|
||||
>K : K
|
||||
|
||||
const b = k in obj;
|
||||
>b : boolean
|
||||
>k in obj : boolean
|
||||
>k : K
|
||||
>obj : { [P in K]: T[P]; }
|
||||
|
||||
let k1: K;
|
||||
>k1 : K
|
||||
>K : K
|
||||
|
||||
for (k1 in obj) {
|
||||
>k1 : K
|
||||
>obj : { [P in K]: T[P]; }
|
||||
|
||||
let x1 = obj[k1];
|
||||
>x1 : T[K]
|
||||
>obj[k1] : T[K]
|
||||
>obj : { [P in K]: T[P]; }
|
||||
>k1 : K
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
>k2 : K
|
||||
>obj : { [P in K]: T[P]; }
|
||||
|
||||
let x2 = obj[k2];
|
||||
>x2 : T[K]
|
||||
>obj[k2] : T[K]
|
||||
>obj : { [P in K]: T[P]; }
|
||||
>k2 : K
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
tests/cases/compiler/widenedTypes.ts(2,1): error TS2358: The left-hand side of an 'instanceof' expression must be of type 'any', an object type or a type parameter.
|
||||
tests/cases/compiler/widenedTypes.ts(5,1): error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
tests/cases/compiler/widenedTypes.ts(6,7): error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
|
||||
tests/cases/compiler/widenedTypes.ts(8,15): error TS2407: The right-hand side of a 'for...in' statement must be of type 'any', an object type or a type parameter.
|
||||
tests/cases/compiler/widenedTypes.ts(10,14): error TS2695: Left side of comma operator is unused and has no side effects.
|
||||
@ -12,7 +11,7 @@ tests/cases/compiler/widenedTypes.ts(24,5): error TS2322: Type '{ x: number; y:
|
||||
Type 'number' is not assignable to type 'string'.
|
||||
|
||||
|
||||
==== tests/cases/compiler/widenedTypes.ts (9 errors) ====
|
||||
==== tests/cases/compiler/widenedTypes.ts (8 errors) ====
|
||||
|
||||
null instanceof (() => { });
|
||||
~~~~
|
||||
@ -20,8 +19,6 @@ tests/cases/compiler/widenedTypes.ts(24,5): error TS2322: Type '{ x: number; y:
|
||||
({}) instanceof null; // Ok because null is a subtype of function
|
||||
|
||||
null in {};
|
||||
~~~~
|
||||
!!! error TS2360: The left-hand side of an 'in' expression must be of type 'any', 'string', 'number', or 'symbol'.
|
||||
"" in null;
|
||||
~~~~
|
||||
!!! error TS2361: The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter
|
||||
|
||||
36
tests/cases/conformance/types/keyof/keyofAndForIn.ts
Normal file
36
tests/cases/conformance/types/keyof/keyofAndForIn.ts
Normal file
@ -0,0 +1,36 @@
|
||||
// @declaration: true
|
||||
|
||||
// Repro from #12513
|
||||
|
||||
function f1<K extends string, T>(obj: { [P in K]: T }, k: K) {
|
||||
const b = k in obj;
|
||||
let k1: K;
|
||||
for (k1 in obj) {
|
||||
let x1 = obj[k1];
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
let x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
|
||||
function f2<T>(obj: { [P in keyof T]: T[P] }, k: keyof T) {
|
||||
const b = k in obj;
|
||||
let k1: keyof T;
|
||||
for (k1 in obj) {
|
||||
let x1 = obj[k1];
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
let x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
|
||||
function f3<T, K extends keyof T>(obj: { [P in K]: T[P] }, k: K) {
|
||||
const b = k in obj;
|
||||
let k1: K;
|
||||
for (k1 in obj) {
|
||||
let x1 = obj[k1];
|
||||
}
|
||||
for (let k2 in obj) {
|
||||
let x2 = obj[k2];
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user