Skip to content

Commit 76ceab9

Browse files
committed
Make keyof T a string-like type
1 parent 110c3ac commit 76ceab9

File tree

2 files changed

+8
-20
lines changed

2 files changed

+8
-20
lines changed

src/compiler/checker.ts

Lines changed: 7 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ namespace ts {
142142
const voidType = createIntrinsicType(TypeFlags.Void, "void");
143143
const neverType = createIntrinsicType(TypeFlags.Never, "never");
144144
const silentNeverType = createIntrinsicType(TypeFlags.Never, "never");
145-
const stringOrNumberType = getUnionType([stringType, numberType]);
146145

147146
const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
148147

@@ -3219,6 +3218,8 @@ namespace ts {
32193218

32203219
// A variable declared in a for..in statement is always of type string
32213220
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
3221+
// const indexType = getIndexType(checkNonNullExpression((<ForInStatement>declaration.parent.parent).expression));
3222+
// return indexType.flags & TypeFlags.Index ? indexType : stringType;
32223223
return stringType;
32233224
}
32243225

@@ -4688,7 +4689,6 @@ namespace ts {
46884689
t.flags & TypeFlags.NumberLike ? globalNumberType :
46894690
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
46904691
t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() :
4691-
t.flags & TypeFlags.Index ? stringOrNumberType :
46924692
t;
46934693
}
46944694

@@ -5920,8 +5920,7 @@ namespace ts {
59205920
function getIndexType(type: Type): Type {
59215921
return type.flags & TypeFlags.TypeParameter ? getIndexTypeForTypeParameter(<TypeParameter>type) :
59225922
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
5923-
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringOrNumberType :
5924-
getIndexInfoOfType(type, IndexKind.Number) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type)]) :
5923+
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :
59255924
getLiteralTypeFromPropertyNames(type);
59265925
}
59275926

@@ -6040,10 +6039,9 @@ namespace ts {
60406039
return indexedAccessTypes[id] || (indexedAccessTypes[id] = createIndexedAccessType(objectType, indexType));
60416040
}
60426041
const apparentObjectType = getApparentType(objectType);
6043-
const apparentIndexType = indexType.flags & TypeFlags.Index ? stringOrNumberType : indexType;
6044-
if (apparentIndexType.flags & TypeFlags.Union && !(apparentIndexType.flags & TypeFlags.Primitive)) {
6042+
if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Primitive)) {
60456043
const propTypes: Type[] = [];
6046-
for (const t of (<UnionType>apparentIndexType).types) {
6044+
for (const t of (<UnionType>indexType).types) {
60476045
const propType = getPropertyTypeForIndexType(apparentObjectType, t, accessNode, /*cacheSymbol*/ false);
60486046
if (propType === unknownType) {
60496047
return unknownType;
@@ -6052,7 +6050,7 @@ namespace ts {
60526050
}
60536051
return getUnionType(propTypes);
60546052
}
6055-
return getPropertyTypeForIndexType(apparentObjectType, apparentIndexType, accessNode, /*cacheSymbol*/ true);
6053+
return getPropertyTypeForIndexType(apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true);
60566054
}
60576055

60586056
function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
@@ -7124,16 +7122,6 @@ namespace ts {
71247122

71257123
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
71267124

7127-
if (source.flags & TypeFlags.Index) {
7128-
// A keyof T is related to a union type containing both string and number
7129-
const related = relation === comparableRelation ?
7130-
maybeTypeOfKind(target, TypeFlags.String | TypeFlags.Number) :
7131-
maybeTypeOfKind(target, TypeFlags.String) && maybeTypeOfKind(target, TypeFlags.Number);
7132-
if (related) {
7133-
return Ternary.True;
7134-
}
7135-
}
7136-
71377125
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
71387126
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
71397127
if (reportErrors) {
@@ -15654,7 +15642,7 @@ namespace ts {
1565415642
const type = <MappedType>getTypeFromMappedTypeNode(node);
1565515643
const constraintType = getConstraintTypeFromMappedType(type);
1565615644
const keyType = constraintType.flags & TypeFlags.TypeParameter ? getApparentTypeOfTypeParameter(<TypeParameter>constraintType) : constraintType;
15657-
checkTypeAssignableTo(keyType, stringOrNumberType, node.typeParameter.constraint);
15645+
checkTypeAssignableTo(keyType, stringType, node.typeParameter.constraint);
1565815646
}
1565915647

1566015648
function isPrivateWithinAmbient(node: Node): boolean {

src/compiler/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2789,7 +2789,7 @@ namespace ts {
27892789
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never,
27902790
/* @internal */
27912791
Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal,
2792-
StringLike = String | StringLiteral,
2792+
StringLike = String | StringLiteral | Index,
27932793
NumberLike = Number | NumberLiteral | Enum | EnumLiteral,
27942794
BooleanLike = Boolean | BooleanLiteral,
27952795
EnumLike = Enum | EnumLiteral,

0 commit comments

Comments
 (0)