diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 3fbc4cd158b90..9cc867e78534d 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -343,6 +343,7 @@ namespace ts {
const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes");
const strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply");
const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization");
+ const strictOptionalProperties = getStrictOptionValue(compilerOptions, "strictOptionalProperties");
const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny");
const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis");
const keyofStringsOnly = !!compilerOptions.keyofStringsOnly;
@@ -736,6 +737,7 @@ namespace ts {
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType);
const optionalType = createIntrinsicType(TypeFlags.Undefined, "undefined");
+ const missingType = strictOptionalProperties ? createIntrinsicType(TypeFlags.Undefined, "undefined") : undefinedType;
const nullType = createIntrinsicType(TypeFlags.Null, "null");
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType);
const stringType = createIntrinsicType(TypeFlags.String, "string");
@@ -4806,7 +4808,7 @@ namespace ts {
}
const typeParameterNode = typeParameterToDeclarationWithConstraint(getTypeParameterFromMappedType(type), context, appropriateConstraintTypeNode);
const nameTypeNode = type.declaration.nameType ? typeToTypeNodeHelper(getNameTypeFromMappedType(type)!, context) : undefined;
- const templateTypeNode = typeToTypeNodeHelper(getTemplateTypeFromMappedType(type), context);
+ const templateTypeNode = typeToTypeNodeHelper(removeMissingType(getTemplateTypeFromMappedType(type), !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), context);
const mappedTypeNode = factory.createMappedTypeNode(readonlyToken, typeParameterNode, nameTypeNode, questionToken, templateTypeNode);
context.approximateLength += 10;
return setEmitFlags(mappedTypeNode, EmitFlags.SingleLine);
@@ -4986,7 +4988,7 @@ namespace ts {
}
function typeReferenceToTypeNode(type: TypeReference) {
- const typeArguments: readonly Type[] = getTypeArguments(type);
+ let typeArguments: readonly Type[] = getTypeArguments(type);
if (type.target === globalArrayType || type.target === globalReadonlyArrayType) {
if (context.flags & NodeBuilderFlags.WriteArrayAsGenericType) {
const typeArgumentNode = typeToTypeNodeHelper(typeArguments[0], context);
@@ -4997,6 +4999,7 @@ namespace ts {
return type.target === globalArrayType ? arrayType : factory.createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, arrayType);
}
else if (type.target.objectFlags & ObjectFlags.Tuple) {
+ typeArguments = sameMap(typeArguments, (t, i) => removeMissingType(t, !!((type.target as TupleType).elementFlags[i] & ElementFlags.Optional)));
if (typeArguments.length > 0) {
const arity = getTypeReferenceArity(type);
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
@@ -5229,7 +5232,7 @@ namespace ts {
function addPropertyToElementList(propertySymbol: Symbol, context: NodeBuilderContext, typeElements: TypeElement[]) {
const propertyIsReverseMapped = !!(getCheckFlags(propertySymbol) & CheckFlags.ReverseMapped);
const propertyType = shouldUsePlaceholderForProperty(propertySymbol, context) ?
- anyType : getTypeOfSymbol(propertySymbol);
+ anyType : getNonMissingTypeOfSymbol(propertySymbol);
const saveEnclosingDeclaration = context.enclosingDeclaration;
context.enclosingDeclaration = undefined;
if (context.tracker.trackSymbol && getCheckFlags(propertySymbol) & CheckFlags.Late && isLateBoundName(propertySymbol.escapedName)) {
@@ -8365,8 +8368,8 @@ namespace ts {
return expr.kind === SyntaxKind.ArrayLiteralExpression && (expr as ArrayLiteralExpression).elements.length === 0;
}
- function addOptionality(type: Type, optional = true): Type {
- return strictNullChecks && optional ? getOptionalType(type) : type;
+ function addOptionality(type: Type, isProperty = false, isOptional = true): Type {
+ return strictNullChecks && isOptional ? getOptionalType(type, isProperty) : type;
}
// Return the inferred type for a variable, parameter, or property declaration
@@ -8391,15 +8394,16 @@ namespace ts {
return getTypeForBindingElement(declaration as BindingElement);
}
+ const isProperty = isPropertyDeclaration(declaration) || isPropertySignature(declaration);
const isOptional = includeOptionality && (
- isParameter(declaration) && isJSDocOptionalParameter(declaration)
- || isOptionalJSDocPropertyLikeTag(declaration)
- || !isBindingElement(declaration) && !isVariableDeclaration(declaration) && !!declaration.questionToken);
+ isProperty && !!(declaration as PropertyDeclaration | PropertySignature).questionToken ||
+ isParameter(declaration) && (!!declaration.questionToken || isJSDocOptionalParameter(declaration)) ||
+ isOptionalJSDocPropertyLikeTag(declaration));
// Use type from type annotation if one is present
const declaredType = tryGetTypeFromEffectiveTypeNode(declaration);
if (declaredType) {
- return addOptionality(declaredType, isOptional);
+ return addOptionality(declaredType, isProperty, isOptional);
}
if ((noImplicitAny || isInJSFile(declaration)) &&
@@ -8445,7 +8449,7 @@ namespace ts {
// Use contextual parameter type if one is available
const type = declaration.symbol.escapedName === InternalSymbolName.This ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration);
if (type) {
- return addOptionality(type, isOptional);
+ return addOptionality(type, /*isProperty*/ false, isOptional);
}
}
@@ -8459,7 +8463,7 @@ namespace ts {
}
}
const type = widenTypeInferredFromInitializer(declaration, checkDeclarationInitializer(declaration));
- return addOptionality(type, isOptional);
+ return addOptionality(type, isProperty, isOptional);
}
if (isPropertyDeclaration(declaration) && !hasStaticModifier(declaration) && (noImplicitAny || isInJSFile(declaration))) {
@@ -8469,7 +8473,7 @@ namespace ts {
const type = constructor ? getFlowTypeInConstructor(declaration.symbol, constructor) :
getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) :
undefined;
- return type && addOptionality(type, isOptional);
+ return type && addOptionality(type, /*isProperty*/ true, isOptional);
}
if (isJsxAttribute(declaration)) {
@@ -8636,7 +8640,7 @@ namespace ts {
type = getUnionType(sourceTypes!, UnionReduction.Subtype);
}
}
- const widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor));
+ const widened = getWidenedType(addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor));
if (symbol.valueDeclaration && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) {
reportImplicitAny(symbol.valueDeclaration, anyType);
return anyType;
@@ -8679,7 +8683,10 @@ namespace ts {
if (symbol.parent?.valueDeclaration) {
const typeNode = getEffectiveTypeAnnotationNode(symbol.parent.valueDeclaration);
if (typeNode) {
- return getTypeOfPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName);
+ const annotationSymbol = getPropertyOfType(getTypeFromTypeNode(typeNode), symbol.escapedName);
+ if (annotationSymbol) {
+ return getNonMissingTypeOfSymbol(annotationSymbol);
+ }
}
}
@@ -9384,6 +9391,10 @@ namespace ts {
return errorType;
}
+ function getNonMissingTypeOfSymbol(symbol: Symbol) {
+ return removeMissingType(getTypeOfSymbol(symbol), !!(symbol.flags & SymbolFlags.Optional));
+ }
+
function isReferenceToType(type: Type, target: Type) {
return type !== undefined
&& target !== undefined
@@ -11168,7 +11179,7 @@ namespace ts {
// When creating an optional property in strictNullChecks mode, if 'undefined' isn't assignable to the
// type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks
// mode, if the underlying property is optional we remove 'undefined' from the type.
- let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
+ let type = strictNullChecks && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) :
symbol.checkFlags & CheckFlags.StripOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
propType;
if (!popTypeResolution()) {
@@ -11199,7 +11210,7 @@ namespace ts {
function getTemplateTypeFromMappedType(type: MappedType) {
return type.templateType ||
(type.templateType = type.declaration.type ?
- instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) :
+ instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), /*isProperty*/ true, !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) :
errorType);
}
@@ -13680,8 +13691,7 @@ namespace ts {
}
function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type {
- const type = getTypeFromTypeNode(node.type);
- return strictNullChecks ? getOptionalType(type) : type;
+ return addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true);
}
function getTypeId(type: Type): TypeId {
@@ -13871,6 +13881,12 @@ namespace ts {
if (includes & TypeFlags.AnyOrUnknown) {
return includes & TypeFlags.Any ? includes & TypeFlags.IncludesWildcard ? wildcardType : anyType : unknownType;
}
+ if (strictOptionalProperties && includes & TypeFlags.Undefined) {
+ const missingIndex = binarySearch(typeSet, missingType, getTypeId, compareValues);
+ if (missingIndex >= 0 && containsType(typeSet, undefinedType)) {
+ orderedRemoveItemAt(typeSet, missingIndex);
+ }
+ }
if (includes & (TypeFlags.Literal | TypeFlags.UniqueESSymbol) || includes & TypeFlags.Void && includes & TypeFlags.Undefined) {
removeRedundantLiteralTypes(typeSet, includes, !!(unionReduction & UnionReduction.Subtype));
}
@@ -15390,7 +15406,7 @@ namespace ts {
const isSetonlyAccessor = prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor);
const flags = SymbolFlags.Property | SymbolFlags.Optional;
const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0));
- result.type = isSetonlyAccessor ? undefinedType : getUnionType([getTypeOfSymbol(prop), undefinedType]);
+ result.type = isSetonlyAccessor ? undefinedType : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true);
result.declarations = prop.declarations;
result.nameType = getSymbolLinks(prop).nameType;
result.syntheticOrigin = prop;
@@ -15688,8 +15704,7 @@ namespace ts {
const links = getNodeLinks(node);
return links.resolvedType || (links.resolvedType =
node.dotDotDotToken ? getTypeFromRestTypeNode(node) :
- node.questionToken && strictNullChecks ? getOptionalType(getTypeFromTypeNode(node.type)) :
- getTypeFromTypeNode(node.type));
+ addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken));
}
function getTypeFromTypeNode(node: TypeNode): Type {
@@ -16152,7 +16167,7 @@ namespace ts {
const templateMapper = appendTypeMapping(mapper, getTypeParameterFromMappedType(type), key);
const propType = instantiateType(getTemplateTypeFromMappedType(type.target as MappedType || type), templateMapper);
const modifiers = getMappedTypeModifiers(type);
- return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType) :
+ return strictNullChecks && modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, /*isProperty*/ true) :
strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) :
propType;
}
@@ -16698,10 +16713,16 @@ 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 = getBestMatchIndexedAccessTypeOrUndefined(source, target, nameType);
+ let targetPropType = getBestMatchIndexedAccessTypeOrUndefined(source, 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)) {
+ let sourcePropType = getIndexedAccessTypeOrUndefined(source, nameType);
+ if (!sourcePropType) continue;
+ const propName = getPropertyNameFromIndex(nameType, /*accessNode*/ undefined);
+ const targetIsOptional = !!(propName && (getPropertyOfType(target, propName) || unknownSymbol).flags & SymbolFlags.Optional);
+ const sourceIsOptional = !!(propName && (getPropertyOfType(source, propName) || unknownSymbol).flags & SymbolFlags.Optional);
+ targetPropType = removeMissingType(targetPropType, targetIsOptional);
+ sourcePropType = removeMissingType(sourcePropType, targetIsOptional && sourceIsOptional);
+ if (!checkTypeRelatedTo(sourcePropType, targetPropType, relation, /*errorNode*/ undefined)) {
const elaborated = next && elaborateError(next, sourcePropType, targetPropType, relation, /*headMessage*/ undefined, containingMessageChain, errorOutputContainer);
if (elaborated) {
reportedError = true;
@@ -18877,7 +18898,7 @@ namespace ts {
// fixed limit before incurring the cost of any allocations:
let numCombinations = 1;
for (const sourceProperty of sourcePropertiesFiltered) {
- numCombinations *= countTypes(getTypeOfSymbol(sourceProperty));
+ numCombinations *= countTypes(getNonMissingTypeOfSymbol(sourceProperty));
if (numCombinations > 25) {
// We've reached the complexity limit.
tracing?.instant(tracing.Phase.CheckTypes, "typeRelatedToDiscriminatedType_DepthLimit", { sourceId: source.id, targetId: target.id, numCombinations });
@@ -18890,7 +18911,7 @@ namespace ts {
const excludedProperties = new Set<__String>();
for (let i = 0; i < sourcePropertiesFiltered.length; i++) {
const sourceProperty = sourcePropertiesFiltered[i];
- const sourcePropertyType = getTypeOfSymbol(sourceProperty);
+ const sourcePropertyType = getNonMissingTypeOfSymbol(sourceProperty);
sourceDiscriminantTypes[i] = sourcePropertyType.flags & TypeFlags.Union
? (sourcePropertyType as UnionType).types
: [sourcePropertyType];
@@ -18971,45 +18992,9 @@ namespace ts {
function isPropertySymbolTypeRelated(sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
const targetIsOptional = strictNullChecks && !!(getCheckFlags(targetProp) & CheckFlags.Partial);
- const source = getTypeOfSourceProperty(sourceProp);
- if (getCheckFlags(targetProp) & CheckFlags.DeferredType && !getSymbolLinks(targetProp).type) {
- // Rather than resolving (and normalizing) the type, relate constituent-by-constituent without performing normalization or seconadary passes
- const links = getSymbolLinks(targetProp);
- Debug.assertIsDefined(links.deferralParent);
- Debug.assertIsDefined(links.deferralConstituents);
- const unionParent = !!(links.deferralParent.flags & TypeFlags.Union);
- let result = unionParent ? Ternary.False : Ternary.True;
- const targetTypes = links.deferralConstituents;
- for (const targetType of targetTypes) {
- const related = isRelatedTo(source, targetType, /*reportErrors*/ false, /*headMessage*/ undefined, unionParent ? 0 : IntersectionState.Target);
- if (!unionParent) {
- if (!related) {
- // Can't assign to a target individually - have to fallback to assigning to the _whole_ intersection (which forces normalization)
- return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors);
- }
- result &= related;
- }
- else {
- if (related) {
- return related;
- }
- }
- }
- if (unionParent && !result && targetIsOptional) {
- result = isRelatedTo(source, undefinedType);
- }
- if (unionParent && !result && reportErrors) {
- // The easiest way to get the right errors here is to un-defer (which may be costly)
- // If it turns out this is too costly too often, we can replicate the error handling logic within
- // typeRelatedToSomeType without the discriminatable type branch (as that requires a manifest union
- // type on which to hand discriminable properties, which we are expressly trying to avoid here)
- return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors);
- }
- return result;
- }
- else {
- return isRelatedTo(source, addOptionality(getTypeOfSymbol(targetProp), targetIsOptional), reportErrors, /*headMessage*/ undefined, intersectionState);
- }
+ const effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), /*isProperty*/ false, targetIsOptional);
+ const effectiveSource = getTypeOfSourceProperty(sourceProp);
+ return isRelatedTo(effectiveSource, effectiveTarget, reportErrors, /*headMessage*/ undefined, intersectionState);
}
function propertyRelatedTo(source: Type, target: Type, sourceProp: Symbol, targetProp: Symbol, getTypeOfSourceProperty: (sym: Symbol) => Type, reportErrors: boolean, intersectionState: IntersectionState, skipOptional: boolean): Ternary {
@@ -19150,7 +19135,7 @@ namespace ts {
}
return Ternary.False;
}
- if (!targetRestFlag && sourceRestFlag) {
+ if (!targetRestFlag && (sourceRestFlag || targetArity < sourceArity)) {
if (reportErrors) {
if (sourceMinLength < targetMinLength) {
reportError(Diagnostics.Target_requires_0_element_s_but_source_may_have_fewer, targetMinLength);
@@ -19198,10 +19183,11 @@ namespace ts {
}
}
const sourceType = !isTupleType(source) ? sourceTypeArguments[0] :
- i < startCount || i >= targetArity - endCount ? sourceTypeArguments[sourceIndex] :
+ i < startCount || i >= targetArity - endCount ? removeMissingType(sourceTypeArguments[sourceIndex], !!(sourceFlags & targetFlags & ElementFlags.Optional)) :
getElementTypeOfSliceOfTupleType(source, startCount, endCount) || neverType;
const targetType = targetTypeArguments[i];
- const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) : targetType;
+ const targetCheckType = sourceFlags & ElementFlags.Variadic && targetFlags & ElementFlags.Rest ? createArrayType(targetType) :
+ removeMissingType(targetType, !!(targetFlags & ElementFlags.Optional));
const related = isRelatedTo(sourceType, targetCheckType, reportErrors, /*headMessage*/ undefined, intersectionState);
if (!related) {
if (reportErrors) {
@@ -19234,7 +19220,7 @@ namespace ts {
for (const sourceProp of excludeProperties(getPropertiesOfType(source), excludedProperties)) {
if (!getPropertyOfObjectType(target, sourceProp.escapedName)) {
const sourceType = getTypeOfSymbol(sourceProp);
- if (!(sourceType === undefinedType || sourceType === undefinedWideningType || sourceType === optionalType)) {
+ if (!(sourceType.flags & TypeFlags.Undefined)) {
if (reportErrors) {
reportError(Diagnostics.Property_0_does_not_exist_on_type_1, symbolToString(sourceProp), typeToString(target));
}
@@ -19252,7 +19238,7 @@ namespace ts {
if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length")) {
const sourceProp = getPropertyOfType(source, name);
if (sourceProp && sourceProp !== targetProp) {
- const related = propertyRelatedTo(source, target, sourceProp, targetProp, getTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
+ const related = propertyRelatedTo(source, target, sourceProp, targetProp, getNonMissingTypeOfSymbol, reportErrors, intersectionState, relation === comparableRelation);
if (!related) {
return Ternary.False;
}
@@ -20319,9 +20305,9 @@ namespace ts {
getUnionType([type, undefinedType, nullType]);
}
- function getOptionalType(type: Type): Type {
+ function getOptionalType(type: Type, isProperty = false): Type {
Debug.assert(strictNullChecks);
- return type.flags & TypeFlags.Undefined ? type : getUnionType([type, undefinedType]);
+ return type.flags & TypeFlags.Undefined ? type : getUnionType([type, isProperty ? missingType : undefinedType]);
}
function getGlobalNonNullableTypeInstantiation(type: Type) {
@@ -20364,6 +20350,14 @@ namespace ts {
exprType;
}
+ function removeMissingType(type: Type, isOptional: boolean) {
+ return strictOptionalProperties && isOptional ? filterType(type, t => t !== missingType) : type;
+ }
+
+ function containsMissingType(type: Type) {
+ return strictOptionalProperties && (type === missingType || type.flags & TypeFlags.Union && containsType((type as UnionType).types, missingType));
+ }
+
/**
* Is source potentially coercible to target type under `==`.
* Assumes that `source` is a constituent of a union, hence
@@ -20507,7 +20501,7 @@ namespace ts {
if (cached) {
return cached;
}
- const result = createSymbolWithType(prop, undefinedType);
+ const result = createSymbolWithType(prop, missingType);
result.flags |= SymbolFlags.Optional;
undefinedProperties.set(prop.escapedName, result);
return result;
@@ -23570,8 +23564,14 @@ namespace ts {
return narrowTypeByInstanceof(type, expr, assumeTrue);
case SyntaxKind.InKeyword:
const target = getReferenceCandidate(expr.right);
- if (isStringLiteralLike(expr.left) && isMatchingReference(reference, target)) {
- return narrowByInKeyword(type, expr.left, assumeTrue);
+ if (isStringLiteralLike(expr.left)) {
+ if (containsMissingType(type) && isAccessExpression(reference) && isMatchingReference(reference.expression, target) &&
+ getAccessedPropertyName(reference) === escapeLeadingUnderscores(expr.left.text)) {
+ return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined);
+ }
+ if (isMatchingReference(reference, target)) {
+ return narrowByInKeyword(type, expr.left, assumeTrue);
+ }
}
break;
case SyntaxKind.CommaToken:
@@ -23957,6 +23957,16 @@ namespace ts {
return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue);
}
}
+ if (containsMissingType(type) && isAccessExpression(reference) && isPropertyAccessExpression(callExpression.expression)) {
+ const callAccess = callExpression.expression;
+ if (isMatchingReference(reference.expression, getReferenceCandidate(callAccess.expression)) &&
+ isIdentifier(callAccess.name) && callAccess.name.escapedText === "hasOwnProperty" && callExpression.arguments.length === 1) {
+ const argument = callExpression.arguments[0];
+ if (isStringLiteralLike(argument) && getAccessedPropertyName(reference) === escapeLeadingUnderscores(argument.text)) {
+ return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined);
+ }
+ }
+ }
return type;
}
@@ -24048,7 +24058,7 @@ namespace ts {
// to it at the given location. Since we have no control flow information for the
// hypothetical reference (control flow information is created and attached by the
// binder), we simply return the declared type of the symbol.
- return getTypeOfSymbol(symbol);
+ return getNonMissingTypeOfSymbol(symbol);
}
function getControlFlowContainer(node: Node): Node {
@@ -26014,6 +26024,7 @@ namespace ts {
const contextualType = getApparentTypeOfContextualType(node);
const inDestructuringPattern = isAssignmentTarget(node);
const inConstContext = isConstContext(node);
+ let hasOmittedExpression = false;
for (let i = 0; i < elementCount; i++) {
const e = elements[i];
if (e.kind === SyntaxKind.SpreadElement) {
@@ -26049,11 +26060,16 @@ namespace ts {
elementFlags.push(ElementFlags.Rest);
}
}
+ else if (strictOptionalProperties && e.kind === SyntaxKind.OmittedExpression) {
+ hasOmittedExpression = true;
+ elementTypes.push(missingType);
+ elementFlags.push(ElementFlags.Optional);
+ }
else {
const elementContextualType = getContextualTypeForElementExpression(contextualType, elementTypes.length);
const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple);
- elementTypes.push(type);
- elementFlags.push(ElementFlags.Required);
+ elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression));
+ elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required);
}
}
if (inDestructuringPattern) {
@@ -27478,8 +27494,10 @@ namespace ts {
// assignment target, and the referenced property was declared as a variable, property,
// accessor, or optional method.
const assignmentKind = getAssignmentTargetKind(node);
- if (assignmentKind === AssignmentKind.Definite ||
- prop &&
+ if (assignmentKind === AssignmentKind.Definite) {
+ return removeMissingType(propType, !!(prop && prop.flags & SymbolFlags.Optional));
+ }
+ if (prop &&
!(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor))
&& !(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)
&& !isDuplicatedCommonJSExport(prop.declarations)) {
@@ -36886,7 +36904,7 @@ namespace ts {
if (stringIndexType || numberIndexType) {
forEach(getPropertiesOfObjectType(type), prop => {
if (isStatic && prop.flags & SymbolFlags.Prototype) return;
- const propType = getTypeOfSymbol(prop);
+ const propType = getNonMissingTypeOfSymbol(prop);
checkIndexConstraintForProperty(prop, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String);
checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number);
});
@@ -36899,7 +36917,7 @@ namespace ts {
// and properties with literal names were already checked.
if (!hasSyntacticModifier(member, ModifierFlags.Static) && !hasBindableName(member)) {
const symbol = getSymbolOfNode(member);
- const propType = getTypeOfSymbol(symbol);
+ const propType = getNonMissingTypeOfSymbol(symbol);
checkIndexConstraintForProperty(symbol, propType, type, declaredStringIndexer, stringIndexType, IndexKind.String);
checkIndexConstraintForProperty(symbol, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number);
}
diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts
index 4fec5cd18caf4..3cc666af682bd 100644
--- a/src/compiler/commandLineParser.ts
+++ b/src/compiler/commandLineParser.ts
@@ -612,6 +612,15 @@ namespace ts {
category: Diagnostics.Strict_Type_Checking_Options,
description: Diagnostics.Enable_strict_checking_of_property_initialization_in_classes
},
+ {
+ name: "strictOptionalProperties",
+ type: "boolean",
+ affectsSemanticDiagnostics: true,
+ strictFlag: true,
+ showInSimplifiedHelpView: true,
+ category: Diagnostics.Strict_Type_Checking_Options,
+ description: Diagnostics.Enable_strict_checking_of_optional_properties
+ },
{
name: "noImplicitThis",
type: "boolean",
diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index 0c766fbde12c9..0998b3a18314e 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -4873,6 +4873,10 @@
"category": "Message",
"code": 6242
},
+ "Enable strict checking of optional properties.": {
+ "category": "Message",
+ "code": 6243
+ },
"Projects to reference": {
"category": "Message",
diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 102517c4ce6fd..e3eb5538d4be6 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -3041,6 +3041,9 @@ namespace ts {
if (options.strictPropertyInitialization && !getStrictOptionValue(options, "strictNullChecks")) {
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks");
}
+ if (options.strictOptionalProperties && !getStrictOptionValue(options, "strictNullChecks")) {
+ createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictOptionalProperties", "strictNullChecks");
+ }
if (options.isolatedModules) {
if (options.out) {
diff --git a/src/compiler/types.ts b/src/compiler/types.ts
index f395014baad1d..5c8992a69a60d 100644
--- a/src/compiler/types.ts
+++ b/src/compiler/types.ts
@@ -6041,6 +6041,7 @@ namespace ts {
strictBindCallApply?: boolean; // Always combine with strict property
strictNullChecks?: boolean; // Always combine with strict property
strictPropertyInitialization?: boolean; // Always combine with strict property
+ strictOptionalProperties?: boolean; // Always combine with strict property
stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts
index 8271e6adfc22f..683d505a97f58 100644
--- a/src/compiler/utilities.ts
+++ b/src/compiler/utilities.ts
@@ -6109,6 +6109,7 @@ namespace ts {
| "strictFunctionTypes"
| "strictBindCallApply"
| "strictPropertyInitialization"
+ | "strictOptionalProperties"
| "alwaysStrict"
;
diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts
index dcbd016c31e3b..6f94fa1b356ed 100644
--- a/tests/baselines/reference/api/tsserverlibrary.d.ts
+++ b/tests/baselines/reference/api/tsserverlibrary.d.ts
@@ -2913,6 +2913,7 @@ declare namespace ts {
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
+ strictOptionalProperties?: boolean;
stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts
index a3d17250a215c..9f58cc3bbab09 100644
--- a/tests/baselines/reference/api/typescript.d.ts
+++ b/tests/baselines/reference/api/typescript.d.ts
@@ -2913,6 +2913,7 @@ declare namespace ts {
strictBindCallApply?: boolean;
strictNullChecks?: boolean;
strictPropertyInitialization?: boolean;
+ strictOptionalProperties?: boolean;
stripInternal?: boolean;
suppressExcessPropertyErrors?: boolean;
suppressImplicitAnyIndexErrors?: boolean;
diff --git a/tests/baselines/reference/checkJsxIntersectionElementPropsType.types b/tests/baselines/reference/checkJsxIntersectionElementPropsType.types
index 187d0f274a409..efaa22d38c6e4 100644
--- a/tests/baselines/reference/checkJsxIntersectionElementPropsType.types
+++ b/tests/baselines/reference/checkJsxIntersectionElementPropsType.types
@@ -16,7 +16,7 @@ declare class Component
{
class C extends Component<{ x?: boolean; } & T> {}
>C : C
->Component : Component<{ x?: boolean | undefined; } & T>
+>Component : Component<{ x?: boolean; } & T>
>x : boolean | undefined
const y = new C({foobar: "example"});
diff --git a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types
index babef6106a169..8f5250d3e4789 100644
--- a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types
+++ b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.types
@@ -10,7 +10,7 @@ declare class Component {
>context : any
readonly props: Readonly
& Readonly<{ children?: {} }>;
->props : Readonly
& Readonly<{ children?: {} | undefined; }>
+>props : Readonly
& Readonly<{ children?: {}; }>
>children : {} | undefined
}
interface ComponentClass
{
@@ -29,7 +29,7 @@ interface ComponentClass
{
}
interface FunctionComponent
{
(props: P & { children?: {} }, context?: any): {} | null;
->props : P & { children?: {} | undefined; }
+>props : P & { children?: {}; }
>children : {} | undefined
>context : any
>null : null
diff --git a/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types
index db65878b320d3..b49c5d763304c 100644
--- a/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types
+++ b/tests/baselines/reference/contextuallyTypedParametersWithInitializers.types
@@ -16,7 +16,7 @@ declare function id3 any>(input: T): T;
declare function id4 any>(input: T): T;
>id4 : any>(input: T) => T
->x : { foo?: number | undefined; }
+>x : { foo?: number; }
>foo : number | undefined
>input : T
@@ -60,10 +60,10 @@ const f13 = id3(function ({ foo = 42 }) { return foo });
>foo : any
const f14 = id4(function ({ foo = 42 }) { return foo });
->f14 : ({ foo }: { foo?: number | undefined; }) => number
->id4(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo?: number | undefined; }) => number
->id4 : any>(input: T) => T
->function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number | undefined; }) => number
+>f14 : ({ foo }: { foo?: number; }) => number
+>id4(function ({ foo = 42 }) { return foo }) : ({ foo }: { foo?: number; }) => number
+>id4 : any>(input: T) => T
+>function ({ foo = 42 }) { return foo } : ({ foo }: { foo?: number; }) => number
>foo : number
>42 : 42
>foo : number
diff --git a/tests/baselines/reference/controlFlowOptionalChain.types b/tests/baselines/reference/controlFlowOptionalChain.types
index 4e335fca6d287..4fc4faf8fce59 100644
--- a/tests/baselines/reference/controlFlowOptionalChain.types
+++ b/tests/baselines/reference/controlFlowOptionalChain.types
@@ -249,256 +249,256 @@ o3.x;
>x : 1 | 2
declare const o4: { x?: { y: boolean } };
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean;}; }
>x : { y: boolean; } | undefined
>y : boolean
if (o4.x?.y) {
>o4.x?.y : boolean | undefined
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
>y : boolean | undefined
o4.x; // { y: boolean }
>o4.x : { y: boolean; }
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; }
o4.x.y; // true
>o4.x.y : true
>o4.x : { y: boolean; }
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; }
>y : true
o4.x?.y; // true
>o4.x?.y : true
>o4.x : { y: boolean; }
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; }
>y : true
}
else {
o4.x;
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
o4.x?.y;
>o4.x?.y : boolean | undefined
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
>y : boolean | undefined
o4.x.y;
>o4.x.y : boolean
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
>y : boolean
}
o4.x;
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
o4.x?.y;
>o4.x?.y : boolean | undefined
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
>y : boolean | undefined
o4.x.y;
>o4.x.y : boolean
>o4.x : { y: boolean; } | undefined
->o4 : { x?: { y: boolean; } | undefined; }
+>o4 : { x?: { y: boolean; }; }
>x : { y: boolean; } | undefined
>y : boolean
declare const o5: { x?: { y: { z?: { w: boolean } } } };
->o5 : { x?: { y: { z?: { w: boolean; };}; } | undefined; }
+>o5 : { x?: { y: { z?: { w: boolean; }; };}; }
>x : { y: { z?: { w: boolean; };}; } | undefined
->y : { z?: { w: boolean; } | undefined; }
+>y : { z?: { w: boolean;}; }
>z : { w: boolean; } | undefined
>w : boolean
if (o5.x?.y.z?.w) {
>o5.x?.y.z?.w : boolean | undefined
>o5.x?.y.z : { w: boolean; } | undefined
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
>z : { w: boolean; } | undefined
>w : boolean | undefined
o5.x;
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
o5.x.y;
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
+>y : { z?: { w: boolean; }; }
o5.x.y.z;
>o5.x.y.z : { w: boolean; }
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; }
o5.x.y.z.w; // true
>o5.x.y.z.w : true
>o5.x.y.z : { w: boolean; }
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; }
>w : true
o5.x.y.z?.w; // true
>o5.x.y.z?.w : true
>o5.x.y.z : { w: boolean; }
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; }
>w : true
o5.x?.y.z.w; // true
>o5.x?.y.z.w : true
>o5.x?.y.z : { w: boolean; }
->o5.x?.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
->y : { z?: { w: boolean; } | undefined; }
+>o5.x?.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; }
>w : true
o5.x?.y.z?.w; // true
>o5.x?.y.z?.w : true
>o5.x?.y.z : { w: boolean; }
->o5.x?.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; }
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; }
->y : { z?: { w: boolean; } | undefined; }
+>o5.x?.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; }
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; }
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; }
>w : true
}
else {
o5.x;
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
o5.x?.y;
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
o5.x?.y.z;
>o5.x?.y.z : { w: boolean; } | undefined
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
>z : { w: boolean; } | undefined
o5.x?.y.z?.w;
>o5.x?.y.z?.w : boolean | undefined
>o5.x?.y.z : { w: boolean; } | undefined
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
>z : { w: boolean; } | undefined
>w : boolean | undefined
o5.x.y;
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; }
o5.x.y.z.w;
>o5.x.y.z.w : boolean
>o5.x.y.z : { w: boolean; } | undefined
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; } | undefined
>w : boolean
}
o5.x;
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
o5.x?.y;
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
o5.x?.y.z;
>o5.x?.y.z : { w: boolean; } | undefined
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
>z : { w: boolean; } | undefined
o5.x?.y.z?.w;
>o5.x?.y.z?.w : boolean | undefined
>o5.x?.y.z : { w: boolean; } | undefined
->o5.x?.y : { z?: { w: boolean; } | undefined; } | undefined
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; } | undefined
+>o5.x?.y : { z?: { w: boolean; }; } | undefined
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; } | undefined
>z : { w: boolean; } | undefined
>w : boolean | undefined
o5.x.y;
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; }
o5.x.y.z.w;
>o5.x.y.z.w : boolean
>o5.x.y.z : { w: boolean; } | undefined
->o5.x.y : { z?: { w: boolean; } | undefined; }
->o5.x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->o5 : { x?: { y: { z?: { w: boolean; } | undefined; }; } | undefined; }
->x : { y: { z?: { w: boolean; } | undefined; }; } | undefined
->y : { z?: { w: boolean; } | undefined; }
+>o5.x.y : { z?: { w: boolean; }; }
+>o5.x : { y: { z?: { w: boolean; }; }; } | undefined
+>o5 : { x?: { y: { z?: { w: boolean; }; }; }; }
+>x : { y: { z?: { w: boolean; }; }; } | undefined
+>y : { z?: { w: boolean; }; }
>z : { w: boolean; } | undefined
>w : boolean
diff --git a/tests/baselines/reference/deleteChain.types b/tests/baselines/reference/deleteChain.types
index 2e5f7fedd3135..a2f3f7ce4c36c 100644
--- a/tests/baselines/reference/deleteChain.types
+++ b/tests/baselines/reference/deleteChain.types
@@ -61,9 +61,9 @@ delete (o3.b?.c);
>c : string | undefined
declare const o4: { b?: { c: { d?: { e: string } } } };
->o4 : { b?: { c: { d?: { e: string; };}; } | undefined; }
+>o4 : { b?: { c: { d?: { e: string; }; };}; }
>b : { c: { d?: { e: string; };}; } | undefined
->c : { d?: { e: string; } | undefined; }
+>c : { d?: { e: string;}; }
>d : { e: string; } | undefined
>e : string
@@ -71,11 +71,11 @@ delete o4.b?.c.d?.e;
>delete o4.b?.c.d?.e : boolean
>o4.b?.c.d?.e : string | undefined
>o4.b?.c.d : { e: string; } | undefined
->o4.b?.c : { d?: { e: string; } | undefined; } | undefined
->o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
->c : { d?: { e: string; } | undefined; } | undefined
+>o4.b?.c : { d?: { e: string; }; } | undefined
+>o4.b : { c: { d?: { e: string; }; }; } | undefined
+>o4 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
+>c : { d?: { e: string; }; } | undefined
>d : { e: string; } | undefined
>e : string | undefined
@@ -84,11 +84,11 @@ delete (o4.b?.c.d)?.e;
>(o4.b?.c.d)?.e : string | undefined
>(o4.b?.c.d) : { e: string; } | undefined
>o4.b?.c.d : { e: string; } | undefined
->o4.b?.c : { d?: { e: string; } | undefined; } | undefined
->o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
->c : { d?: { e: string; } | undefined; } | undefined
+>o4.b?.c : { d?: { e: string; }; } | undefined
+>o4.b : { c: { d?: { e: string; }; }; } | undefined
+>o4 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
+>c : { d?: { e: string; }; } | undefined
>d : { e: string; } | undefined
>e : string | undefined
@@ -97,18 +97,18 @@ delete (o4.b?.c.d?.e);
>(o4.b?.c.d?.e) : string | undefined
>o4.b?.c.d?.e : string | undefined
>o4.b?.c.d : { e: string; } | undefined
->o4.b?.c : { d?: { e: string; } | undefined; } | undefined
->o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
->c : { d?: { e: string; } | undefined; } | undefined
+>o4.b?.c : { d?: { e: string; }; } | undefined
+>o4.b : { c: { d?: { e: string; }; }; } | undefined
+>o4 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
+>c : { d?: { e: string; }; } | undefined
>d : { e: string; } | undefined
>e : string | undefined
declare const o5: { b?(): { c: { d?: { e: string } } } };
>o5 : { b?(): { c: { d?: { e: string; }; };}; }
>b : (() => { c: { d?: { e: string; }; };}) | undefined
->c : { d?: { e: string; } | undefined; }
+>c : { d?: { e: string;}; }
>d : { e: string; } | undefined
>e : string
@@ -116,12 +116,12 @@ delete o5.b?.().c.d?.e;
>delete o5.b?.().c.d?.e : boolean
>o5.b?.().c.d?.e : string | undefined
>o5.b?.().c.d : { e: string; } | undefined
->o5.b?.().c : { d?: { e: string; } | undefined; } | undefined
->o5.b?.() : { c: { d?: { e: string; } | undefined; }; } | undefined
->o5.b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; }
->b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->c : { d?: { e: string; } | undefined; } | undefined
+>o5.b?.().c : { d?: { e: string; }; } | undefined
+>o5.b?.() : { c: { d?: { e: string; }; }; } | undefined
+>o5.b : (() => { c: { d?: { e: string; }; }; }) | undefined
+>o5 : { b?(): { c: { d?: { e: string; }; }; }; }
+>b : (() => { c: { d?: { e: string; }; }; }) | undefined
+>c : { d?: { e: string; }; } | undefined
>d : { e: string; } | undefined
>e : string | undefined
@@ -130,19 +130,19 @@ delete (o5.b?.().c.d?.e);
>(o5.b?.().c.d?.e) : string | undefined
>o5.b?.().c.d?.e : string | undefined
>o5.b?.().c.d : { e: string; } | undefined
->o5.b?.().c : { d?: { e: string; } | undefined; } | undefined
->o5.b?.() : { c: { d?: { e: string; } | undefined; }; } | undefined
->o5.b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; }
->b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->c : { d?: { e: string; } | undefined; } | undefined
+>o5.b?.().c : { d?: { e: string; }; } | undefined
+>o5.b?.() : { c: { d?: { e: string; }; }; } | undefined
+>o5.b : (() => { c: { d?: { e: string; }; }; }) | undefined
+>o5 : { b?(): { c: { d?: { e: string; }; }; }; }
+>b : (() => { c: { d?: { e: string; }; }; }) | undefined
+>c : { d?: { e: string; }; } | undefined
>d : { e: string; } | undefined
>e : string | undefined
declare const o6: { b?: { c: { d?: { e: string } } } };
->o6 : { b?: { c: { d?: { e: string; };}; } | undefined; }
+>o6 : { b?: { c: { d?: { e: string; }; };}; }
>b : { c: { d?: { e: string; };}; } | undefined
->c : { d?: { e: string; } | undefined; }
+>c : { d?: { e: string;}; }
>d : { e: string; } | undefined
>e : string
@@ -150,10 +150,10 @@ delete o6.b?.['c'].d?.['e'];
>delete o6.b?.['c'].d?.['e'] : boolean
>o6.b?.['c'].d?.['e'] : string | undefined
>o6.b?.['c'].d : { e: string; } | undefined
->o6.b?.['c'] : { d?: { e: string; } | undefined; } | undefined
->o6.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o6 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
+>o6.b?.['c'] : { d?: { e: string; }; } | undefined
+>o6.b : { c: { d?: { e: string; }; }; } | undefined
+>o6 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
>'c' : "c"
>d : { e: string; } | undefined
>'e' : "e"
@@ -163,10 +163,10 @@ delete (o6.b?.['c'].d?.['e']);
>(o6.b?.['c'].d?.['e']) : string | undefined
>o6.b?.['c'].d?.['e'] : string | undefined
>o6.b?.['c'].d : { e: string; } | undefined
->o6.b?.['c'] : { d?: { e: string; } | undefined; } | undefined
->o6.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o6 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
+>o6.b?.['c'] : { d?: { e: string; }; } | undefined
+>o6.b : { c: { d?: { e: string; }; }; } | undefined
+>o6 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
>'c' : "c"
>d : { e: string; } | undefined
>'e' : "e"
diff --git a/tests/baselines/reference/destructuringControlFlow.types b/tests/baselines/reference/destructuringControlFlow.types
index 02deb39200688..6c04cfd193c5a 100644
--- a/tests/baselines/reference/destructuringControlFlow.types
+++ b/tests/baselines/reference/destructuringControlFlow.types
@@ -1,29 +1,29 @@
=== tests/cases/conformance/es6/destructuring/destructuringControlFlow.ts ===
function f1(obj: { a?: string }) {
>f1 : (obj: { a?: string;}) => void
->obj : { a?: string | undefined; }
+>obj : { a?: string; }
>a : string | undefined
if (obj.a) {
>obj.a : string | undefined
->obj : { a?: string | undefined; }
+>obj : { a?: string; }
>a : string | undefined
obj = {};
>obj = {} : {}
->obj : { a?: string | undefined; }
+>obj : { a?: string; }
>{} : {}
let a1 = obj["a"]; // string | undefined
>a1 : string | undefined
>obj["a"] : string | undefined
->obj : { a?: string | undefined; }
+>obj : { a?: string; }
>"a" : "a"
let a2 = obj.a; // string | undefined
>a2 : string | undefined
>obj.a : string | undefined
->obj : { a?: string | undefined; }
+>obj : { a?: string; }
>a : string | undefined
}
}
@@ -96,31 +96,31 @@ function f2(obj: [number, string] | null[]) {
function f3(obj: { a?: number, b?: string }) {
>f3 : (obj: { a?: number; b?: string;}) => void
->obj : { a?: number | undefined; b?: string | undefined; }
+>obj : { a?: number; b?: string; }
>a : number | undefined
>b : string | undefined
if (obj.a && obj.b) {
>obj.a && obj.b : string | 0 | undefined
>obj.a : number | undefined
->obj : { a?: number | undefined; b?: string | undefined; }
+>obj : { a?: number; b?: string; }
>a : number | undefined
>obj.b : string | undefined
->obj : { a?: number | undefined; b?: string | undefined; }
+>obj : { a?: number; b?: string; }
>b : string | undefined
let { a, b } = obj; // number, string
>a : number
>b : string
->obj : { a?: number | undefined; b?: string | undefined; }
+>obj : { a?: number; b?: string; }
({ a, b } = obj);
->({ a, b } = obj) : { a?: number | undefined; b?: string | undefined; }
->{ a, b } = obj : { a?: number | undefined; b?: string | undefined; }
+>({ a, b } = obj) : { a?: number; b?: string; }
+>{ a, b } = obj : { a?: number; b?: string; }
>{ a, b } : { a: number; b: string; }
>a : number
>b : string
->obj : { a?: number | undefined; b?: string | undefined; }
+>obj : { a?: number; b?: string; }
}
}
diff --git a/tests/baselines/reference/elementAccessChain.types b/tests/baselines/reference/elementAccessChain.types
index ccb7d97460464..681312b515cb6 100644
--- a/tests/baselines/reference/elementAccessChain.types
+++ b/tests/baselines/reference/elementAccessChain.types
@@ -47,19 +47,19 @@ o3.b?.["c"];
>"c" : "c"
declare const o4: { b?: { c: { d?: { e: string } } } };
->o4 : { b?: { c: { d?: { e: string; };}; } | undefined; }
+>o4 : { b?: { c: { d?: { e: string; }; };}; }
>b : { c: { d?: { e: string; };}; } | undefined
->c : { d?: { e: string; } | undefined; }
+>c : { d?: { e: string;}; }
>d : { e: string; } | undefined
>e : string
o4.b?.["c"].d?.e;
>o4.b?.["c"].d?.e : string | undefined
>o4.b?.["c"].d : { e: string; } | undefined
->o4.b?.["c"] : { d?: { e: string; } | undefined; } | undefined
->o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
+>o4.b?.["c"] : { d?: { e: string; }; } | undefined
+>o4.b : { c: { d?: { e: string; }; }; } | undefined
+>o4 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
>"c" : "c"
>d : { e: string; } | undefined
>e : string | undefined
@@ -67,10 +67,10 @@ o4.b?.["c"].d?.e;
o4.b?.["c"].d?.["e"];
>o4.b?.["c"].d?.["e"] : string | undefined
>o4.b?.["c"].d : { e: string; } | undefined
->o4.b?.["c"] : { d?: { e: string; } | undefined; } | undefined
->o4.b : { c: { d?: { e: string; } | undefined; }; } | undefined
->o4 : { b?: { c: { d?: { e: string; } | undefined; }; } | undefined; }
->b : { c: { d?: { e: string; } | undefined; }; } | undefined
+>o4.b?.["c"] : { d?: { e: string; }; } | undefined
+>o4.b : { c: { d?: { e: string; }; }; } | undefined
+>o4 : { b?: { c: { d?: { e: string; }; }; }; }
+>b : { c: { d?: { e: string; }; }; } | undefined
>"c" : "c"
>d : { e: string; } | undefined
>"e" : "e"
@@ -78,18 +78,18 @@ o4.b?.["c"].d?.["e"];
declare const o5: { b?(): { c: { d?: { e: string } } } };
>o5 : { b?(): { c: { d?: { e: string; }; };}; }
>b : (() => { c: { d?: { e: string; }; };}) | undefined
->c : { d?: { e: string; } | undefined; }
+>c : { d?: { e: string;}; }
>d : { e: string; } | undefined
>e : string
o5.b?.()["c"].d?.e;
>o5.b?.()["c"].d?.e : string | undefined
>o5.b?.()["c"].d : { e: string; } | undefined
->o5.b?.()["c"] : { d?: { e: string; } | undefined; } | undefined
->o5.b?.() : { c: { d?: { e: string; } | undefined; }; } | undefined
->o5.b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; }
->b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
+>o5.b?.()["c"] : { d?: { e: string; }; } | undefined
+>o5.b?.() : { c: { d?: { e: string; }; }; } | undefined
+>o5.b : (() => { c: { d?: { e: string; }; }; }) | undefined
+>o5 : { b?(): { c: { d?: { e: string; }; }; }; }
+>b : (() => { c: { d?: { e: string; }; }; }) | undefined
>"c" : "c"
>d : { e: string; } | undefined
>e : string | undefined
@@ -97,11 +97,11 @@ o5.b?.()["c"].d?.e;
o5.b?.()["c"].d?.["e"];
>o5.b?.()["c"].d?.["e"] : string | undefined
>o5.b?.()["c"].d : { e: string; } | undefined
->o5.b?.()["c"] : { d?: { e: string; } | undefined; } | undefined
->o5.b?.() : { c: { d?: { e: string; } | undefined; }; } | undefined
->o5.b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; }
->b : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
+>o5.b?.()["c"] : { d?: { e: string; }; } | undefined
+>o5.b?.() : { c: { d?: { e: string; }; }; } | undefined
+>o5.b : (() => { c: { d?: { e: string; }; }; }) | undefined
+>o5 : { b?(): { c: { d?: { e: string; }; }; }; }
+>b : (() => { c: { d?: { e: string; }; }; }) | undefined
>"c" : "c"
>d : { e: string; } | undefined
>"e" : "e"
@@ -109,10 +109,10 @@ o5.b?.()["c"].d?.["e"];
o5["b"]?.()["c"].d?.e;
>o5["b"]?.()["c"].d?.e : string | undefined
>o5["b"]?.()["c"].d : { e: string; } | undefined
->o5["b"]?.()["c"] : { d?: { e: string; } | undefined; } | undefined
->o5["b"]?.() : { c: { d?: { e: string; } | undefined; }; } | undefined
->o5["b"] : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; }
+>o5["b"]?.()["c"] : { d?: { e: string; }; } | undefined
+>o5["b"]?.() : { c: { d?: { e: string; }; }; } | undefined
+>o5["b"] : (() => { c: { d?: { e: string; }; }; }) | undefined
+>o5 : { b?(): { c: { d?: { e: string; }; }; }; }
>"b" : "b"
>"c" : "c"
>d : { e: string; } | undefined
@@ -121,10 +121,10 @@ o5["b"]?.()["c"].d?.e;
o5["b"]?.()["c"].d?.["e"];
>o5["b"]?.()["c"].d?.["e"] : string | undefined
>o5["b"]?.()["c"].d : { e: string; } | undefined
->o5["b"]?.()["c"] : { d?: { e: string; } | undefined; } | undefined
->o5["b"]?.() : { c: { d?: { e: string; } | undefined; }; } | undefined
->o5["b"] : (() => { c: { d?: { e: string; } | undefined; }; }) | undefined
->o5 : { b?(): { c: { d?: { e: string; } | undefined; }; }; }
+>o5["b"]?.()["c"] : { d?: { e: string; }; } | undefined
+>o5["b"]?.() : { c: { d?: { e: string; }; }; } | undefined
+>o5["b"] : (() => { c: { d?: { e: string; }; }; }) | undefined
+>o5 : { b?(): { c: { d?: { e: string; }; }; }; }
>"b" : "b"
>"c" : "c"
>d : { e: string; } | undefined
diff --git a/tests/baselines/reference/homomorphicMappedTypeIntersectionAssignability.types b/tests/baselines/reference/homomorphicMappedTypeIntersectionAssignability.types
index f89f132dcc875..bf10a7f1585d1 100644
--- a/tests/baselines/reference/homomorphicMappedTypeIntersectionAssignability.types
+++ b/tests/baselines/reference/homomorphicMappedTypeIntersectionAssignability.types
@@ -3,7 +3,7 @@ function f(
>f : (a: { weak?: string;} & Readonly & { name: "ok";}, b: Readonly, c: Readonly & { name: string;}) => void
a: { weak?: string } & Readonly & { name: "ok" },
->a : { weak?: string | undefined; } & Readonly & { name: "ok"; }
+>a : { weak?: string; } & Readonly & { name: "ok"; }
>weak : string | undefined
>name : "ok"
@@ -16,13 +16,13 @@ function f(
>name : string
c = a; // Works
->c = a : { weak?: string | undefined; } & Readonly & { name: "ok"; }
+>c = a : { weak?: string; } & Readonly & { name: "ok"; }
>c : Readonly & { name: string; }
->a : { weak?: string | undefined; } & Readonly & { name: "ok"; }
+>a : { weak?: string; } & Readonly & { name: "ok"; }
b = a; // Should also work
->b = a : { weak?: string | undefined; } & Readonly & { name: "ok"; }
+>b = a : { weak?: string; } & Readonly & { name: "ok"; }
>b : Readonly
->a : { weak?: string | undefined; } & Readonly & { name: "ok"; }
+>a : { weak?: string; } & Readonly & { name: "ok"; }
}
diff --git a/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.types b/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.types
index b707b156b2ea2..8c5ce88ac26f9 100644
--- a/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.types
+++ b/tests/baselines/reference/inferenceOptionalPropertiesToIndexSignatures.types
@@ -15,7 +15,7 @@ declare const x2: { a: string, b: number | undefined };
>b : number | undefined
declare const x3: { a: string, b?: number };
->x3 : { a: string; b?: number | undefined; }
+>x3 : { a: string; b?: number; }
>a : string
>b : number | undefined
@@ -40,7 +40,7 @@ let a3 = foo(x3); // string | number
>a3 : string | number
>foo(x3) : string | number
>foo : (obj: { [x: string]: T; }) => T
->x3 : { a: string; b?: number | undefined; }
+>x3 : { a: string; b?: number; }
let a4 = foo(x4); // string | number
>a4 : string | number
@@ -63,8 +63,8 @@ const param2 = Math.random() < 0.5 ? 'value2' : null;
>null : null
const obj = {
->obj : { param2?: string | undefined; param1: string; }
->{ param1: 'value1', ...(param2 ? {param2} : {})} : { param2?: string | undefined; param1: string; }
+>obj : { param2?: string; param1: string; }
+>{ param1: 'value1', ...(param2 ? {param2} : {})} : { param2?: string; param1: string; }
param1: 'value1',
>param1 : string
@@ -90,7 +90,7 @@ const query = Object.entries(obj).map(
>Object.entries : { (o: { [s: string]: T; } | ArrayLike): [string, T][]; (o: {}): [string, any][]; }
>Object : ObjectConstructor
>entries : { (o: { [s: string]: T; } | ArrayLike): [string, T][]; (o: {}): [string, any][]; }
->obj : { param2?: string | undefined; param1: string; }
+>obj : { param2?: string; param1: string; }
>map : (callbackfn: (value: [string, string], index: number, array: [string, string][]) => U, thisArg?: any) => U[]
([k, v]) => `${k}=${encodeURIComponent(v)}`
diff --git a/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types
index 5035da7bcef17..f6eb1f4f8107b 100644
--- a/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types
+++ b/tests/baselines/reference/initializedParameterBeforeNonoptionalNotOptional.types
@@ -1,6 +1,6 @@
=== tests/cases/compiler/index.d.ts ===
export declare function foo({a}?: {
->foo : ({ a }?: { a?: string | undefined; } | undefined) => void
+>foo : ({ a }?: { a?: string; } | undefined) => void
>a : string | undefined
a?: string;
diff --git a/tests/baselines/reference/instantiateContextualTypes.types b/tests/baselines/reference/instantiateContextualTypes.types
index ff6154c78589c..902114916c494 100644
--- a/tests/baselines/reference/instantiateContextualTypes.types
+++ b/tests/baselines/reference/instantiateContextualTypes.types
@@ -221,7 +221,7 @@ interface ComponentClass {
}
type CreateElementChildren
=
->CreateElementChildren : P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown
+>CreateElementChildren : P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown
P extends { children?: infer C }
>children : C | undefined
@@ -232,24 +232,24 @@ type CreateElementChildren
=
: unknown;
declare function createElement
(
->createElement :
(type: ComponentClass
, ...children: P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown) => any
+>createElement :
(type: ComponentClass
, ...children: P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown) => any
type: ComponentClass
,
>type : ComponentClass
...children: CreateElementChildren
->children : P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown
+>children : P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown
): any;
declare function createElement2
(
->createElement2 :
(type: ComponentClass
, child: P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown) => any
+>createElement2 :
(type: ComponentClass
, child: P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown) => any
type: ComponentClass
,
>type : ComponentClass
child: CreateElementChildren
->child : P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown
+>child : P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown
): any;
@@ -261,7 +261,7 @@ class InferFunctionTypes extends Component<{children: (foo: number) => string}>
createElement(InferFunctionTypes, (foo) => "" + foo);
>createElement(InferFunctionTypes, (foo) => "" + foo) : any
->createElement :
(type: ComponentClass
, ...children: P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown) => any
+>createElement :
(type: ComponentClass
, ...children: P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown) => any
>InferFunctionTypes : typeof InferFunctionTypes
>(foo) => "" + foo : (foo: number) => string
>foo : number
@@ -271,7 +271,7 @@ createElement(InferFunctionTypes, (foo) => "" + foo);
createElement2(InferFunctionTypes, [(foo) => "" + foo]);
>createElement2(InferFunctionTypes, [(foo) => "" + foo]) : any
->createElement2 :
(type: ComponentClass
, child: P extends { children?: infer C | undefined; } ? C extends any[] ? C : C[] : unknown) => any
+>createElement2 :
(type: ComponentClass
, child: P extends { children?: infer C; } ? C extends any[] ? C : C[] : unknown) => any
>InferFunctionTypes : typeof InferFunctionTypes
>[(foo) => "" + foo] : ((foo: number) => string)[]
>(foo) => "" + foo : (foo: number) => string
diff --git a/tests/baselines/reference/intersectionPropertyCheck.errors.txt b/tests/baselines/reference/intersectionPropertyCheck.errors.txt
index 7c74c3512eaf1..494832fec8123 100644
--- a/tests/baselines/reference/intersectionPropertyCheck.errors.txt
+++ b/tests/baselines/reference/intersectionPropertyCheck.errors.txt
@@ -1,12 +1,12 @@
tests/cases/compiler/intersectionPropertyCheck.ts(1,68): error TS2322: Type '{ x: string; y: number; }' is not assignable to type '{ x: string; }'.
Object literal may only specify known properties, and 'y' does not exist in type '{ x: string; }'.
-tests/cases/compiler/intersectionPropertyCheck.ts(4,5): error TS2322: Type '{ a: { y: string; }; }' is not assignable to type '{ a?: { x?: number | undefined; } | undefined; } & { c?: string | undefined; }'.
+tests/cases/compiler/intersectionPropertyCheck.ts(4,5): error TS2322: Type '{ a: { y: string; }; }' is not assignable to type '{ a?: { x?: number; }; } & { c?: string; }'.
Types of property 'a' are incompatible.
- Type '{ y: string; }' has no properties in common with type '{ x?: number | undefined; }'.
-tests/cases/compiler/intersectionPropertyCheck.ts(7,3): error TS2322: Type 'T & { a: boolean; }' is not assignable to type '{ a?: string | undefined; }'.
+ Type '{ y: string; }' has no properties in common with type '{ x?: number; }'.
+tests/cases/compiler/intersectionPropertyCheck.ts(7,3): error TS2322: Type 'T & { a: boolean; }' is not assignable to type '{ a?: string; }'.
Types of property 'a' are incompatible.
- Type 'boolean' is not assignable to type 'string | undefined'.
-tests/cases/compiler/intersectionPropertyCheck.ts(17,22): error TS2322: Type 'true' is not assignable to type 'string[] | undefined'.
+ Type 'boolean' is not assignable to type 'string'.
+tests/cases/compiler/intersectionPropertyCheck.ts(17,22): error TS2322: Type 'boolean' is not assignable to type 'string[]'.
==== tests/cases/compiler/intersectionPropertyCheck.ts (4 errors) ====
@@ -19,16 +19,16 @@ tests/cases/compiler/intersectionPropertyCheck.ts(17,22): error TS2322: Type 'tr
declare let wrong: { a: { y: string } };
let weak: { a?: { x?: number } } & { c?: string } = wrong; // Nested weak object type
~~~~
-!!! error TS2322: Type '{ a: { y: string; }; }' is not assignable to type '{ a?: { x?: number | undefined; } | undefined; } & { c?: string | undefined; }'.
+!!! error TS2322: Type '{ a: { y: string; }; }' is not assignable to type '{ a?: { x?: number; }; } & { c?: string; }'.
!!! error TS2322: Types of property 'a' are incompatible.
-!!! error TS2322: Type '{ y: string; }' has no properties in common with type '{ x?: number | undefined; }'.
+!!! error TS2322: Type '{ y: string; }' has no properties in common with type '{ x?: number; }'.
function foo(x: { a?: string }, y: T & { a: boolean }) {
x = y; // Mismatched property in source intersection
~
-!!! error TS2322: Type 'T & { a: boolean; }' is not assignable to type '{ a?: string | undefined; }'.
+!!! error TS2322: Type 'T & { a: boolean; }' is not assignable to type '{ a?: string; }'.
!!! error TS2322: Types of property 'a' are incompatible.
-!!! error TS2322: Type 'boolean' is not assignable to type 'string | undefined'.
+!!! error TS2322: Type 'boolean' is not assignable to type 'string'.
}
// Repro from #36637
@@ -40,7 +40,7 @@ tests/cases/compiler/intersectionPropertyCheck.ts(17,22): error TS2322: Type 'tr
function test(value: T): Test {
return { ...value, hi: true }
~~
-!!! error TS2322: Type 'true' is not assignable to type 'string[] | undefined'.
+!!! error TS2322: Type 'boolean' is not assignable to type 'string[]'.
!!! related TS6500 tests/cases/compiler/intersectionPropertyCheck.ts:13:12: The expected type comes from property 'hi' which is declared here on type 'Test'
}
\ No newline at end of file
diff --git a/tests/baselines/reference/intersectionPropertyCheck.types b/tests/baselines/reference/intersectionPropertyCheck.types
index 515d5009732fd..5b37490ea88cf 100644
--- a/tests/baselines/reference/intersectionPropertyCheck.types
+++ b/tests/baselines/reference/intersectionPropertyCheck.types
@@ -20,22 +20,22 @@ declare let wrong: { a: { y: string } };
>y : string
let weak: { a?: { x?: number } } & { c?: string } = wrong; // Nested weak object type
->weak : { a?: { x?: number | undefined; } | undefined; } & { c?: string | undefined; }
->a : { x?: number | undefined; } | undefined
+>weak : { a?: { x?: number;}; } & { c?: string; }
+>a : { x?: number; } | undefined
>x : number | undefined
>c : string | undefined
>wrong : { a: { y: string; }; }
function foo(x: { a?: string }, y: T & { a: boolean }) {
>foo : (x: { a?: string;}, y: T & { a: boolean;}) => void
->x : { a?: string | undefined; }
+>x : { a?: string; }
>a : string | undefined
>y : T & { a: boolean; }
>a : boolean
x = y; // Mismatched property in source intersection
>x = y : T & { a: boolean; }
->x : { a?: string | undefined; }
+>x : { a?: string; }
>y : T & { a: boolean; }
}
diff --git a/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt b/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt
index faa8b067b1ac3..2bd15c04d42d6 100644
--- a/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt
+++ b/tests/baselines/reference/intersectionsAndOptionalProperties.errors.txt
@@ -1,13 +1,13 @@
-tests/cases/compiler/intersectionsAndOptionalProperties.ts(5,1): error TS2322: Type '{ a: null; b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'.
+tests/cases/compiler/intersectionsAndOptionalProperties.ts(5,1): error TS2322: Type '{ a: null; b: string; }' is not assignable to type '{ a?: number; b: string; }'.
Types of property 'a' are incompatible.
- Type 'null' is not assignable to type 'number | undefined'.
-tests/cases/compiler/intersectionsAndOptionalProperties.ts(6,1): error TS2322: Type '{ a: null; } & { b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'.
+ Type 'null' is not assignable to type 'number'.
+tests/cases/compiler/intersectionsAndOptionalProperties.ts(6,1): error TS2322: Type '{ a: null; } & { b: string; }' is not assignable to type '{ a?: number; b: string; }'.
Types of property 'a' are incompatible.
- Type 'null' is not assignable to type 'number | undefined'.
+ Type 'null' is not assignable to type 'number'.
tests/cases/compiler/intersectionsAndOptionalProperties.ts(19,5): error TS2322: Type 'From' is not assignable to type 'To'.
Types of property 'field' are incompatible.
- Type 'null' is not assignable to type 'number | undefined'.
-tests/cases/compiler/intersectionsAndOptionalProperties.ts(20,5): error TS2322: Type 'null' is not assignable to type 'number | undefined'.
+ Type 'null' is not assignable to type 'number'.
+tests/cases/compiler/intersectionsAndOptionalProperties.ts(20,5): error TS2322: Type 'null' is not assignable to type 'number'.
==== tests/cases/compiler/intersectionsAndOptionalProperties.ts (4 errors) ====
@@ -17,14 +17,14 @@ tests/cases/compiler/intersectionsAndOptionalProperties.ts(20,5): error TS2322:
x = y; // Error
~
-!!! error TS2322: Type '{ a: null; b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'.
+!!! error TS2322: Type '{ a: null; b: string; }' is not assignable to type '{ a?: number; b: string; }'.
!!! error TS2322: Types of property 'a' are incompatible.
-!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'.
+!!! error TS2322: Type 'null' is not assignable to type 'number'.
x = z; // Error
~
-!!! error TS2322: Type '{ a: null; } & { b: string; }' is not assignable to type '{ a?: number | undefined; b: string; }'.
+!!! error TS2322: Type '{ a: null; } & { b: string; }' is not assignable to type '{ a?: number; b: string; }'.
!!! error TS2322: Types of property 'a' are incompatible.
-!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'.
+!!! error TS2322: Type 'null' is not assignable to type 'number'.
// Repro from #36604
@@ -41,10 +41,10 @@ tests/cases/compiler/intersectionsAndOptionalProperties.ts(20,5): error TS2322:
~
!!! error TS2322: Type 'From' is not assignable to type 'To'.
!!! error TS2322: Types of property 'field' are incompatible.
-!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'.
+!!! error TS2322: Type 'null' is not assignable to type 'number'.
x.field = v.field; // Error
~~~~~~~
-!!! error TS2322: Type 'null' is not assignable to type 'number | undefined'.
+!!! error TS2322: Type 'null' is not assignable to type 'number'.
}
// Repro from #38348
diff --git a/tests/baselines/reference/intersectionsAndOptionalProperties.types b/tests/baselines/reference/intersectionsAndOptionalProperties.types
index 98bc85c7e4299..655cdc513839f 100644
--- a/tests/baselines/reference/intersectionsAndOptionalProperties.types
+++ b/tests/baselines/reference/intersectionsAndOptionalProperties.types
@@ -1,6 +1,6 @@
=== tests/cases/compiler/intersectionsAndOptionalProperties.ts ===
declare let x: { a?: number, b: string };
->x : { a?: number | undefined; b: string; }
+>x : { a?: number; b: string; }
>a : number | undefined
>b : string
@@ -18,12 +18,12 @@ declare let z: { a: null } & { b: string };
x = y; // Error
>x = y : { a: null; b: string; }
->x : { a?: number | undefined; b: string; }
+>x : { a?: number; b: string; }
>y : { a: null; b: string; }
x = z; // Error
>x = z : { a: null; } & { b: string; }
->x : { a?: number | undefined; b: string; }
+>x : { a?: number; b: string; }
>z : { a: null; } & { b: string; }
// Repro from #36604
@@ -55,9 +55,9 @@ function foo(v: From) {
x.field = v.field; // Error
>x.field = v.field : null
->x.field : number | undefined
+>x.field : number
>x : To
->field : number | undefined
+>field : number
>v.field : null
>v : From
>field : null
diff --git a/tests/baselines/reference/jsDeclarationsReactComponents.types b/tests/baselines/reference/jsDeclarationsReactComponents.types
index 4934a173b935b..17a63894fddf4 100644
--- a/tests/baselines/reference/jsDeclarationsReactComponents.types
+++ b/tests/baselines/reference/jsDeclarationsReactComponents.types
@@ -61,7 +61,7 @@ import React from "react";
*/
const TabbedShowLayout = () => {
>TabbedShowLayout : React.SFC<{}>
->() => { return ( ok
);} : { (): JSX.Element; defaultProps: Partial<{}> | undefined; }
+>() => { return ( ok
);} : { (): JSX.Element; defaultProps: Partial<{}>; }
return (
>( ok
) : JSX.Element
@@ -81,9 +81,9 @@ const TabbedShowLayout = () => {
TabbedShowLayout.defaultProps = {
>TabbedShowLayout.defaultProps = { tabs: "default value"} : { tabs: string; }
->TabbedShowLayout.defaultProps : Partial<{}> | undefined
+>TabbedShowLayout.defaultProps : Partial<{}>
>TabbedShowLayout : React.SFC<{}>
->defaultProps : Partial<{}> | undefined
+>defaultProps : Partial<{}>
>{ tabs: "default value"} : { tabs: string; }
tabs: "default value"
diff --git a/tests/baselines/reference/jsxComplexSignatureHasApplicabilityError.errors.txt b/tests/baselines/reference/jsxComplexSignatureHasApplicabilityError.errors.txt
new file mode 100644
index 0000000000000..a10ae139e0381
--- /dev/null
+++ b/tests/baselines/reference/jsxComplexSignatureHasApplicabilityError.errors.txt
@@ -0,0 +1,626 @@
+tests/cases/compiler/jsxComplexSignatureHasApplicabilityError.tsx(31,17): error TS2769: No overload matches this call.
+ Overload 1 of 2, '(props: Readonly>>): ReactSelectClass>', gave the following error.
+ Type 'ExtractValueType | Option> | undefined' is not assignable to type 'string | number | boolean | string[] | number[] | Option> | Options>'.
+ Type 'undefined' is not assignable to type 'string | number | boolean | string[] | number[] | Option> | Options>'.
+ Overload 2 of 2, '(props: ReactSelectProps>, context?: any): ReactSelectClass>', gave the following error.
+ Type 'ExtractValueType | Option> | undefined' is not assignable to type 'string | number | boolean | string[] | number[] | Option> | Options>'.
+
+
+==== tests/cases/compiler/jsxComplexSignatureHasApplicabilityError.tsx (1 errors) ====
+ ///
+
+ import * as React from "react";
+
+
+ interface Props {
+ value?: Option | T;
+ onChange?(value: Option | undefined): void;
+ }
+
+ type ExtractValueType = T extends ReactSelectProps ? U : never;
+
+ export type ReactSingleSelectProps<
+ WrappedProps extends ReactSelectProps
+ > = Overwrite<
+ Omit,
+ Props>
+ >;
+
+ export function createReactSingleSelect<
+ WrappedProps extends ReactSelectProps
+ >(
+ WrappedComponent: React.ComponentType
+ ): React.ComponentType> {
+ return (props) => {
+ return (
+ >
+ {...props}
+ multi={false}
+ autosize={false}
+ value={props.value}
+ ~~~~~
+!!! error TS2769: No overload matches this call.
+!!! error TS2769: Overload 1 of 2, '(props: Readonly>>): ReactSelectClass>', gave the following error.
+!!! error TS2769: Type 'ExtractValueType | Option> | undefined' is not assignable to type 'string | number | boolean | string[] | number[] | Option> | Options>'.
+!!! error TS2769: Type 'undefined' is not assignable to type 'string | number | boolean | string[] | number[] | Option> | Options>'.
+!!! error TS2769: Overload 2 of 2, '(props: ReactSelectProps>, context?: any): ReactSelectClass>', gave the following error.
+!!! error TS2769: Type 'ExtractValueType | Option> | undefined' is not assignable to type 'string | number | boolean | string[] | number[] | Option> | Options>'.
+!!! related TS6500 tests/cases/compiler/jsxComplexSignatureHasApplicabilityError.tsx:567:5: The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes>> & Readonly<{ children?: ReactNode; }> & Readonly>>'
+!!! related TS6500 tests/cases/compiler/jsxComplexSignatureHasApplicabilityError.tsx:567:5: The expected type comes from property 'value' which is declared here on type 'IntrinsicAttributes & IntrinsicClassAttributes>> & Readonly<{ children?: ReactNode; }> & Readonly>>'
+ onChange={(value) => {
+ if (props.onChange) {
+ props.onChange(value === null ? undefined : value);
+ }
+ }}
+ />
+ );
+ };
+ }
+
+
+ // Copied from "type-zoo" version 3.4.0
+ export type Omit = T extends any ? Pick> : never;
+ export type Overwrite = Omit & U;
+
+ // Everything below here copied from "@types/react-select" version 1.3.4
+ declare class ReactSelectClass extends React.Component> {
+ focus(): void;
+ setValue(value: Option): void;
+ }
+
+ export type OptionComponentType = React.ComponentType>;
+ export type ValueComponentType = React.ComponentType>;
+
+ export type HandlerRendererResult = JSX.Element | null | false;
+
+ // Handlers
+ export type FocusOptionHandler = (option: Option) => void;
+ export type SelectValueHandler = (option: Option) => void;
+ export type ArrowRendererHandler = (props: ArrowRendererProps) => HandlerRendererResult;
+ export type ClearRendererHandler = () => HandlerRendererResult;
+ export type FilterOptionHandler = (option: Option, filter: string) => boolean;
+ export type FilterOptionsHandler = (options: Options, filter: string, currentValues: Options) => Options;
+ export type InputRendererHandler = (props: { [key: string]: any }) => HandlerRendererResult;
+ export type MenuRendererHandler = (props: MenuRendererProps) => HandlerRendererResult;
+ export type OnCloseHandler = () => void;
+ export type OnInputChangeHandler = (inputValue: string) => string;
+ export type OnInputKeyDownHandler = React.KeyboardEventHandler;
+ export type OnMenuScrollToBottomHandler = () => void;
+ export type OnOpenHandler = () => void;
+ export type OnFocusHandler = React.FocusEventHandler;
+ export type OnBlurHandler = React.FocusEventHandler;
+ export type OptionRendererHandler = (option: Option) => HandlerRendererResult;
+ export type ValueRendererHandler = (option: Option, index?: number) => HandlerRendererResult;
+ export type OnValueClickHandler = (option: Option, event: React.MouseEvent) => void;
+ export type IsOptionUniqueHandler = (arg: { option: Option, options: Options, labelKey: string, valueKey: string }) => boolean;
+ export type IsValidNewOptionHandler = (arg: { label: string }) => boolean;
+ export type NewOptionCreatorHandler = (arg: { label: string, labelKey: string, valueKey: string }) => Option;
+ export type PromptTextCreatorHandler = (filterText: string) => string;
+ export type ShouldKeyDownEventCreateNewOptionHandler = (arg: { keyCode: number }) => boolean;
+
+ export type OnChangeSingleHandler = OnChangeHandler>;
+ export type OnChangeMultipleHandler = OnChangeHandler>;
+ export type OnChangeHandler | Options> = (newValue: TOption | null) => void;
+ export type OnNewOptionClickHandler = (option: Option) => void;
+
+ export type LoadOptionsHandler = LoadOptionsAsyncHandler | LoadOptionsLegacyHandler;
+ export type LoadOptionsAsyncHandler = (input: string) => Promise>;
+ export type LoadOptionsLegacyHandler = (input: string, callback: (err: any, result: AutocompleteResult) => void) => void;
+
+ export interface AutocompleteResult {
+ /** The search-results to be displayed */
+ options: Options;
+ /**
+ * Should be set to true, if and only if a longer query with the same prefix
+ * would return a subset of the results
+ * If set to true, more specific queries will not be sent to the server.
+ */
+ complete: boolean;
+ }
+
+ export type Options = Array>;
+
+ export interface Option {
+ /** Text for rendering */
+ label?: string;
+ /** Value for searching */
+ value?: TValue;
+ /**
+ * Allow this option to be cleared
+ * @default true
+ */
+ clearableValue?: boolean;
+ /**
+ * Do not allow this option to be selected
+ * @default false
+ */
+ disabled?: boolean;
+ /**
+ * In the event that a custom menuRenderer is provided, Option should be able
+ * to accept arbitrary key-value pairs. See react-virtualized-select.
+ */
+ [property: string]: any;
+ }
+
+ export type OptionValues = string | number | boolean;
+
+ export interface MenuRendererProps {
+ /**
+ * The currently focused option; should be visible in the menu by default.
+ * default {}
+ */
+ focusedOption: Option;
+
+ /**
+ * Callback to focus a new option; receives the option as a parameter.
+ */
+ focusOption: FocusOptionHandler;
+
+ /**
+ * Option labels are accessible with this string key.
+ */
+ labelKey: string;
+
+ /**
+ * Ordered array of options to render.
+ */
+ options: Options;
+
+ /**
+ * Callback to select a new option; receives the option as a parameter.
+ */
+ selectValue: SelectValueHandler;
+
+ /**
+ * Array of currently selected options.
+ */
+ valueArray: Options;
+
+ /**
+ * Callback to remove selection from option; receives the option as a parameter.
+ */
+ removeValue: SelectValueHandler;
+
+ /**
+ * function which returns a custom way to render the options in the menu
+ */
+ optionRenderer: OptionRendererHandler;
+ }
+
+ export interface OptionComponentProps {
+ /**
+ * Classname(s) to apply to the option component.
+ */
+ className?: string;
+
+ /**
+ * Currently focused option.
+ */
+ focusOption?: Option;
+
+ inputValue?: string;
+ instancePrefix?: string;
+
+ /**
+ * True if this option is disabled.
+ */
+ isDisabled?: boolean;
+
+ /**
+ * True if this option is focused.
+ */
+ isFocused?: boolean;
+
+ /**
+ * True if this option is selected.
+ */
+ isSelected?: boolean;
+
+ /**
+ * Callback to be invoked when this option is focused.
+ */
+ onFocus?: (option: Option, event: any) => void;
+
+ /**
+ * Callback to be invoked when this option is selected.
+ */
+ onSelect?: (option: Option, event: any) => void;
+
+ /**
+ * Option to be rendered by this component.
+ */
+ option: Option;
+
+ /**
+ * Index of the option being rendered in the list
+ */
+ optionIndex?: number;
+
+ /**
+ * Callback to invoke when removing an option from a multi-selection. (Not necessarily the one
+ * being rendered)
+ */
+ removeValue?: (value: TValue | TValue[]) => void;
+
+ /**
+ * Callback to invoke to select an option. (Not necessarily the one being rendered)
+ */
+ selectValue?: (value: TValue | TValue[]) => void;
+ }
+
+ export interface ArrowRendererProps {
+ /**
+ * Arrow mouse down event handler.
+ */
+ onMouseDown: React.MouseEventHandler;
+
+ /**
+ * whether the Select is open or not.
+ */
+ isOpen: boolean;
+ }
+
+ export interface ValueComponentProps {
+ disabled: ReactSelectProps['disabled'];
+ id: string;
+ instancePrefix: string;
+ onClick: OnValueClickHandler | null;
+ onRemove?: SelectValueHandler;
+ placeholder: ReactSelectProps['placeholder'];
+ value: Option;
+ values?: Array>;
+ }
+
+ export interface ReactSelectProps extends React.Props> {
+ /**
+ * text to display when `allowCreate` is true.
+ * @default 'Add "{label}"?'
+ */
+ addLabelText?: string;
+ /**
+ * renders a custom drop-down arrow to be shown in the right-hand side of the select.
+ * @default undefined
+ */
+ arrowRenderer?: ArrowRendererHandler | null;
+ /**
+ * blurs the input element after a selection has been made. Handy for lowering the keyboard on mobile devices.
+ * @default false
+ */
+ autoBlur?: boolean;
+ /**
+ * autofocus the component on mount
+ * @deprecated. Use autoFocus instead
+ * @default false
+ */
+ autofocus?: boolean;
+ /**
+ * autofocus the component on mount
+ * @default false
+ */
+ autoFocus?: boolean;
+ /**
+ * If enabled, the input will expand as the length of its value increases
+ */
+ autosize?: boolean;
+ /**
+ * whether pressing backspace removes the last item when there is no input value
+ * @default true
+ */
+ backspaceRemoves?: boolean;
+ /**
+ * Message to use for screenreaders to press backspace to remove the current item
+ * {label} is replaced with the item label
+ * @default "Press backspace to remove..."
+ */
+ backspaceToRemoveMessage?: string;
+ /**
+ * CSS className for the outer element
+ */
+ className?: string;
+ /**
+ * Prefix prepended to element default className if no className is defined
+ */
+ classNamePrefix?: string;
+ /**
+ * title for the "clear" control when `multi` is true
+ * @default "Clear all"
+ */
+ clearAllText?: string;
+ /**
+ * Renders a custom clear to be shown in the right-hand side of the select when clearable true
+ * @default undefined
+ */
+ clearRenderer?: ClearRendererHandler;
+ /**
+ * title for the "clear" control
+ * @default "Clear value"
+ */
+ clearValueText?: string;
+ /**
+ * whether to close the menu when a value is selected
+ * @default true
+ */
+ closeOnSelect?: boolean;
+ /**
+ * whether it is possible to reset value. if enabled, an X button will appear at the right side.
+ * @default true
+ */
+ clearable?: boolean;
+ /**
+ * whether backspace removes an item if there is no text input
+ * @default true
+ */
+ deleteRemoves?: boolean;
+ /**
+ * delimiter to use to join multiple values
+ * @default ","
+ */
+ delimiter?: string;
+ /**
+ * whether the Select is disabled or not
+ * @default false
+ */
+ disabled?: boolean;
+ /**
+ * whether escape clears the value when the menu is closed
+ * @default true
+ */
+ escapeClearsValue?: boolean;
+ /**
+ * method to filter a single option
+ */
+ filterOption?: FilterOptionHandler;
+ /**
+ * method to filter the options array
+ */
+ filterOptions?: FilterOptionsHandler;
+ /**
+ * id for the underlying HTML input element
+ * @default undefined
+ */
+ id?: string;
+ /**
+ * whether to strip diacritics when filtering
+ * @default true
+ */
+ ignoreAccents?: boolean;
+ /**
+ * whether to perform case-insensitive filtering
+ * @default true
+ */
+ ignoreCase?: boolean;
+ /**
+ * custom attributes for the Input (in the Select-control) e.g: {'data-foo': 'bar'}
+ * @default {}
+ */
+ inputProps?: { [key: string]: any };
+ /**
+ * renders a custom input
+ */
+ inputRenderer?: InputRendererHandler;
+ /**
+ * allows for synchronization of component id's on server and client.
+ * @see https://github.com/JedWatson/react-select/pull/1105
+ */
+ instanceId?: string;
+ /**
+ * whether the Select is loading externally or not (such as options being loaded).
+ * if true, a loading spinner will be shown at the right side.
+ * @default false
+ */
+ isLoading?: boolean;
+ /**
+ * (legacy mode) joins multiple values into a single form field with the delimiter
+ * @default false
+ */
+ joinValues?: boolean;
+ /**
+ * the option property to use for the label
+ * @default "label"
+ */
+ labelKey?: string;
+ /**
+ * (any, start) match the start or entire string when filtering
+ * @default "any"
+ */
+ matchPos?: string;
+ /**
+ * (any, label, value) which option property to filter on
+ * @default "any"
+ */
+ matchProp?: string;
+ /**
+ * buffer of px between the base of the dropdown and the viewport to shift if menu doesnt fit in viewport
+ * @default 0
+ */
+ menuBuffer?: number;
+ /**
+ * optional style to apply to the menu container
+ */
+ menuContainerStyle?: React.CSSProperties;
+ /**
+ * renders a custom menu with options
+ */
+ menuRenderer?: MenuRendererHandler;
+ /**
+ * optional style to apply to the menu
+ */
+ menuStyle?: React.CSSProperties;
+ /**
+ * multi-value input
+ * @default false
+ */
+ multi?: boolean;
+ /**
+ * field name, for hidden ` ` tag
+ */
+ name?: string;
+ /**
+ * placeholder displayed when there are no matching search results or a falsy value to hide it
+ * @default "No results found"
+ */
+ noResultsText?: string | JSX.Element;
+ /**
+ * onBlur handler: function (event) {}
+ */
+ onBlur?: OnBlurHandler;
+ /**
+ * whether to clear input on blur or not
+ * @default true
+ */
+ onBlurResetsInput?: boolean;
+ /**
+ * whether the input value should be reset when options are selected.
+ * Also input value will be set to empty if 'onSelectResetsInput=true' and
+ * Select will get new value that not equal previous value.
+ * @default true
+ */
+ onSelectResetsInput?: boolean;
+ /**
+ * whether to clear input when closing the menu through the arrow
+ * @default true
+ */
+ onCloseResetsInput?: boolean;
+ /**
+ * onChange handler: function (newValue) {}
+ */
+ onChange?: OnChangeHandler;
+ /**
+ * fires when the menu is closed
+ */
+ onClose?: OnCloseHandler;
+ /**
+ * onFocus handler: function (event) {}
+ */
+ onFocus?: OnFocusHandler;
+ /**
+ * onInputChange handler: function (inputValue) {}
+ */
+ onInputChange?: OnInputChangeHandler;
+ /**
+ * onInputKeyDown handler: function (keyboardEvent) {}
+ */
+ onInputKeyDown?: OnInputKeyDownHandler;
+ /**
+ * fires when the menu is scrolled to the bottom; can be used to paginate options
+ */
+ onMenuScrollToBottom?: OnMenuScrollToBottomHandler;
+ /**
+ * fires when the menu is opened
+ */
+ onOpen?: OnOpenHandler;
+ /**
+ * boolean to enable opening dropdown when focused
+ * @default false
+ */
+ openOnClick?: boolean;
+ /**
+ * open the options menu when the input gets focus (requires searchable = true)
+ * @default true
+ */
+ openOnFocus?: boolean;
+ /**
+ * className to add to each option component
+ */
+ optionClassName?: string;
+ /**
+ * option component to render in dropdown
+ */
+ optionComponent?: OptionComponentType;
+ /**
+ * function which returns a custom way to render the options in the menu
+ */
+ optionRenderer?: OptionRendererHandler;
+ /**
+ * array of Select options
+ * @default false
+ */
+ options?: Options;
+ /**
+ * number of options to jump when using page up/down keys
+ * @default 5
+ */
+ pageSize?: number;
+ /**
+ * field placeholder, displayed when there's no value
+ * @default "Select..."
+ */
+ placeholder?: string | JSX.Element;
+ /**
+ * whether the selected option is removed from the dropdown on multi selects
+ * @default true
+ */
+ removeSelected?: boolean;
+ /**
+ * applies HTML5 required attribute when needed
+ * @default false
+ */
+ required?: boolean;
+ /**
+ * value to use when you clear the control
+ */
+ resetValue?: any;
+ /**
+ * use react-select in right-to-left direction
+ * @default false
+ */
+ rtl?: boolean;
+ /**
+ * whether the viewport will shift to display the entire menu when engaged
+ * @default true
+ */
+ scrollMenuIntoView?: boolean;
+ /**
+ * whether to enable searching feature or not
+ * @default true;
+ */
+ searchable?: boolean;
+ /**
+ * whether to select the currently focused value when the [tab] key is pressed
+ */
+ tabSelectsValue?: boolean;
+ /**
+ * initial field value
+ */
+ value?: Option | Options | string | string[] | number | number[] | boolean;
+ /**
+ * the option property to use for the value
+ * @default "value"
+ */
+ valueKey?: string;
+ /**
+ * function which returns a custom way to render the value selected
+ * @default false
+ */
+ valueRenderer?: ValueRendererHandler;
+ /**
+ * optional style to apply to the control
+ */
+ style?: React.CSSProperties;
+
+ /**
+ * optional tab index of the control
+ */
+ tabIndex?: string | number;
+
+ /**
+ * value component to render
+ */
+ valueComponent?: ValueComponentType;
+
+ /**
+ * optional style to apply to the component wrapper
+ */
+ wrapperStyle?: React.CSSProperties;
+
+ /**
+ * onClick handler for value labels: function (value, event) {}
+ */
+ onValueClick?: OnValueClickHandler;
+
+ /**
+ * pass the value to onChange as a simple value (legacy pre 1.0 mode), defaults to false
+ */
+ simpleValue?: boolean;
+ }
+
\ No newline at end of file
diff --git a/tests/baselines/reference/jsxNamespaceGlobalReexport.types b/tests/baselines/reference/jsxNamespaceGlobalReexport.types
index 85fc07e3497e3..19acd72ebfed1 100644
--- a/tests/baselines/reference/jsxNamespaceGlobalReexport.types
+++ b/tests/baselines/reference/jsxNamespaceGlobalReexport.types
@@ -90,13 +90,13 @@ import { JSXInternal } from '..';
>JSXInternal : any
export function jsx(
->jsx : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChild;}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChild | undefined; }, key?: string | undefined): VNode; }
+>jsx : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChild;}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChild; }, key?: string | undefined): VNode; }
type: string,
>type : string
props: JSXInternal.HTMLAttributes &
->props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild | undefined; }
+>props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild; }
>JSXInternal : any
JSXInternal.SVGAttributes &
@@ -110,13 +110,13 @@ export function jsx(
): VNode;
export function jsx(
->jsx : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild | undefined; }, key?: string | undefined): VNode; (type: ComponentType
, props: Attributes & P & { children?: ComponentChild;}, key?: string | undefined): VNode; }
+>jsx : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild; }, key?: string | undefined): VNode; (type: ComponentType
, props: Attributes & P & { children?: ComponentChild;}, key?: string | undefined): VNode; }
type: ComponentType,
>type : ComponentType
props: Attributes & P & { children?: ComponentChild },
->props : P & { children?: ComponentChild | undefined; }
+>props : P & { children?: ComponentChild; }
>children : ComponentChild | undefined
key?: string
@@ -125,13 +125,13 @@ export function jsx
(
): VNode;
export function jsxs(
->jsxs : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChild[];}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChild[] | undefined; }, key?: string | undefined): VNode; }
+>jsxs : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChild[];}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChild[]; }, key?: string | undefined): VNode; }
type: string,
>type : string
props: JSXInternal.HTMLAttributes &
->props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild[] | undefined; }
+>props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild[]; }
>JSXInternal : any
JSXInternal.SVGAttributes &
@@ -145,13 +145,13 @@ export function jsxs(
): VNode;
export function jsxs(
->jsxs : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild[] | undefined; }, key?: string | undefined): VNode; (type: ComponentType
, props: Attributes & P & { children?: ComponentChild[];}, key?: string | undefined): VNode; }
+>jsxs : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild[]; }, key?: string | undefined): VNode; (type: ComponentType
, props: Attributes & P & { children?: ComponentChild[];}, key?: string | undefined): VNode; }
type: ComponentType,
>type : ComponentType
props: Attributes & P & { children?: ComponentChild[] },
->props : P & { children?: ComponentChild[] | undefined; }
+>props : P & { children?: ComponentChild[]; }
>children : ComponentChild[] | undefined
key?: string
@@ -160,13 +160,13 @@ export function jsxs
(
): VNode;
export function jsxDEV(
->jsxDEV : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChildren;}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChildren | undefined; }, key?: string | undefined): VNode; }
+>jsxDEV : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChildren;}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChildren; }, key?: string | undefined): VNode; }
type: string,
>type : string
props: JSXInternal.HTMLAttributes &
->props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChildren | undefined; }
+>props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChildren; }
>JSXInternal : any
JSXInternal.SVGAttributes &
@@ -180,13 +180,13 @@ export function jsxDEV(
): VNode;
export function jsxDEV(
->jsxDEV : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChildren | undefined; }, key?: string | undefined): VNode; (type: ComponentType
, props: Attributes & P & { children?: ComponentChildren;}, key?: string | undefined): VNode; }
+>jsxDEV : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChildren; }, key?: string | undefined): VNode; (type: ComponentType
, props: Attributes & P & { children?: ComponentChildren;}, key?: string | undefined): VNode; }
type: ComponentType,
>type : ComponentType
props: Attributes & P & { children?: ComponentChildren },
->props : P & { children?: ComponentChildren | undefined; }
+>props : P & { children?: ComponentChildren; }
>children : ComponentChildren | undefined
key?: string
diff --git a/tests/baselines/reference/jsxNamespaceGlobalReexportMissingAliasTarget.types b/tests/baselines/reference/jsxNamespaceGlobalReexportMissingAliasTarget.types
index 7cc6f7937322c..0262ca9dfafd1 100644
--- a/tests/baselines/reference/jsxNamespaceGlobalReexportMissingAliasTarget.types
+++ b/tests/baselines/reference/jsxNamespaceGlobalReexportMissingAliasTarget.types
@@ -90,13 +90,13 @@ import { JSXInternal } from '..';
>JSXInternal : any
export function jsx(
->jsx : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChild;}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChild | undefined; }, key?: string | undefined): VNode; }
+>jsx : { (type: string, props: JSXInternal.HTMLAttributes & JSXInternal.SVGAttributes & Record & { children?: ComponentChild;}, key?: string | undefined): VNode; (type: ComponentType
, props: P & { children?: ComponentChild; }, key?: string | undefined): VNode; }
type: string,
>type : string
props: JSXInternal.HTMLAttributes &
->props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild | undefined; }
+>props : JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild; }
>JSXInternal : any
JSXInternal.SVGAttributes &
@@ -110,13 +110,13 @@ export function jsx(
): VNode;
export function jsx(
->jsx : { (type: string, props: JSXInternal.HTMLAttributes<{}> & JSXInternal.SVGAttributes<{}> & Record & { children?: ComponentChild | undefined; }, key?: string | undefined): VNode