mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 01:49:57 -05:00
Add getIndexedAccessOrUndefined function
This commit is contained in:
@@ -7195,8 +7195,7 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
if (type.flags & TypeFlags.Index) {
|
||||
const keys = getIndexType(getApparentType((<IndexType>type).type));
|
||||
return isIndexType ? filterType(keys, t => !!(t.flags & TypeFlags.Literal)) : keys;
|
||||
return getIndexType(getApparentType((<IndexType>type).type));
|
||||
}
|
||||
if (type.flags & TypeFlags.Conditional) {
|
||||
if ((<ConditionalType>type).root.isDistributive) {
|
||||
@@ -7491,8 +7490,8 @@ namespace ts {
|
||||
function getConstraintFromIndexedAccess(type: IndexedAccessType) {
|
||||
const objectType = getConstraintOfType(type.objectType) || type.objectType;
|
||||
if (objectType !== type.objectType) {
|
||||
const constraint = getIndexedAccessType(objectType, type.indexType, /*accessNode*/ undefined, errorType);
|
||||
if (constraint && constraint !== errorType) {
|
||||
const constraint = getIndexedAccessTypeOrUndefined(objectType, type.indexType);
|
||||
if (constraint) {
|
||||
return constraint;
|
||||
}
|
||||
}
|
||||
@@ -7686,8 +7685,8 @@ namespace ts {
|
||||
if (t.flags & TypeFlags.IndexedAccess) {
|
||||
const baseObjectType = getBaseConstraint((<IndexedAccessType>t).objectType);
|
||||
const baseIndexType = getBaseConstraint((<IndexedAccessType>t).indexType);
|
||||
const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType, /*accessNode*/ undefined, errorType) : undefined;
|
||||
return baseIndexedAccess && baseIndexedAccess !== errorType ? getBaseConstraint(baseIndexedAccess) : undefined;
|
||||
const baseIndexedAccess = baseObjectType && baseIndexType && getIndexedAccessTypeOrUndefined(baseObjectType, baseIndexType);
|
||||
return baseIndexedAccess && getBaseConstraint(baseIndexedAccess);
|
||||
}
|
||||
if (t.flags & TypeFlags.Conditional) {
|
||||
const constraint = getConstraintFromConditionalType(<ConditionalType>t);
|
||||
@@ -9875,7 +9874,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean, missingType: Type) {
|
||||
function getPropertyTypeForIndexType(originalObjectType: Type, objectType: Type, indexType: Type, accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression | undefined, cacheSymbol: boolean) {
|
||||
const accessExpression = accessNode && accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode : undefined;
|
||||
const propName = isTypeUsableAsPropertyName(indexType) ?
|
||||
getPropertyNameFromType(indexType) :
|
||||
@@ -9892,7 +9891,7 @@ namespace ts {
|
||||
markPropertyAsReferenced(prop, accessExpression, /*isThisAccess*/ accessExpression.expression.kind === SyntaxKind.ThisKeyword);
|
||||
if (isAssignmentTarget(accessExpression) && (isReferenceToReadonlyEntity(accessExpression, prop) || isReferenceThroughNamespaceImport(accessExpression))) {
|
||||
error(accessExpression.argumentExpression, Diagnostics.Cannot_assign_to_0_because_it_is_a_read_only_property, symbolToString(prop));
|
||||
return missingType;
|
||||
return undefined;
|
||||
}
|
||||
if (cacheSymbol) {
|
||||
getNodeLinks(accessNode!).resolvedSymbol = prop;
|
||||
@@ -9921,16 +9920,19 @@ namespace ts {
|
||||
if (objectType.flags & (TypeFlags.Any | TypeFlags.Never)) {
|
||||
return objectType;
|
||||
}
|
||||
const indexInfo = accessExpression && isAssignmentTarget(accessExpression) && isGenericObjectType(originalObjectType) ? undefined :
|
||||
isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||
|
||||
getIndexInfoOfType(objectType, IndexKind.String) ||
|
||||
undefined;
|
||||
const isAssignment = accessExpression && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression));
|
||||
if (isAssignment && maybeTypeOfKind(originalObjectType, TypeFlags.Instantiable)) {
|
||||
error(accessExpression, Diagnostics.Type_0_cannot_be_indexed_by_type_1, typeToString(originalObjectType), typeToString(indexType));
|
||||
return undefined;
|
||||
}
|
||||
const indexInfo = isTypeAssignableToKind(indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||
|
||||
getIndexInfoOfType(objectType, IndexKind.String);
|
||||
if (indexInfo) {
|
||||
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));
|
||||
}
|
||||
else if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
|
||||
else if (isAssignment && indexInfo.isReadonly) {
|
||||
error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
|
||||
}
|
||||
return indexInfo.type;
|
||||
@@ -9964,7 +9966,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
return missingType;
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
if (isJSLiteralType(objectType)) {
|
||||
@@ -9985,7 +9987,7 @@ namespace ts {
|
||||
if (isTypeAny(indexType)) {
|
||||
return indexType;
|
||||
}
|
||||
return missingType;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getIndexNodeForAccessExpression(accessNode: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression) {
|
||||
@@ -10076,7 +10078,11 @@ namespace ts {
|
||||
return instantiateType(getTemplateTypeFromMappedType(objectType), templateMapper);
|
||||
}
|
||||
|
||||
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, missingType = accessNode ? errorType : unknownType): Type {
|
||||
function getIndexedAccessType(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, writing?: boolean): Type {
|
||||
return getIndexedAccessTypeOrUndefined(objectType, indexType, accessNode, writing) || (accessNode ? errorType : unknownType);
|
||||
}
|
||||
|
||||
function getIndexedAccessTypeOrUndefined(objectType: Type, indexType: Type, accessNode?: ElementAccessExpression | IndexedAccessTypeNode | PropertyName | BindingName | SyntheticExpression, writing?: boolean): Type | undefined {
|
||||
if (objectType === wildcardType || indexType === wildcardType) {
|
||||
return wildcardType;
|
||||
}
|
||||
@@ -10105,25 +10111,25 @@ namespace ts {
|
||||
const propTypes: Type[] = [];
|
||||
let wasMissingProp = false;
|
||||
for (const t of (<UnionType>indexType).types) {
|
||||
const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, accessNode, /*cacheSymbol*/ false, missingType);
|
||||
if (propType === missingType) {
|
||||
if (!accessNode) {
|
||||
// If there's no error node, we can immeditely stop, since error reporting is off
|
||||
return missingType;
|
||||
}
|
||||
else {
|
||||
// Otherwise we set a flag and return at the end of the loop so we still mark all errors
|
||||
wasMissingProp = true;
|
||||
}
|
||||
const propType = getPropertyTypeForIndexType(objectType, apparentObjectType, t, accessNode, /*cacheSymbol*/ false);
|
||||
if (propType) {
|
||||
propTypes.push(propType);
|
||||
}
|
||||
else if (!accessNode) {
|
||||
// If there's no error node, we can immeditely stop, since error reporting is off
|
||||
return undefined;
|
||||
}
|
||||
else {
|
||||
// Otherwise we set a flag and return at the end of the loop so we still mark all errors
|
||||
wasMissingProp = true;
|
||||
}
|
||||
propTypes.push(propType);
|
||||
}
|
||||
if (wasMissingProp) {
|
||||
return missingType;
|
||||
return undefined;
|
||||
}
|
||||
return !accessNode || getAssignmentTargetKind(accessNode) === AssignmentKind.None ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
return writing ? getIntersectionType(propTypes) : getUnionType(propTypes);
|
||||
}
|
||||
return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true, missingType);
|
||||
return getPropertyTypeForIndexType(objectType, apparentObjectType, indexType, accessNode, /*cacheSymbol*/ true);
|
||||
}
|
||||
|
||||
function getTypeFromIndexedAccessTypeNode(node: IndexedAccessTypeNode) {
|
||||
@@ -11512,10 +11518,10 @@ namespace ts {
|
||||
let reportedError = false;
|
||||
for (let status = iterator.next(); !status.done; status = iterator.next()) {
|
||||
const { errorNode: prop, innerExpression: next, nameType, errorMessage } = status.value;
|
||||
const targetPropType = getIndexedAccessType(target, nameType, /*accessNode*/ undefined, errorType);
|
||||
if (targetPropType === errorType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables
|
||||
const sourcePropType = getIndexedAccessType(source, nameType, /*accessNode*/ undefined, errorType);
|
||||
if (sourcePropType !== errorType && targetPropType !== errorType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
|
||||
const targetPropType = getIndexedAccessTypeOrUndefined(target, nameType);
|
||||
if (!targetPropType || targetPropType.flags & TypeFlags.IndexedAccess) continue; // Don't elaborate on indexes on generic variables
|
||||
const sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType);
|
||||
if (sourcePropType && !checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
|
||||
const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined);
|
||||
if (elaborated) {
|
||||
reportedError = true;
|
||||
@@ -12819,9 +12825,7 @@ namespace ts {
|
||||
if (indexType.flags & TypeFlags.StructuredOrInstantiable) {
|
||||
const keyType = getLowerBoundOfKeyType(indexType, /*isIndexType*/ true);
|
||||
if (keyType !== indexType && !(keyType.flags & TypeFlags.Never)) {
|
||||
const targetType = keyType.flags & TypeFlags.Union ?
|
||||
getIntersectionType(map((<UnionType>keyType).types, t => getIndexedAccessType(objectType, t))) :
|
||||
getIndexedAccessType(objectType, keyType);
|
||||
const targetType = getIndexedAccessType(objectType, keyType, /*accessNode*/ undefined, /*writing*/ true);
|
||||
if (result = isRelatedTo(source, targetType, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
@@ -12830,7 +12834,8 @@ namespace ts {
|
||||
else {
|
||||
const constraint = getConstraintOfType(objectType);
|
||||
if (constraint) {
|
||||
if (result = isRelatedTo(source, getIndexedAccessType(constraint, indexType), reportErrors)) {
|
||||
const targetType = getIndexedAccessType(constraint, indexType, /*accessNode*/ undefined, /*writing*/ true);
|
||||
if (result = isRelatedTo(source, targetType, reportErrors)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -19975,7 +19980,9 @@ namespace ts {
|
||||
return errorType;
|
||||
}
|
||||
|
||||
return checkIndexedAccessIndexType(getIndexedAccessType(objectType, isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType, node), node);
|
||||
const effectiveIndexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : indexType;
|
||||
const indexedAccessType = getIndexedAccessType(objectType, effectiveIndexType, node, isAssignmentTarget(node));
|
||||
return checkIndexedAccessIndexType(indexedAccessType, node);
|
||||
}
|
||||
|
||||
function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean {
|
||||
@@ -24570,7 +24577,7 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
error(accessNode, Diagnostics.Type_0_cannot_be_used_to_index_type_1, typeToString(indexType), typeToString(objectType));
|
||||
return type;
|
||||
return errorType;
|
||||
}
|
||||
|
||||
function checkIndexedAccessType(node: IndexedAccessTypeNode) {
|
||||
|
||||
@@ -2152,6 +2152,10 @@
|
||||
"category": "Error",
|
||||
"code": 2593
|
||||
},
|
||||
"Type '{0}' cannot be indexed by type '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2594
|
||||
},
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
|
||||
Reference in New Issue
Block a user