Skip to content

Commit 4798de0

Browse files
committed
Integrate a version of indexed access setup into the instantiation trampoline
1 parent 83eeab6 commit 4798de0

File tree

1 file changed

+100
-2
lines changed

1 file changed

+100
-2
lines changed

src/compiler/checker.ts

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6026,6 +6026,21 @@ namespace ts {
60266026
return links.type;
60276027
}
60286028

6029+
function* getInstantiatedTypeOfInstantiatedSymbol(symbol: Symbol): Generator<[Type, TypeMapper], Type, Type> {
6030+
const links = getSymbolLinks(symbol);
6031+
if (!links.type) {
6032+
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
6033+
return links.type = errorType;
6034+
}
6035+
let type = yield [yield* getInstantiatedTypeOfSymbol(links.target!), links.mapper!];
6036+
if (!popTypeResolution()) {
6037+
type = reportCircularityError(symbol);
6038+
}
6039+
links.type = type;
6040+
}
6041+
return links.type;
6042+
}
6043+
60296044
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
60306045
const links = getSymbolLinks(symbol);
60316046
if (!links.type) {
@@ -6070,6 +6085,16 @@ namespace ts {
60706085
return links.type;
60716086
}
60726087

6088+
function* getInstantiatedTypeOfSymbol(symbol: Symbol): Generator<[Type, TypeMapper], Type, Type> {
6089+
if (getCheckFlags(symbol) & CheckFlags.DeferredType) {
6090+
return getTypeOfSymbolWithDeferredType(symbol);
6091+
}
6092+
if (getCheckFlags(symbol) & CheckFlags.Instantiated) {
6093+
return yield* getInstantiatedTypeOfInstantiatedSymbol(symbol);
6094+
}
6095+
return getTypeOfSymbol(symbol);
6096+
}
6097+
60736098
function getTypeOfSymbol(symbol: Symbol): Type {
60746099
if (getCheckFlags(symbol) & CheckFlags.DeferredType) {
60756100
return getTypeOfSymbolWithDeferredType(symbol);
@@ -10258,6 +10283,45 @@ namespace ts {
1025810283
undefined;
1025910284
}
1026010285

10286+
function* getInstantiatedPropertyTypeForIndexType(objectType: Type, indexType: Type, accessFlags: AccessFlags): Generator<[Type, TypeMapper], Type | undefined, Type> {
10287+
const propName = getPropertyNameFromIndex(indexType, /*accessNode*/ undefined);
10288+
if (propName !== undefined) {
10289+
const prop = getPropertyOfType(objectType, propName);
10290+
if (prop) {
10291+
return yield* getInstantiatedTypeOfSymbol(prop);
10292+
}
10293+
if (everyType(objectType, isTupleType) && isNumericLiteralName(propName) && +propName >= 0) {
10294+
return mapType(objectType, t => getRestTypeOfTupleType(<TupleTypeReference>t) || undefinedType);
10295+
}
10296+
}
10297+
if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind(indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbolLike)) {
10298+
if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) {
10299+
return objectType;
10300+
}
10301+
const stringIndexInfo = getIndexInfoOfType(objectType, IndexKind.String);
10302+
const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) || stringIndexInfo;
10303+
if (indexInfo) {
10304+
if (accessFlags & AccessFlags.NoIndexSignatures && indexInfo === stringIndexInfo) {
10305+
return undefined;
10306+
}
10307+
return indexInfo.type;
10308+
}
10309+
if (indexType.flags & TypeFlags.Never) {
10310+
return neverType;
10311+
}
10312+
if (isJSLiteralType(objectType)) {
10313+
return anyType;
10314+
}
10315+
}
10316+
if (isJSLiteralType(objectType)) {
10317+
return anyType;
10318+
}
10319+
if (isTypeAny(indexType)) {
10320+
return indexType;
10321+
}
10322+
return undefined;
10323+
}
10324+
1026110325
function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, fullIndexType: Type, suppressNoImplicitAnyError: boolean, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, accessFlags: AccessFlags) {
1026210326
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
1026310327
const propName = getPropertyNameFromIndex(indexType, accessNode);
@@ -10532,7 +10596,7 @@ namespace ts {
1053210596
return getIndexedAccessTypeOrUndefined(objectType, indexType, accessNode, AccessFlags.None) || (accessNode ? errorType : unknownType);
1053310597
}
1053410598

10535-
function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, accessFlags = AccessFlags.None): Type | undefined {
10599+
function getSimpleOrGenericIndexedAccess(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression): Type | undefined {
1053610600
if (objectType === wildcardType || indexType === wildcardType) {
1053710601
return wildcardType;
1053810602
}
@@ -10558,6 +10622,40 @@ namespace ts {
1055810622
}
1055910623
return type;
1056010624
}
10625+
}
10626+
10627+
function* getInstantiatedIndexedAccessType(objectType: Type, indexType: Type, accessFlags = AccessFlags.None): Generator<[Type, TypeMapper], Type | undefined, Type> {
10628+
const simple = getSimpleOrGenericIndexedAccess(objectType, indexType);
10629+
if (simple) {
10630+
return simple;
10631+
}
10632+
10633+
// In the following we resolve T[K] to the type of the property in T selected by K.
10634+
// We treat boolean as different from other unions to improve errors;
10635+
// skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'.
10636+
const apparentObjectType = getApparentType(objectType);
10637+
if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) {
10638+
const propTypes: Type[] = [];
10639+
for (const t of (<UnionType>indexType).types) {
10640+
const propType = yield* getInstantiatedPropertyTypeForIndexType(apparentObjectType, t, accessFlags);
10641+
if (propType) {
10642+
propTypes.push(propType);
10643+
}
10644+
else {
10645+
// If there's no error node, we can immeditely stop, since error reporting is off
10646+
return undefined;
10647+
}
10648+
}
10649+
return accessFlags & AccessFlags.Writing ? getIntersectionType(propTypes) : getUnionType(propTypes);
10650+
}
10651+
return yield* getInstantiatedPropertyTypeForIndexType(apparentObjectType, indexType, accessFlags | AccessFlags.CacheSymbol);
10652+
}
10653+
10654+
function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, accessFlags = AccessFlags.None): Type | undefined {
10655+
const simple = getSimpleOrGenericIndexedAccess(objectType, indexType, accessNode);
10656+
if (simple) {
10657+
return simple;
10658+
}
1056110659
// In the following we resolve T[K] to the type of the property in T selected by K.
1056210660
// We treat boolean as different from other unions to improve errors;
1056310661
// skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'.
@@ -11640,7 +11738,7 @@ namespace ts {
1164011738
return getIndexType(yield [(<IndexType>type).type, mapper]);
1164111739
}
1164211740
if (flags & TypeFlags.IndexedAccess) {
11643-
return getIndexedAccessType(yield [(<IndexedAccessType>type).objectType, mapper], yield [(<IndexedAccessType>type).indexType, mapper]);
11741+
return (yield* getInstantiatedIndexedAccessType(yield [(<IndexedAccessType>type).objectType, mapper], yield [(<IndexedAccessType>type).indexType, mapper])) || unknownType;
1164411742
}
1164511743
if (flags & TypeFlags.Conditional) {
1164611744
return yield* getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers((<ConditionalType>type).mapper, mapper));

0 commit comments

Comments
 (0)