diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 1a817ee006ae2..5ea86514962d3 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -285,7 +285,7 @@ namespace ts { return bindSourceFile; function bindInStrictMode(file: SourceFile, opts: CompilerOptions): boolean { - if (getStrictOptionValue(opts, "alwaysStrict") && !file.isDeclarationFile) { + if (getStrictOptionValue(file, opts, "alwaysStrict") && !file.isDeclarationFile) { // bind in strict mode source files with alwaysStrict option return true; } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ebe2d1c84b566..ae8e6d66367d8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -359,16 +359,16 @@ namespace ts { const moduleKind = getEmitModuleKind(compilerOptions); const useDefineForClassFields = getUseDefineForClassFields(compilerOptions); const allowSyntheticDefaultImports = getAllowSyntheticDefaultImports(compilerOptions); - const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); - const strictFunctionTypes = getStrictOptionValue(compilerOptions, "strictFunctionTypes"); - const strictBindCallApply = getStrictOptionValue(compilerOptions, "strictBindCallApply"); - const strictPropertyInitialization = getStrictOptionValue(compilerOptions, "strictPropertyInitialization"); - const noImplicitAny = getStrictOptionValue(compilerOptions, "noImplicitAny"); - const noImplicitThis = getStrictOptionValue(compilerOptions, "noImplicitThis"); - const useUnknownInCatchVariables = getStrictOptionValue(compilerOptions, "useUnknownInCatchVariables"); + const strictNullChecks = (context: Node | undefined) => getStrictOptionValue(context && getSourceFileOfNode(context), compilerOptions, "strictNullChecks"); + const strictFunctionTypes = (file: SourceFile | undefined) => getStrictOptionValue(file, compilerOptions, "strictFunctionTypes"); + const strictBindCallApply = (file: SourceFile | undefined) => getStrictOptionValue(file, compilerOptions, "strictBindCallApply"); + const strictPropertyInitialization = (file: SourceFile) => getStrictOptionValue(file, compilerOptions, "strictPropertyInitialization"); + const noImplicitAny = (context: Node | undefined) => getStrictOptionValue(context && getSourceFileOfNode(context), compilerOptions, "noImplicitAny"); + const noImplicitThis = (file: SourceFile) => getStrictOptionValue(file, compilerOptions, "noImplicitThis"); + const useUnknownInCatchVariables = (file: SourceFile) => getStrictOptionValue(file, compilerOptions, "useUnknownInCatchVariables"); const keyofStringsOnly = !!compilerOptions.keyofStringsOnly; const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : ObjectFlags.FreshLiteral; - const exactOptionalPropertyTypes = compilerOptions.exactOptionalPropertyTypes; + const exactOptionalPropertyTypes = (context: Node | undefined) => getFileLocalCompilerOption(context && getSourceFileOfNode(context), compilerOptions, "exactOptionalPropertyTypes"); const checkBinaryExpression = createCheckBinaryExpression(); const emitResolver = createResolver(); @@ -633,8 +633,8 @@ namespace ts { getFalseType: (fresh?) => fresh ? falseType : regularFalseType, getTrueType: (fresh?) => fresh ? trueType : regularTrueType, getVoidType: () => voidType, - getUndefinedType: () => undefinedType, - getNullType: () => nullType, + getUndefinedType: (widening?: boolean) => widening ? undefinedWideningType : undefinedType, + getNullType: (widening?: boolean) => widening ? nullWideningType : nullType, getESSymbolType: () => esSymbolType, getNeverType: () => neverType, getOptionalType: () => optionalType, @@ -699,7 +699,7 @@ namespace ts { diagnostics = addRange(diagnostics, suggestionDiagnostics.getDiagnostics(file.fileName)); checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (containingNode, kind, diag) => { - if (!containsParseError(containingNode) && !unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) { + if (!containsParseError(containingNode) && !unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient), file)) { (diagnostics || (diagnostics = [])).push({ ...diag, category: DiagnosticCategory.Suggestion }); } }); @@ -794,11 +794,16 @@ namespace ts { const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); const nonNullUnknownType = createIntrinsicType(TypeFlags.Unknown, "unknown"); const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined"); - const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType); + const undefinedPermissiveType = createIntrinsicType(TypeFlags.Undefined, "undefined"); + const undefinedWideningType = createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType); + const getUndefinedWideningType = (context: Node | undefined) => strictNullChecks(context) ? undefinedType : undefinedWideningType; const optionalType = createIntrinsicType(TypeFlags.Undefined, "undefined"); - const missingType = exactOptionalPropertyTypes ? createIntrinsicType(TypeFlags.Undefined, "undefined") : undefinedType; + const missingType = createIntrinsicType(TypeFlags.Undefined, "undefined"); + const getMissingOrUndefinedType = (context: Node | undefined) => exactOptionalPropertyTypes(context) ? missingType : undefinedType; const nullType = createIntrinsicType(TypeFlags.Null, "null"); - const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType); + const nullWideningType = createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType); + const nullPermissiveType = createIntrinsicType(TypeFlags.Null, "null"); + const getNullWideningType = (context: Node | undefined) => strictNullChecks(context) ? nullType : nullWideningType; const stringType = createIntrinsicType(TypeFlags.String, "string"); const numberType = createIntrinsicType(TypeFlags.Number, "number"); const bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint"); @@ -856,7 +861,7 @@ namespace ts { emptyTypeLiteralSymbol.members = createSymbolTable(); const emptyTypeLiteralType = createAnonymousType(emptyTypeLiteralSymbol, emptySymbols, emptyArray, emptyArray, emptyArray); - const unknownUnionType = strictNullChecks ? getUnionType([undefinedType, nullType, createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray)]) : unknownType; + const unknownUnionType = getUnionType([undefinedType, nullType, createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray)]); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, emptyArray) as ObjectType as GenericType; emptyGenericType.instantiations = new Map(); @@ -953,8 +958,8 @@ namespace ts { let globalObjectType: ObjectType; let globalFunctionType: ObjectType; - let globalCallableFunctionType: ObjectType; - let globalNewableFunctionType: ObjectType; + let globalCallableFunctionType: (file: SourceFile | undefined) => ObjectType; + let globalNewableFunctionType: (file: SourceFile | undefined) => ObjectType; let globalArrayType: GenericType; let globalReadonlyArrayType: GenericType; let globalStringType: ObjectType; @@ -1074,6 +1079,17 @@ namespace ts { return checker; + function getSourceFileOfNode(node: Node): SourceFile; + function getSourceFileOfNode(node: Node | undefined): SourceFile | undefined; + function getSourceFileOfNode(node: Node | undefined) { + if (!node) return node; + const links = getNodeLinks(node); + if (!hasProperty(links, "sourceFile")) { + links.sourceFile = ts.getSourceFileOfNode(node); + } + return links.sourceFile; + } + function getCachedType(key: string | undefined) { return key ? cachedTypes.get(key) : undefined; } @@ -3563,7 +3579,7 @@ namespace ts { (isLiteralImportTypeNode(location) ? location : undefined)?.argument.literal; const mode = contextSpecifier && isStringLiteralLike(contextSpecifier) ? getModeForUsageLocation(currentSourceFile, contextSpecifier) : currentSourceFile.impliedNodeFormat; const resolvedModule = getResolvedModule(currentSourceFile, moduleReference, mode); - const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(compilerOptions, resolvedModule); + const resolutionDiagnostic = resolvedModule && getResolutionDiagnostic(currentSourceFile, compilerOptions, resolvedModule); const sourceFile = resolvedModule && (!resolutionDiagnostic || resolutionDiagnostic === Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set) && host.getSourceFile(resolvedModule.resolvedFileName); @@ -3618,7 +3634,7 @@ namespace ts { error(errorNode, diag, moduleReference, resolvedModule!.resolvedFileName); } else { - errorOnImplicitAnyModule(/*isError*/ noImplicitAny && !!moduleNotFoundError, errorNode, resolvedModule!, moduleReference); + errorOnImplicitAnyModule(/*isError*/ noImplicitAny(errorNode) && !!moduleNotFoundError, errorNode, resolvedModule!, moduleReference); } // Failed imports and untyped modules are both treated in an untyped manner; only difference is whether we give a diagnostic first. return undefined; @@ -5983,7 +5999,7 @@ namespace ts { let parameterType = getTypeOfSymbol(parameterSymbol); if (parameterDeclaration && isRequiredInitializedParameter(parameterDeclaration)) { - parameterType = getOptionalType(parameterType); + parameterType = getOptionalType(parameterType, context.enclosingDeclaration); } const parameterTypeNode = serializeTypeForDeclaration(context, parameterType, parameterSymbol, context.enclosingDeclaration, privateSymbolVisitor, bundledImports); @@ -6646,7 +6662,7 @@ namespace ts { return true; } if (isParameter(annotatedDeclaration) && annotatedDeclaration.questionToken) { - return getTypeWithFacts(type, TypeFacts.NEUndefined) === typeFromTypeNode; + return getTypeWithFacts(type, TypeFacts.NEUndefined, typeNode) === typeFromTypeNode; } return false; } @@ -8779,9 +8795,9 @@ namespace ts { return !!(type.flags & TypeFlags.Instantiable) && maybeTypeOfKind(getBaseConstraintOfType(type) || unknownType, TypeFlags.Undefined); } - function getNonUndefinedType(type: Type) { + function getNonUndefinedType(type: Type, context: Node) { const typeOrConstraint = someType(type, isGenericTypeWithUndefinedConstraint) ? mapType(type, t => t.flags & TypeFlags.Instantiable ? getBaseConstraintOrType(t) : t) : type; - return getTypeWithFacts(typeOrConstraint, TypeFacts.NEUndefined); + return getTypeWithFacts(typeOrConstraint, TypeFacts.NEUndefined, context); } // Determine the control flow type associated with a destructuring declaration or assignment. The following @@ -8862,19 +8878,19 @@ namespace ts { } const pattern = declaration.parent; // Relax null check on ambient destructuring parameters, since the parameters have no implementation and are just documentation - if (strictNullChecks && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) { - parentType = getNonNullableType(parentType); + if (strictNullChecks(declaration) && declaration.flags & NodeFlags.Ambient && isParameterDeclaration(declaration)) { + parentType = getNonNullableType(parentType, declaration); } // Filter `undefined` from the type we check against if the parent has an initializer and that initializer is not possibly `undefined` - else if (strictNullChecks && pattern.parent.initializer && !(getTypeFacts(getTypeOfInitializer(pattern.parent.initializer)) & TypeFacts.EQUndefined)) { - parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined); + else if (strictNullChecks(declaration) && pattern.parent.initializer && !(getTypeFacts(getTypeOfInitializer(pattern.parent.initializer), declaration) & TypeFacts.EQUndefined)) { + parentType = getTypeWithFacts(parentType, TypeFacts.NEUndefined, declaration); } let type: Type | undefined; if (pattern.kind === SyntaxKind.ObjectBindingPattern) { if (declaration.dotDotDotToken) { parentType = getReducedType(parentType); - if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType)) { + if (parentType.flags & TypeFlags.Unknown || !isValidSpreadType(parentType, declaration)) { error(declaration, Diagnostics.Rest_types_may_only_be_created_from_object_types); return errorType; } @@ -8924,9 +8940,9 @@ namespace ts { if (getEffectiveTypeAnnotationNode(walkUpBindingElementsAndPatterns(declaration))) { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. - return strictNullChecks && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal)) & TypeFacts.IsUndefined) ? getNonUndefinedType(type) : type; + return strictNullChecks(declaration) && !(getTypeFacts(checkDeclarationInitializer(declaration, CheckMode.Normal), declaration) & TypeFacts.IsUndefined) ? getNonUndefinedType(type, declaration) : type; } - return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype)); + return widenTypeInferredFromInitializer(declaration, getUnionType([getNonUndefinedType(type, declaration), checkDeclarationInitializer(declaration, CheckMode.Normal)], UnionReduction.Subtype)); } function getTypeForDeclarationFromJSDocComment(declaration: Node) { @@ -8947,8 +8963,8 @@ namespace ts { return expr.kind === SyntaxKind.ArrayLiteralExpression && (expr as ArrayLiteralExpression).elements.length === 0; } - function addOptionality(type: Type, isProperty = false, isOptional = true): Type { - return strictNullChecks && isOptional ? getOptionalType(type, isProperty) : type; + function addOptionality(type: Type, context: Node | undefined, isProperty = false, isOptional = true): Type { + return strictNullChecks(context) && isOptional ? getOptionalType(type, context, isProperty) : type; } // Return the inferred type for a variable, parameter, or property declaration @@ -8960,7 +8976,7 @@ namespace ts { // A variable declared in a for..in statement is of type string, or of type keyof T when the // right hand expression is of a type parameter type. if (isVariableDeclaration(declaration) && declaration.parent.parent.kind === SyntaxKind.ForInStatement) { - const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode))); + const indexType = getIndexType(getNonNullableTypeIfNeeded(checkExpression(declaration.parent.parent.expression, /*checkMode*/ checkMode), declaration)); return indexType.flags & (TypeFlags.TypeParameter | TypeFlags.Index) ? getExtractStringType(indexType) : stringType; } @@ -8986,10 +9002,10 @@ namespace ts { // Use type from type annotation if one is present const declaredType = tryGetTypeFromEffectiveTypeNode(declaration); if (declaredType) { - return addOptionality(declaredType, isProperty, isOptional); + return addOptionality(declaredType, declaration, isProperty, isOptional); } - if ((noImplicitAny || isInJSFile(declaration)) && + if ((noImplicitAny(declaration) || isInJSFile(declaration)) && isVariableDeclaration(declaration) && !isBindingPattern(declaration.name) && !(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !(declaration.flags & NodeFlags.Ambient)) { // If --noImplicitAny is on or the declaration is in a Javascript file, @@ -9028,7 +9044,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, /*isProperty*/ false, isOptional); + return addOptionality(type, declaration, /*isProperty*/ undefined, isOptional); } } @@ -9042,10 +9058,10 @@ namespace ts { } } const type = widenTypeInferredFromInitializer(declaration, checkDeclarationInitializer(declaration, checkMode)); - return addOptionality(type, isProperty, isOptional); + return addOptionality(type, declaration, isProperty, isOptional); } - if (isPropertyDeclaration(declaration) && (noImplicitAny || isInJSFile(declaration))) { + if (isPropertyDeclaration(declaration) && (noImplicitAny(declaration) || isInJSFile(declaration))) { // We have a property declaration with no type annotation or initializer, in noImplicitAny mode or a .js file. // Use control flow analysis of this.xxx assignments in the constructor or static block to determine the type of the property. if (!hasStaticModifier(declaration)) { @@ -9053,14 +9069,14 @@ namespace ts { const type = constructor ? getFlowTypeInConstructor(declaration.symbol, constructor) : getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : undefined; - return type && addOptionality(type, /*isProperty*/ true, isOptional); + return type && addOptionality(type, declaration, /*isProperty*/ true, isOptional); } else { const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration); const type = staticBlocks.length ? getFlowTypeInStaticBlocks(declaration.symbol, staticBlocks) : getEffectiveModifierFlags(declaration) & ModifierFlags.Ambient ? getTypeOfPropertyInBaseClass(declaration.symbol) : undefined; - return type && addOptionality(type, /*isProperty*/ true, isOptional); + return type && addOptionality(type, declaration, /*isProperty*/ true, isOptional); } } @@ -9104,7 +9120,7 @@ namespace ts { // noImplicitAny mode or a .js file. const declaration = symbol.valueDeclaration; return declaration && isPropertyDeclaration(declaration) && !getEffectiveTypeAnnotationNode(declaration) && - !declaration.initializer && (noImplicitAny || isInJSFile(declaration)); + !declaration.initializer && (noImplicitAny(declaration) || isInJSFile(declaration)); } function getDeclaringConstructor(symbol: Symbol) { @@ -9146,11 +9162,11 @@ namespace ts { setParent(reference, staticBlock); reference.flowNode = staticBlock.returnFlowNode; const flowType = getFlowTypeOfProperty(reference, symbol); - if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) { + if (noImplicitAny(reference) && (flowType === autoType || flowType === autoArrayType)) { error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } // We don't infer a type if assignments are only null or undefined. - if (everyType(flowType, isNullableType)) { + if (everyType(flowType, t => isNullableType(t, reference))) { continue; } return convertAutoToAny(flowType); @@ -9166,11 +9182,11 @@ namespace ts { setParent(reference, constructor); reference.flowNode = constructor.returnFlowNode; const flowType = getFlowTypeOfProperty(reference, symbol); - if (noImplicitAny && (flowType === autoType || flowType === autoArrayType)) { + if (noImplicitAny(reference) && (flowType === autoType || flowType === autoArrayType)) { error(symbol.valueDeclaration, Diagnostics.Member_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } // We don't infer a type if assignments are only null or undefined. - return everyType(flowType, isNullableType) ? undefined : convertAutoToAny(flowType); + return everyType(flowType, t => isNullableType(t, reference)) ? undefined : convertAutoToAny(flowType); } function getFlowTypeOfProperty(reference: Node, prop: Symbol | undefined) { @@ -9249,7 +9265,7 @@ namespace ts { type = getUnionType(sourceTypes!); } } - const widened = getWidenedType(addOptionality(type, /*isProperty*/ false, definedInMethod && !definedInConstructor)); + const widened = getWidenedType(addOptionality(type, container, /*isProperty*/ false, definedInMethod && !definedInConstructor)); if (symbol.valueDeclaration && filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) { reportImplicitAny(symbol.valueDeclaration, anyType); return anyType; @@ -9448,7 +9464,7 @@ namespace ts { // contextual type or, if the element itself is a binding pattern, with the type implied by that binding // pattern. const contextualType = isBindingPattern(element.name) ? getTypeFromBindingPattern(element.name, /*includePatternInType*/ true, /*reportErrors*/ false) : unknownType; - return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType))); + return addOptionality(widenTypeInferredFromInitializer(element, checkDeclarationInitializer(element, CheckMode.Normal, contextualType)), element, /*isProperty*/ true); } if (isBindingPattern(element.name)) { return getTypeFromBindingPattern(element.name, includePatternInType, reportErrors); @@ -9634,7 +9650,7 @@ namespace ts { if (isCatchClauseVariableDeclarationOrBindingElement(declaration)) { const typeNode = getEffectiveTypeAnnotationNode(declaration); if (typeNode === undefined) { - return useUnknownInCatchVariables ? unknownType : anyType; + return useUnknownInCatchVariables(getSourceFileOfNode(declaration)) ? unknownType : anyType; } const type = getTypeOfNode(typeNode); // an errorType will make `checkTryStatement` issue an error @@ -9775,10 +9791,10 @@ namespace ts { getter && getter.body && getReturnTypeFromBody(getter); if (!type) { if (setter && !isPrivateWithinAmbient(setter)) { - errorOrSuggestion(noImplicitAny, setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); + errorOrSuggestion(noImplicitAny(setter), setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation, symbolToString(symbol)); } else if (getter && !isPrivateWithinAmbient(getter)) { - errorOrSuggestion(noImplicitAny, getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol)); + errorOrSuggestion(noImplicitAny(getter), getter, Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation, symbolToString(symbol)); } type = anyType; } @@ -9789,7 +9805,7 @@ namespace ts { else if (getAnnotatedAccessorTypeNode(setter)) { error(setter, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_type_annotation, symbolToString(symbol)); } - else if (getter && noImplicitAny) { + else if (getter && noImplicitAny(getter)) { error(getter, Diagnostics._0_implicitly_has_return_type_any_because_it_does_not_have_a_return_type_annotation_and_is_referenced_directly_or_indirectly_in_one_of_its_return_expressions, symbolToString(symbol)); } type = anyType; @@ -9873,7 +9889,7 @@ namespace ts { return baseTypeVariable ? getIntersectionType([type, baseTypeVariable]) : type; } else { - return strictNullChecks && symbol.flags & SymbolFlags.Optional ? getOptionalType(type) : type; + return strictNullChecks(declaration) && symbol.flags & SymbolFlags.Optional ? getOptionalType(type, declaration) : type; } } @@ -9921,7 +9937,7 @@ namespace ts { return errorType; } // Check if variable has initializer that circularly references the variable itself - if (noImplicitAny && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) { + if (noImplicitAny(declaration) && (declaration.kind !== SyntaxKind.Parameter || (declaration as HasInitializer).initializer)) { error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_it_does_not_have_a_type_annotation_and_is_referenced_directly_or_indirectly_in_its_own_initializer, symbolToString(symbol)); } @@ -11753,7 +11769,7 @@ namespace ts { !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || !(templateModifiers & MappedTypeModifiers.ExcludeReadonly) && modifiersProp && isReadonlySymbol(modifiersProp)); - const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional; + const stripOptional = strictNullChecks(type.declaration) && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional; const lateFlag: CheckFlags = modifiersProp ? getIsLateCheckFlag(modifiersProp) : 0; const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, lateFlag | CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)) as MappedSymbol; @@ -11793,8 +11809,8 @@ 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, /*isProperty*/ true) : - symbol.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType) : + let type = strictNullChecks(mappedType.declaration) && symbol.flags & SymbolFlags.Optional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, mappedType.declaration, /*isProperty*/ true) : + symbol.checkFlags & CheckFlags.StripOptional ? removeMissingOrUndefinedType(propType, mappedType.declaration) : propType; if (!popTypeResolution()) { error(currentNode, Diagnostics.Type_of_property_0_circularly_references_itself_in_mapped_type_1, symbolToString(symbol), typeToString(mappedType)); @@ -11824,7 +11840,7 @@ namespace ts { function getTemplateTypeFromMappedType(type: MappedType) { return type.templateType || (type.templateType = type.declaration.type ? - instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), /*isProperty*/ true, !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) : + instantiateType(addOptionality(getTypeFromTypeNode(type.declaration.type), type.declaration, /*isProperty*/ true, !!(getMappedTypeModifiers(type) & MappedTypeModifiers.IncludeOptional)), type.mapper) : errorType); } @@ -12011,6 +12027,10 @@ namespace ts { getBaseConstraintOfType(type); } + function getUnknownConstraintForType(type: Type): Type { + return !strictNullChecks(type.symbol?.declarations?.[0] || type.aliasSymbol?.declarations?.[0]) ? nonNullUnknownType : unknownType; + } + function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type | undefined { return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined; } @@ -12344,7 +12364,7 @@ namespace ts { * type itself. */ function getApparentType(type: Type): Type { - const t = !(type.flags & TypeFlags.Instantiable) ? type : getBaseConstraintOfType(type) || unknownType; + const t = !(type.flags & TypeFlags.Instantiable) ? type : getBaseConstraintOfType(type) || getUnknownConstraintForType(type); return getObjectFlags(t) & ObjectFlags.Mapped ? getApparentTypeOfMappedType(t as MappedType) : t.flags & TypeFlags.Intersection ? getApparentTypeOfIntersectionType(t as IntersectionType) : t.flags & TypeFlags.StringLike ? globalStringType : @@ -12354,7 +12374,7 @@ namespace ts { t.flags & TypeFlags.ESSymbolLike ? getGlobalESSymbolType() : t.flags & TypeFlags.NonPrimitive ? emptyObjectType : t.flags & TypeFlags.Index ? keyofConstraintType : - t.flags & TypeFlags.Unknown && !strictNullChecks ? emptyObjectType : + t === nonNullUnknownType ? emptyObjectType : t; } @@ -12431,11 +12451,11 @@ namespace ts { const indexInfo = !isLateBoundName(name) && getApplicableIndexInfoForName(type, name); if (indexInfo) { checkFlags |= CheckFlags.WritePartial | (indexInfo.isReadonly ? CheckFlags.Readonly : 0); - indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || undefinedType : indexInfo.type); + indexTypes = append(indexTypes, isTupleType(type) ? getRestTypeOfTupleType(type) || (strictNullChecks(indexInfo.declaration) ? undefinedType : neverType) : indexInfo.type); } else if (isObjectLiteralType(type) && !(getObjectFlags(type) & ObjectFlags.ContainsSpread)) { checkFlags |= CheckFlags.WritePartial; - indexTypes = append(indexTypes, undefinedType); + indexTypes = append(indexTypes, strictNullChecks(type.symbol.valueDeclaration) ? undefinedType : neverType); } else { checkFlags |= CheckFlags.ReadPartial; @@ -12637,9 +12657,10 @@ namespace ts { return symbol; } if (skipObjectFunctionPropertyAugment) return undefined; + const file = symbol?.valueDeclaration && getSourceFileOfNode(symbol.valueDeclaration); const functionType = resolved === anyFunctionType ? globalFunctionType : - resolved.callSignatures.length ? globalCallableFunctionType : - resolved.constructSignatures.length ? globalNewableFunctionType : + resolved.callSignatures.length ? globalCallableFunctionType(file) : + resolved.constructSignatures.length ? globalNewableFunctionType(file) : undefined; if (functionType) { const symbol = getPropertyOfObjectType(functionType, name); @@ -13141,10 +13162,10 @@ namespace ts { getReturnTypeFromAnnotation(signature.declaration!) || (nodeIsMissing((signature.declaration as FunctionLikeDeclaration).body) ? anyType : getReturnTypeFromBody(signature.declaration as FunctionLikeDeclaration)); if (signature.flags & SignatureFlags.IsInnerCallChain) { - type = addOptionalTypeMarker(type); + type = addOptionalTypeMarker(type, signature.declaration); } else if (signature.flags & SignatureFlags.IsOuterCallChain) { - type = getOptionalType(type); + type = strictNullChecks(signature.declaration) ? getOptionalType(type, signature.declaration) : type; } if (!popTypeResolution()) { if (signature.declaration) { @@ -13152,7 +13173,7 @@ namespace ts { if (typeNode) { error(typeNode, Diagnostics.Return_type_annotation_circularly_references_itself); } - else if (noImplicitAny) { + else if (noImplicitAny(signature.declaration)) { const declaration = signature.declaration as Declaration; const name = getNameOfDeclaration(declaration); if (name) { @@ -13588,7 +13609,7 @@ namespace ts { const numTypeArguments = length(node.typeArguments); const minTypeArgumentCount = getMinTypeArgumentCount(typeParameters); const isJs = isInJSFile(node); - const isJsImplicitAny = !noImplicitAny && isJs; + const isJsImplicitAny = !noImplicitAny(node) && isJs; if (!isJsImplicitAny && (numTypeArguments < minTypeArgumentCount || numTypeArguments > typeParameters.length)) { const missingAugmentsTag = isJs && isExpressionWithTypeArguments(node) && !isJSDocAugmentsTag(node.parent); const diag = minTypeArgumentCount === typeParameters.length ? @@ -13889,9 +13910,9 @@ namespace ts { checkNoTypeArguments(node); return globalFunctionType; case "array": - return (!typeArgs || !typeArgs.length) && !noImplicitAny ? anyArrayType : undefined; + return (!typeArgs || !typeArgs.length) && !noImplicitAny(node) ? anyArrayType : undefined; case "promise": - return (!typeArgs || !typeArgs.length) && !noImplicitAny ? createPromiseType(anyType) : undefined; + return (!typeArgs || !typeArgs.length) && !noImplicitAny(node) ? createPromiseType(anyType) : undefined; case "Object": if (typeArgs && typeArgs.length === 2) { if (isJSDocIndexSignature(node)) { @@ -13903,14 +13924,14 @@ namespace ts { return anyType; } checkNoTypeArguments(node); - return !noImplicitAny ? anyType : undefined; + return !noImplicitAny(node) ? anyType : undefined; } } } function getTypeFromJSDocNullableTypeNode(node: JSDocNullableType) { const type = getTypeFromTypeNode(node.type); - return strictNullChecks ? getNullableType(type, TypeFlags.Null) : type; + return strictNullChecks(node) ? getNullableType(type, TypeFlags.Null) : type; } function getTypeFromTypeReference(node: TypeReferenceType): Type { @@ -14509,7 +14530,7 @@ namespace ts { } function getTypeFromOptionalTypeNode(node: OptionalTypeNode): Type { - return addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true); + return addOptionality(getTypeFromTypeNode(node.type), node, /*isProperty*/ true); } function getTypeId(type: Type): TypeId { @@ -14529,37 +14550,64 @@ namespace ts { return false; } - function addTypeToUnion(typeSet: Type[], includes: TypeFlags, type: Type) { - const flags = type.flags; - if (flags & TypeFlags.Union) { - return addTypesToUnion(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types); - } - // We ignore 'never' types in unions - if (!(flags & TypeFlags.Never)) { - includes |= flags & TypeFlags.IncludesMask; - if (flags & TypeFlags.Instantiable) includes |= TypeFlags.IncludesInstantiable; - if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; - if (!strictNullChecks && flags & TypeFlags.Nullable) { - if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType; - } - else { - const len = typeSet.length; - const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues); - if (index < 0) { - typeSet.splice(~index, 0, type); - } - } + function addTypeToListSorted(typeSet: Type[], type: Type) { + const len = typeSet.length; + const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues); + if (index < 0) { + typeSet.splice(~index, 0, type); } - return includes; } // Add the given types to the given type set. Order is preserved, duplicates are removed, // and nested types of the given kind are flattened into the set. function addTypesToUnion(typeSet: Type[], includes: TypeFlags, types: readonly Type[]): TypeFlags { - for (const type of types) { - includes = addTypeToUnion(typeSet, includes, type); + let undefinedVariant: Type | undefined; + includes = addTypesToUnionWorker(typeSet, includes, types); + if (includes & TypeFlags.Null) { + if (includes & TypeFlags.IncludesNonWideningType) { + addTypeToListSorted(typeSet, includes & TypeFlags.IncludesNonWideningType ? nullType : nullWideningType); + } + } + if (includes & TypeFlags.Undefined) { + if (includes & TypeFlags.IncludesNonWideningType) { + addTypeToListSorted(typeSet, includes & TypeFlags.IncludesNonWideningType ? undefinedVariant || undefinedType : undefinedWideningType); + } } return includes; + + + function addTypeToUnion(typeSet: Type[], includes: TypeFlags, type: Type) { + const flags = type.flags; + if (flags & TypeFlags.Union) { + return addTypesToUnionWorker(typeSet, includes | (isNamedUnionType(type) ? TypeFlags.Union : 0), (type as UnionType).types); + } + // We ignore 'never' types in unions + if (!(flags & TypeFlags.Never)) { + includes |= flags & TypeFlags.IncludesMask; + if (flags & TypeFlags.Instantiable) includes |= TypeFlags.IncludesInstantiable; + if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; + if (flags & TypeFlags.Nullable) { + if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) { + includes |= TypeFlags.IncludesNonWideningType; + if (flags & TypeFlags.Undefined) { + if (!undefinedVariant) undefinedVariant = type; + else undefinedVariant = undefinedType; // multiple of the missing, optional, or base undefined types combine to just normal undefined + } + } + } + else { + addTypeToListSorted(typeSet, type); + } + } + return includes; + } + + function addTypesToUnionWorker(typeSet: Type[], includes: TypeFlags, types: readonly Type[]): TypeFlags { + for (const type of types) { + includes = addTypeToUnion(typeSet, includes, type); + } + return includes; + } } function removeSubtypes(types: Type[], hasObjectTypes: boolean): Type[] | undefined { @@ -14707,7 +14755,7 @@ namespace ts { includes & TypeFlags.IncludesWildcard ? wildcardType : anyType : includes & TypeFlags.Null || containsType(typeSet, unknownType) ? unknownType : nonNullUnknownType; } - if (exactOptionalPropertyTypes && includes & TypeFlags.Undefined) { + if (includes & TypeFlags.Undefined) { const missingIndex = binarySearch(typeSet, missingType, getTypeId, compareValues); if (missingIndex >= 0 && containsType(typeSet, undefinedType)) { orderedRemoveItemAt(typeSet, missingIndex); @@ -14829,12 +14877,25 @@ namespace ts { const links = getNodeLinks(node); if (!links.resolvedType) { const aliasSymbol = getAliasSymbolForTypeNode(node); - links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), UnionReduction.Literal, + links.resolvedType = getUnionType(map(node.types, getTypeFromUnionMemberTypeNode), UnionReduction.Literal, aliasSymbol, getTypeArgumentsForAliasSymbol(aliasSymbol)); } return links.resolvedType; } + /** + * This is a syntactic approximation of the longstanding non-strictNullChecks behavior of unions with null/undefined + * eliminating the null/undefined upon construction. By doing it at type construction site, we can get per-file behavior. + * The downside is that a helper like `type Union = T | U` isn't affected by this, and so will preserve null/undefined + * arguments where it wouldn't have before. + */ + function getTypeFromUnionMemberTypeNode(node: TypeNode) { + if (strictNullChecks(node) || !((isLiteralTypeNode(node) && isNullOrUndefined(node.literal)) || isNullOrUndefined(node as Node as Expression) || node.kind === SyntaxKind.UndefinedKeyword)) { + return getTypeFromTypeNode(node); + } + return neverType; + } + function addTypeToIntersection(typeSet: ESMap, includes: TypeFlags, type: Type) { const flags = type.flags; if (flags & TypeFlags.Intersection) { @@ -14850,8 +14911,8 @@ namespace ts { if (flags & TypeFlags.AnyOrUnknown) { if (type === wildcardType) includes |= TypeFlags.IncludesWildcard; } - else if (strictNullChecks || !(flags & TypeFlags.Nullable)) { - if (exactOptionalPropertyTypes && type === missingType) { + else { + if (type === missingType) { includes |= TypeFlags.IncludesMissingType; type = undefinedType; } @@ -15025,17 +15086,19 @@ namespace ts { // a number-like type and a type known to be non-number-like, or // a symbol-like type and a type known to be non-symbol-like, or // a void-like type and a type known to be non-void-like, or - // a non-primitive type and a type known to be primitive. + // a non-primitive type and a type known to be primitive, or + // an index type and a nullable or bigint-like type. if (includes & TypeFlags.Never) { return contains(typeSet, silentNeverType) ? silentNeverType : neverType; } - if (strictNullChecks && includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) || + if (includes & TypeFlags.Nullable && includes & (TypeFlags.Object | TypeFlags.NonPrimitive | TypeFlags.IncludesEmptyObject) || includes & TypeFlags.NonPrimitive && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NonPrimitive) || includes & TypeFlags.StringLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.StringLike) || includes & TypeFlags.NumberLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.NumberLike) || includes & TypeFlags.BigIntLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.BigIntLike) || includes & TypeFlags.ESSymbolLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.ESSymbolLike) || - includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike)) { + includes & TypeFlags.VoidLike && includes & (TypeFlags.DisjointDomains & ~TypeFlags.VoidLike) || + includes & TypeFlags.Index && includes & (TypeFlags.Nullable | TypeFlags.BigIntLike)) { return neverType; } if (includes & TypeFlags.TemplateLiteral && includes & TypeFlags.StringLiteral && extractRedundantTemplateLiterals(typeSet)) { @@ -15044,9 +15107,6 @@ namespace ts { if (includes & TypeFlags.Any) { return includes & TypeFlags.IncludesWildcard ? wildcardType : anyType; } - if (!strictNullChecks && includes & TypeFlags.Nullable) { - return includes & TypeFlags.Undefined ? undefinedType : nullType; - } if (includes & TypeFlags.String && includes & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) || includes & TypeFlags.Number && includes & TypeFlags.NumberLiteral || includes & TypeFlags.BigInt && includes & TypeFlags.BigIntLiteral || @@ -15075,7 +15135,7 @@ namespace ts { result = getIntersectionType(typeSet, aliasSymbol, aliasTypeArguments); } else if (eachIsUnionContaining(typeSet, TypeFlags.Undefined)) { - const undefinedOrMissingType = exactOptionalPropertyTypes && some(typeSet, t => containsType((t as UnionType).types, missingType)) ? missingType : undefinedType; + const undefinedOrMissingType = some(typeSet, t => containsType((t as UnionType).types, missingType)) ? missingType : undefinedType; removeFromEach(typeSet, TypeFlags.Undefined); result = getUnionType([getIntersectionType(typeSet), undefinedOrMissingType], UnionReduction.Literal, aliasSymbol, aliasTypeArguments); } @@ -15509,15 +15569,15 @@ namespace ts { * Should all count as literals and not print errors on access or assignment of possibly existing properties. * This mirrors the behavior of the index signature propagation, to which this behaves similarly (but doesn't affect assignability or inference). */ - function isJSLiteralType(type: Type): boolean { - if (noImplicitAny) { + function isJSLiteralType(type: Type, context?: Node): boolean { + if (noImplicitAny(getSourceFileOfNode(context))) { return false; // Flag is meaningless under `noImplicitAny` mode } if (getObjectFlags(type) & ObjectFlags.JSLiteral) { return true; } if (type.flags & TypeFlags.Union) { - return every((type as UnionType).types, isJSLiteralType); + return every((type as UnionType).types, t => isJSLiteralType(t)); } if (type.flags & TypeFlags.Intersection) { return some((type as IntersectionType).types, isJSLiteralType); @@ -15624,12 +15684,12 @@ namespace ts { if (indexType.flags & TypeFlags.Never) { return neverType; } - if (isJSLiteralType(objectType)) { + if (isJSLiteralType(objectType, accessNode)) { return anyType; } if (accessExpression && !isConstEnumObjectType(objectType)) { if (isObjectLiteralType(objectType)) { - if (noImplicitAny && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { + if (noImplicitAny(accessNode) && indexType.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) { diagnostics.add(createDiagnosticForNode(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, (indexType as StringLiteralType).value, typeToString(objectType))); return undefinedType; } @@ -15644,7 +15704,7 @@ namespace ts { if (objectType.symbol === globalThisSymbol && propName !== undefined && globalThisSymbol.exports!.has(propName) && (globalThisSymbol.exports!.get(propName)!.flags & SymbolFlags.BlockScoped)) { error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(propName), typeToString(objectType)); } - else if (noImplicitAny && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & AccessFlags.SuppressNoImplicitAnyError)) { + else if (noImplicitAny(accessExpression) && !compilerOptions.suppressImplicitAnyIndexErrors && !(accessFlags & AccessFlags.SuppressNoImplicitAnyError)) { if (propName !== undefined && typeHasStaticProperty(propName, objectType)) { const typeName = typeToString(objectType); error(accessExpression, Diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName as string, typeName, typeName + "[" + getTextOfNode(accessExpression.argumentExpression) + "]"); @@ -15695,7 +15755,7 @@ namespace ts { return undefined; } } - if (isJSLiteralType(objectType)) { + if (isJSLiteralType(objectType, accessNode)) { return anyType; } if (accessNode) { @@ -15912,7 +15972,7 @@ namespace ts { } // In noUncheckedIndexedAccess mode, indexed access operations that occur in an expression in a read position and resolve to // an index signature have 'undefined' included in their type. - if (compilerOptions.noUncheckedIndexedAccess && accessFlags & AccessFlags.ExpressionPosition) accessFlags |= AccessFlags.IncludeUndefined; + if (getFileLocalCompilerOption(getSourceFileOfNode(accessNode), compilerOptions, "noUncheckedIndexedAccess") && accessFlags & AccessFlags.ExpressionPosition) accessFlags |= AccessFlags.IncludeUndefined; // If the index type is generic, or if the object type is generic and doesn't originate in an expression and // the operation isn't exclusively indexing the fixed (non-variadic) portion of a tuple type, we are performing // a higher-order index access where we cannot meaningfully access the properties of the object type. Note that @@ -15938,7 +15998,10 @@ namespace ts { // In the following we resolve T[K] to the type of the property in T selected by K. // We treat boolean as different from other unions to improve errors; // skipping straight to getPropertyTypeForIndexType gives errors with 'boolean' instead of 'true'. - const apparentObjectType = getReducedApparentType(objectType); + let apparentObjectType = getReducedApparentType(objectType); + if (!strictNullChecks(accessNode) && apparentObjectType.flags & TypeFlags.Unknown) { + apparentObjectType = emptyObjectType; + } if (indexType.flags & TypeFlags.Union && !(indexType.flags & TypeFlags.Boolean)) { const propTypes: Type[] = []; let wasMissingProp = false; @@ -16404,7 +16467,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 : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true); + result.type = isSetonlyAccessor ? undefinedType : addOptionality(getTypeOfSymbol(prop), prop.declarations?.[0], /*isProperty*/ true); result.declarations = prop.declarations; result.nameType = getSymbolLinks(prop).nameType; result.syntheticOrigin = prop; @@ -16492,7 +16555,7 @@ namespace ts { const declarations = concatenate(leftProp.declarations, rightProp.declarations); const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional); const result = createSymbol(flags, leftProp.escapedName); - result.type = getUnionType([getTypeOfSymbol(leftProp), removeMissingOrUndefinedType(rightType)], UnionReduction.Subtype); + result.type = getUnionType([getTypeOfSymbol(leftProp), removeMissingOrUndefinedType(rightType, rightProp.valueDeclaration)], UnionReduction.Subtype); result.leftSpread = leftProp; result.rightSpread = rightProp; result.declarations = declarations; @@ -16595,7 +16658,7 @@ namespace ts { function getTypeFromLiteralTypeNode(node: LiteralTypeNode): Type { if (node.literal.kind === SyntaxKind.NullKeyword) { - return nullType; + return strictNullChecks(node) ? nullType : nullPermissiveType; } const links = getNodeLinks(node); if (!links.resolvedType) { @@ -16684,7 +16747,7 @@ namespace ts { const links = getNodeLinks(node); return links.resolvedType || (links.resolvedType = node.dotDotDotToken ? getTypeFromRestTypeNode(node) : - addOptionality(getTypeFromTypeNode(node.type), /*isProperty*/ true, !!node.questionToken)); + addOptionality(getTypeFromTypeNode(node.type), node, /*isProperty*/ true, !!node.questionToken)); } function getTypeFromTypeNode(node: TypeNode): Type { @@ -16712,14 +16775,14 @@ namespace ts { case SyntaxKind.VoidKeyword: return voidType; case SyntaxKind.UndefinedKeyword: - return undefinedType; + return strictNullChecks(node) ? undefinedType : undefinedPermissiveType; case SyntaxKind.NullKeyword as TypeNodeSyntaxKind: // TODO(rbuckton): `NullKeyword` is no longer a `TypeNode`, but we defensively allow it here because of incorrect casts in the Language Service. - return nullType; + return strictNullChecks(node) ? nullType : nullPermissiveType; case SyntaxKind.NeverKeyword: return neverType; case SyntaxKind.ObjectKeyword: - return node.flags & NodeFlags.JavaScriptFile && !noImplicitAny ? anyType : nonPrimitiveType; + return node.flags & NodeFlags.JavaScriptFile && !noImplicitAny(node) ? anyType : nonPrimitiveType; case SyntaxKind.IntrinsicKeyword: return intrinsicMarkerType; case SyntaxKind.ThisType: @@ -16748,7 +16811,7 @@ namespace ts { case SyntaxKind.JSDocNullableType: return getTypeFromJSDocNullableTypeNode(node as JSDocNullableType); case SyntaxKind.JSDocOptionalType: - return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type)); + return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type), node); case SyntaxKind.NamedTupleMember: return getTypeFromNamedTupleTypeNode(node as NamedTupleMember); case SyntaxKind.ParenthesizedType: @@ -17173,8 +17236,8 @@ 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, /*isProperty*/ true) : - strictNullChecks && modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : + return modifiers & MappedTypeModifiers.IncludeOptional && !maybeTypeOfKind(propType, TypeFlags.Undefined | TypeFlags.Void) ? getOptionalType(propType, type.declaration, /*isProperty*/ false) : + modifiers & MappedTypeModifiers.ExcludeOptional && isOptional ? getTypeWithFacts(propType, TypeFacts.NEUndefined, type.declaration) : propType; } @@ -17715,7 +17778,7 @@ namespace ts { const resultObj: { errors?: Diagnostic[] } = errorOutputContainer || {}; // Use the expression type, if available const specificSource = next ? checkExpressionForMutableLocationWithContextualType(next, sourcePropType) : sourcePropType; - if (exactOptionalPropertyTypes && isExactOptionalPropertyMismatch(specificSource, targetPropType)) { + if (exactOptionalPropertyTypes(prop) && isExactOptionalPropertyMismatch(specificSource, targetPropType)) { const diag = createDiagnosticForNode(prop, Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target, typeToString(specificSource), typeToString(targetPropType)); diagnostics.add(diag); resultObj.errors = [diag]; @@ -18040,7 +18103,10 @@ namespace ts { } const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; - const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictFunctionTypes && kind !== SyntaxKind.MethodDeclaration && + const sourceFile = source.declaration && getSourceFileOfNode(source.declaration); + const targetFile = target.declaration && getSourceFileOfNode(target.declaration); + const strictSignatureComparison = strictFunctionTypes(sourceFile) || strictFunctionTypes(targetFile); + const strictVariance = !(checkMode & SignatureCheckMode.Callback) && strictSignatureComparison && kind !== SyntaxKind.MethodDeclaration && kind !== SyntaxKind.MethodSignature && kind !== SyntaxKind.Constructor; let result = Ternary.True; @@ -18076,10 +18142,10 @@ namespace ts { // similar to return values, callback parameters are output positions. This means that a Promise, // where T is used only in callback parameter positions, will be co-variant (as opposed to bi-variant) // with respect to T. - const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType)); - const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType)); + const sourceSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(sourceType, sourceFile)); + const targetSig = checkMode & SignatureCheckMode.Callback ? undefined : getSingleCallSignature(getNonNullableType(targetType, targetFile)); const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) && - (getTypeFacts(sourceType) & TypeFacts.IsUndefinedOrNull) === (getTypeFacts(targetType) & TypeFacts.IsUndefinedOrNull); + (getTypeFacts(sourceType, sourceFile) & TypeFacts.IsUndefinedOrNull) === (getTypeFacts(targetType, targetFile) & TypeFacts.IsUndefinedOrNull); let related = callbacks ? compareSignaturesRelated(targetSig, sourceSig, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : !(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); @@ -18215,7 +18281,7 @@ namespace ts { } function isUnknownLikeUnionType(type: Type) { - if (strictNullChecks && type.flags & TypeFlags.Union) { + if (type.flags & TypeFlags.Union) { if (!((type as UnionType).objectFlags & ObjectFlags.IsUnknownLikeUnionComputed)) { const types = (type as UnionType).types; (type as UnionType).objectFlags |= ObjectFlags.IsUnknownLikeUnionComputed | (types.length >= 3 && types[0].flags & TypeFlags.Undefined && @@ -18295,8 +18361,9 @@ namespace ts { } // In non-strictNullChecks mode, `undefined` and `null` are assignable to anything except `never`. // Since unions and intersections may reduce to `never`, we exclude them here. - if (s & TypeFlags.Undefined && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & (TypeFlags.Undefined | TypeFlags.Void))) return true; - if (s & TypeFlags.Null && (!strictNullChecks && !(t & TypeFlags.UnionOrIntersection) || t & TypeFlags.Null)) return true; + if ((source === undefinedWideningType || source === nullWideningType || source === undefinedPermissiveType || source === nullPermissiveType) && !(t & TypeFlags.UnionOrIntersection)) return true; + if (s & TypeFlags.Undefined && t & (TypeFlags.Undefined | TypeFlags.Void)) return true; + if (s & TypeFlags.Null && t & TypeFlags.Null) return true; if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive && !(relation === strictSubtypeRelation && isEmptyAnonymousObjectType(source) && !(getObjectFlags(source) & ObjectFlags.FreshLiteral))) return true; if (relation === assignableRelation || relation === comparableRelation) { if (s & TypeFlags.Any) return true; @@ -18608,7 +18675,9 @@ namespace ts { relatedInfo = [info]; } else { - relatedInfo.push(info); + if (!some(relatedInfo, i => compareDiagnostics(i, info) === Comparison.EqualTo)) { + relatedInfo.push(info); + } } } @@ -18652,7 +18721,7 @@ namespace ts { else if (sourceType === targetType) { message = Diagnostics.Type_0_is_not_assignable_to_type_1_Two_different_types_with_this_name_exist_but_they_are_unrelated; } - else if (exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length) { + else if (getExactOptionalUnassignableProperties(source, target).length) { message = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; } else { @@ -18667,7 +18736,6 @@ namespace ts { } } else if (message === Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1 - && exactOptionalPropertyTypes && getExactOptionalUnassignableProperties(source, target).length) { message = Diagnostics.Argument_of_type_0_is_not_assignable_to_parameter_of_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_types_of_the_target_s_properties; } @@ -18950,7 +19018,9 @@ namespace ts { } function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { - if (!isExcessPropertyCheckTarget(target) || !noImplicitAny && getObjectFlags(target) & ObjectFlags.JSLiteral) { + const sourceNoImplicitAny = noImplicitAny(source.symbol?.valueDeclaration); + const targetNoImplicitAny = noImplicitAny(target.symbol?.valueDeclaration); + if (!isExcessPropertyCheckTarget(target) || !(sourceNoImplicitAny || targetNoImplicitAny) && getObjectFlags(target) & ObjectFlags.JSLiteral) { return false; // Disable excess property checks on JS literals to simulate having an implicit "index signature" - but only outside of noImplicitAny } const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); @@ -19722,13 +19792,13 @@ namespace ts { if (sourceFlags & TypeFlags.TypeVariable) { // IndexedAccess comparisons are handled above in the `targetFlags & TypeFlage.IndexedAccess` branch if (!(sourceFlags & TypeFlags.IndexedAccess && targetFlags & TypeFlags.IndexedAccess)) { - const constraint = getConstraintOfType(source as TypeVariable) || unknownType; + const constraint = getConstraintOfType(source as TypeVariable) || getUnknownConstraintForType(source as TypeVariable); // hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed if (result = isRelatedTo(constraint, target, RecursionFlags.Source, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState)) { return result; } // slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example - else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && constraint !== unknownType && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) { + else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, RecursionFlags.Source, reportErrors && !(constraint.flags & TypeFlags.Unknown) && !(targetFlags & sourceFlags & TypeFlags.TypeParameter), /*headMessage*/ undefined, intersectionState)) { return result; } if (isMappedTypeGenericIndexedAccess(source)) { @@ -20044,7 +20114,7 @@ namespace ts { if (!targetProperty) continue outer; if (sourceProperty === targetProperty) continue; // We compare the source property to the target in the context of a single discriminant type. - const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks || relation === comparableRelation); + const related = propertyRelatedTo(source, target, sourceProperty, targetProperty, _ => combination[i], /*reportErrors*/ false, IntersectionState.None, /*skipOptional*/ strictNullChecks(targetProperty.valueDeclaration) || relation === comparableRelation); // If the target property could not be found, or if the properties were not related, // then this constituent is not a match. if (!related) { @@ -20101,8 +20171,8 @@ 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 effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), /*isProperty*/ false, targetIsOptional); + const targetIsOptional = strictNullChecks(targetProp.valueDeclaration) && !!(getCheckFlags(targetProp) & CheckFlags.Partial); + const effectiveTarget = addOptionality(getNonMissingTypeOfSymbol(targetProp), targetProp.valueDeclaration, /*isProperty*/ false, targetIsOptional); const effectiveSource = getTypeOfSourceProperty(sourceProp); return isRelatedTo(effectiveSource, effectiveTarget, RecursionFlags.Both, reportErrors, /*headMessage*/ undefined, intersectionState); } @@ -20556,9 +20626,9 @@ namespace ts { } if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), keyType)) { const propType = getNonMissingTypeOfSymbol(prop); - const type = exactOptionalPropertyTypes || propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional) + const type = exactOptionalPropertyTypes(prop.valueDeclaration) || propType.flags & TypeFlags.Undefined || keyType === numberType || !(prop.flags & SymbolFlags.Optional) ? propType - : getTypeWithFacts(propType, TypeFacts.NEUndefined); + : getTypeWithFacts(propType, TypeFacts.NEUndefined, prop.valueDeclaration); const related = isRelatedTo(type, targetInfo.type, RecursionFlags.Both, reportErrors); if (!related) { if (reportErrors) { @@ -20715,7 +20785,8 @@ namespace ts { findMatchingTypeReferenceOrTypeAliasReference(source, target) || findBestTypeForObjectLiteral(source, target) || findBestTypeForInvokable(source, target) || - findMostOverlappyType(source, target); + findMostOverlappyType(source, target) || + (target.types.length === 2 && target.types[0].flags & TypeFlags.Nullable ? target.types[1] : undefined); } function discriminateTypeByDiscriminableItems(target: UnionType, discriminators: [() => Type, __String][], related: (source: Type, target: Type) => boolean | Ternary, defaultValue?: undefined, skipPartial?: boolean): Type | undefined; @@ -21218,8 +21289,8 @@ namespace ts { reduceLeft(types, (s, t) => isTypeSubtypeOf(s, t) ? t : s)!; } - function getCommonSupertype(types: Type[]): Type { - if (!strictNullChecks) { + function getCommonSupertype(types: Type[], context: Node | undefined): Type { + if (!strictNullChecks(context)) { return getSupertypeOrUnion(types); } const primaryTypes = filter(types, t => !(t.flags & TypeFlags.Nullable)); @@ -21294,7 +21365,7 @@ namespace ts { } function isEmptyLiteralType(type: Type): boolean { - return strictNullChecks ? type === implicitNeverType : type === undefinedWideningType; + return type === implicitNeverType || type === undefinedWideningType; } function isEmptyArrayLiteralType(type: Type): boolean { @@ -21449,8 +21520,8 @@ namespace ts { return value.base10Value === "0"; } - function removeDefinitelyFalsyTypes(type: Type): Type { - return filterType(type, t => !!(getTypeFacts(t) & TypeFacts.Truthy)); + function removeDefinitelyFalsyTypes(type: Type, context: Node | undefined): Type { + return filterType(type, t => !!(getTypeFacts(t, context) & TypeFacts.Truthy)); } function extractDefinitelyFalsyTypes(type: Type): Type { @@ -21483,9 +21554,14 @@ namespace ts { getUnionType([type, undefinedType, nullType]); } - function getOptionalType(type: Type, isProperty = false): Type { - Debug.assert(strictNullChecks); - return type.flags & TypeFlags.Undefined ? type : getUnionType([type, isProperty ? missingType : undefinedType]); + /** + * *Most* callers should only use this when `strictNullChecks` is known to be `true` for the given `context`, + * as it unconditionally introduces some form of `undefined` into the result. + * An important exception is control-flow-based initialization checking, which sometimes may want to use this + * outside `strictNullChecks` mode. + */ + function getOptionalType(type: Type, context: Node | undefined, isProperty = false): Type { + return type.flags & TypeFlags.Undefined ? type : getUnionType([type, isProperty ? getMissingOrUndefinedType(context) : undefinedType]); } function getGlobalNonNullableTypeInstantiation(type: Type) { @@ -21497,38 +21573,38 @@ namespace ts { getIntersectionType([type, emptyObjectType]); } - function getNonNullableType(type: Type): Type { - return strictNullChecks ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; + function getNonNullableType(type: Type, context: Node | undefined): Type { + return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, context); } - function addOptionalTypeMarker(type: Type) { - return strictNullChecks ? getUnionType([type, optionalType]) : type; + function addOptionalTypeMarker(type: Type, context: Node | undefined) { + return strictNullChecks(context) ? getUnionType([type, optionalType]) : type; } function removeOptionalTypeMarker(type: Type): Type { - return strictNullChecks ? removeType(type, optionalType) : type; + return removeType(type, optionalType); } function propagateOptionalTypeMarker(type: Type, node: OptionalChain, wasOptional: boolean) { - return wasOptional ? isOutermostOptionalChain(node) ? getOptionalType(type) : addOptionalTypeMarker(type) : type; + return wasOptional ? isOutermostOptionalChain(node) ? getOptionalType(type, node) : addOptionalTypeMarker(type, node) : type; } function getOptionalExpressionType(exprType: Type, expression: Expression) { - return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType) : + return isExpressionOfOptionalChainRoot(expression) ? getNonNullableType(exprType, expression) : isOptionalChain(expression) ? removeOptionalTypeMarker(exprType) : exprType; } function removeMissingType(type: Type, isOptional: boolean) { - return exactOptionalPropertyTypes && isOptional ? removeType(type, missingType) : type; + return isOptional ? removeType(type, missingType) : type; } function containsMissingType(type: Type) { - return exactOptionalPropertyTypes && (type === missingType || type.flags & TypeFlags.Union && containsType((type as UnionType).types, missingType)); + return (type === missingType || type.flags & TypeFlags.Union && containsType((type as UnionType).types, missingType)); } - function removeMissingOrUndefinedType(type: Type): Type { - return exactOptionalPropertyTypes ? removeType(type, missingType) : getTypeWithFacts(type, TypeFacts.NEUndefined); + function removeMissingOrUndefinedType(type: Type, context: Node | undefined): Type { + return exactOptionalPropertyTypes(context) ? removeType(type, missingType) : getTypeWithFacts(type, TypeFacts.NEUndefined, context); } /** @@ -21677,7 +21753,7 @@ namespace ts { if (cached) { return cached; } - const result = createSymbolWithType(prop, missingType); + const result = createSymbolWithType(prop, getMissingOrUndefinedType(prop.valueDeclaration)); result.flags |= SymbolFlags.Optional; undefinedProperties.set(prop.escapedName, result); return result; @@ -21798,7 +21874,7 @@ namespace ts { case SyntaxKind.BinaryExpression: case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - diagnostic = noImplicitAny ? Diagnostics.Member_0_implicitly_has_an_1_type : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = noImplicitAny(declaration) ? Diagnostics.Member_0_implicitly_has_an_1_type : Diagnostics.Member_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; break; case SyntaxKind.Parameter: const param = declaration as ParameterDeclaration; @@ -21809,16 +21885,16 @@ namespace ts { param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) { const newName = "arg" + param.parent.parameters.indexOf(param); const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : ""); - errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); + errorOrSuggestion(noImplicitAny(declaration), declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); return; } diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ? - noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage : - noImplicitAny ? Diagnostics.Parameter_0_implicitly_has_an_1_type : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + noImplicitAny(declaration) ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage : + noImplicitAny(declaration) ? Diagnostics.Parameter_0_implicitly_has_an_1_type : Diagnostics.Parameter_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; break; case SyntaxKind.BindingElement: diagnostic = Diagnostics.Binding_element_0_implicitly_has_an_1_type; - if (!noImplicitAny) { + if (!noImplicitAny(declaration)) { // Don't issue a suggestion for binding elements since the codefix doesn't yet support them. return; } @@ -21833,7 +21909,7 @@ namespace ts { case SyntaxKind.SetAccessor: case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - if (noImplicitAny && !(declaration as NamedDeclaration).name) { + if (noImplicitAny(declaration) && !(declaration as NamedDeclaration).name) { if (wideningKind === WideningKind.GeneratorYield) { error(declaration, Diagnostics.Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, typeAsString); } @@ -21842,24 +21918,24 @@ namespace ts { } return; } - diagnostic = !noImplicitAny ? Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage : + diagnostic = !noImplicitAny(declaration) ? Diagnostics._0_implicitly_has_an_1_return_type_but_a_better_type_may_be_inferred_from_usage : wideningKind === WideningKind.GeneratorYield ? Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_yield_type : Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type; break; case SyntaxKind.MappedType: - if (noImplicitAny) { + if (noImplicitAny(declaration)) { error(declaration, Diagnostics.Mapped_object_type_implicitly_has_an_any_template_type); } return; default: - diagnostic = noImplicitAny ? Diagnostics.Variable_0_implicitly_has_an_1_type : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; + diagnostic = noImplicitAny(declaration) ? Diagnostics.Variable_0_implicitly_has_an_1_type : Diagnostics.Variable_0_implicitly_has_an_1_type_but_a_better_type_may_be_inferred_from_usage; } - errorOrSuggestion(noImplicitAny, declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString); + errorOrSuggestion(noImplicitAny(declaration), declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString); } function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) { addLazyDiagnostic(() => { - if (noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) { + if (noImplicitAny(declaration) && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) { // Report implicit any error within type if possible, otherwise report error on declaration if (!reportWideningErrorsInType(type)) { reportImplicitAny(declaration, type, wideningKind); @@ -22688,7 +22764,10 @@ namespace ts { } function inferFromContravariantTypes(source: Type, target: Type) { - if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) { + const sourceFile = source.symbol?.valueDeclaration && getSourceFileOfNode(source.symbol?.valueDeclaration); + const targetFile = target.symbol?.valueDeclaration && getSourceFileOfNode(target.symbol?.valueDeclaration); + const strictSignatureComparison = strictFunctionTypes(sourceFile) || strictFunctionTypes(targetFile); + if (strictSignatureComparison || priority & InferencePriority.AlwaysStrict) { contravariant = !contravariant; inferFromTypes(source, target); contravariant = !contravariant; @@ -23071,7 +23150,7 @@ namespace ts { for (const prop of getPropertiesOfType(source)) { if (isApplicableIndexType(getLiteralTypeFromProperty(prop, TypeFlags.StringOrNumberLiteralOrUnique), targetInfo.keyType)) { const propType = getTypeOfSymbol(prop); - propTypes.push(prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType) : propType); + propTypes.push(prop.flags & SymbolFlags.Optional ? removeMissingOrUndefinedType(propType, prop.valueDeclaration) : propType); } } for (const info of getIndexInfosOfType(source)) { @@ -23094,7 +23173,7 @@ namespace ts { } function isTypeOrBaseIdenticalTo(s: Type, t: Type) { - return exactOptionalPropertyTypes && t === missingType ? s === t : + return t === missingType ? s === t : (isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral)); } @@ -23148,7 +23227,7 @@ namespace ts { // Otherwise, infer a common supertype. const unwidenedType = inference.priority! & InferencePriority.PriorityImpliesCombination ? getUnionType(baseCandidates, UnionReduction.Subtype) : - getCommonSupertype(baseCandidates); + getCommonSupertype(baseCandidates, inference.typeParameter.symbol.declarations?.[0]); return getWidenedType(unwidenedType); } @@ -23632,52 +23711,52 @@ namespace ts { resolved.members.get("bind" as __String) && isTypeSubtypeOf(type, globalFunctionType)); } - function getTypeFacts(type: Type): TypeFacts { + function getTypeFacts(type: Type, context: Node | undefined): TypeFacts { if (type.flags & (TypeFlags.Intersection | TypeFlags.Instantiable)) { type = getBaseConstraintOfType(type) || unknownType; } const flags = type.flags; if (flags & (TypeFlags.String | TypeFlags.StringMapping)) { - return strictNullChecks ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts; + return strictNullChecks(context) ? TypeFacts.StringStrictFacts : TypeFacts.StringFacts; } if (flags & (TypeFlags.StringLiteral | TypeFlags.TemplateLiteral)) { const isEmpty = flags & TypeFlags.StringLiteral && (type as StringLiteralType).value === ""; - return strictNullChecks ? + return strictNullChecks(context) ? isEmpty ? TypeFacts.EmptyStringStrictFacts : TypeFacts.NonEmptyStringStrictFacts : isEmpty ? TypeFacts.EmptyStringFacts : TypeFacts.NonEmptyStringFacts; } if (flags & (TypeFlags.Number | TypeFlags.Enum)) { - return strictNullChecks ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; + return strictNullChecks(context) ? TypeFacts.NumberStrictFacts : TypeFacts.NumberFacts; } if (flags & TypeFlags.NumberLiteral) { const isZero = (type as NumberLiteralType).value === 0; - return strictNullChecks ? + return strictNullChecks(context) ? isZero ? TypeFacts.ZeroNumberStrictFacts : TypeFacts.NonZeroNumberStrictFacts : isZero ? TypeFacts.ZeroNumberFacts : TypeFacts.NonZeroNumberFacts; } if (flags & TypeFlags.BigInt) { - return strictNullChecks ? TypeFacts.BigIntStrictFacts : TypeFacts.BigIntFacts; + return strictNullChecks(context) ? TypeFacts.BigIntStrictFacts : TypeFacts.BigIntFacts; } if (flags & TypeFlags.BigIntLiteral) { const isZero = isZeroBigInt(type as BigIntLiteralType); - return strictNullChecks ? + return strictNullChecks(context) ? isZero ? TypeFacts.ZeroBigIntStrictFacts : TypeFacts.NonZeroBigIntStrictFacts : isZero ? TypeFacts.ZeroBigIntFacts : TypeFacts.NonZeroBigIntFacts; } if (flags & TypeFlags.Boolean) { - return strictNullChecks ? TypeFacts.BooleanStrictFacts : TypeFacts.BooleanFacts; + return strictNullChecks(context) ? TypeFacts.BooleanStrictFacts : TypeFacts.BooleanFacts; } if (flags & TypeFlags.BooleanLike) { - return strictNullChecks ? + return strictNullChecks(context) ? (type === falseType || type === regularFalseType) ? TypeFacts.FalseStrictFacts : TypeFacts.TrueStrictFacts : (type === falseType || type === regularFalseType) ? TypeFacts.FalseFacts : TypeFacts.TrueFacts; } if (flags & TypeFlags.Object) { return getObjectFlags(type) & ObjectFlags.Anonymous && isEmptyObjectType(type as ObjectType) ? - strictNullChecks ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts : + strictNullChecks(context) ? TypeFacts.EmptyObjectStrictFacts : TypeFacts.EmptyObjectFacts : isFunctionObjectType(type as ObjectType) ? - strictNullChecks ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : - strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; + strictNullChecks(context) ? TypeFacts.FunctionStrictFacts : TypeFacts.FunctionFacts : + strictNullChecks(context) ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } if (flags & TypeFlags.Void) { return TypeFacts.VoidFacts; @@ -23689,24 +23768,24 @@ namespace ts { return TypeFacts.NullFacts; } if (flags & TypeFlags.ESSymbolLike) { - return strictNullChecks ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts; + return strictNullChecks(context) ? TypeFacts.SymbolStrictFacts : TypeFacts.SymbolFacts; } if (flags & TypeFlags.NonPrimitive) { - return strictNullChecks ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; + return strictNullChecks(context) ? TypeFacts.ObjectStrictFacts : TypeFacts.ObjectFacts; } if (flags & TypeFlags.Never) { return TypeFacts.None; } if (flags & TypeFlags.Union) { - return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t), TypeFacts.None); + return reduceLeft((type as UnionType).types, (facts, t) => facts | getTypeFacts(t, context), TypeFacts.None); } if (flags & TypeFlags.Intersection) { - return getIntersectionTypeFacts(type as IntersectionType); + return getIntersectionTypeFacts(type as IntersectionType, context); } return TypeFacts.UnknownFacts; } - function getIntersectionTypeFacts(type: IntersectionType): TypeFacts { + function getIntersectionTypeFacts(type: IntersectionType, context: Node | undefined): TypeFacts { // When an intersection contains a primitive type we ignore object type constituents as they are // presumably type tags. For example, in string & { __kind__: "name" } we ignore the object type. const ignoreObjects = maybeTypeOfKind(type, TypeFlags.Primitive); @@ -23716,7 +23795,7 @@ namespace ts { let andedFacts = TypeFacts.All; for (const t of type.types) { if (!(ignoreObjects && t.flags & TypeFlags.Object)) { - const f = getTypeFacts(t); + const f = getTypeFacts(t, context); oredFacts |= f; andedFacts &= f; } @@ -23724,24 +23803,24 @@ namespace ts { return oredFacts & TypeFacts.OrFactsMask | andedFacts & TypeFacts.AndFactsMask; } - function getTypeWithFacts(type: Type, include: TypeFacts) { - return filterType(type, t => (getTypeFacts(t) & include) !== 0); + function getTypeWithFacts(type: Type, include: TypeFacts, context: Node | undefined) { + return filterType(type, t => (getTypeFacts(t, context) & include) !== 0); } // This function is similar to getTypeWithFacts, except that in strictNullChecks mode it replaces type // unknown with the union {} | null | undefined (and reduces that accordingly), and it intersects remaining // instantiable types with {}, {} | null, or {} | undefined in order to remove null and/or undefined. - function getAdjustedTypeWithFacts(type: Type, facts: TypeFacts) { - const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts)); - if (strictNullChecks) { + function getAdjustedTypeWithFacts(type: Type, facts: TypeFacts, context: Node | undefined) { + const reduced = recombineUnknownType(getTypeWithFacts(strictNullChecks(context) && type.flags & TypeFlags.Unknown ? unknownUnionType : type, facts, context)); + if (strictNullChecks(context)) { switch (facts) { case TypeFacts.NEUndefined: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]): t); + return mapType(reduced, t => getTypeFacts(t, context) & TypeFacts.EQUndefined ? getIntersectionType([t, getTypeFacts(t, context) & TypeFacts.EQNull && !maybeTypeOfKind(reduced, TypeFlags.Null) ? getUnionType([emptyObjectType, nullType]) : emptyObjectType]): t); case TypeFacts.NENull: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]): t); + return mapType(reduced, t => getTypeFacts(t, context) & TypeFacts.EQNull ? getIntersectionType([t, getTypeFacts(t, context) & TypeFacts.EQUndefined && !maybeTypeOfKind(reduced, TypeFlags.Undefined) ? getUnionType([emptyObjectType, undefinedType]) : emptyObjectType]): t); case TypeFacts.NEUndefinedOrNull: case TypeFacts.Truthy: - return mapType(reduced, t => getTypeFacts(t) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t): t); + return mapType(reduced, t => getTypeFacts(t, context) & TypeFacts.EQUndefinedOrNull ? getGlobalNonNullableTypeInstantiation(t): t); } } return reduced; @@ -23753,7 +23832,7 @@ namespace ts { function getTypeWithDefault(type: Type, defaultExpression: Expression) { return defaultExpression ? - getUnionType([getNonUndefinedType(type), getTypeOfExpression(defaultExpression)]) : + getUnionType([getNonUndefinedType(type, defaultExpression), getTypeOfExpression(defaultExpression)]) : type; } @@ -23761,18 +23840,18 @@ namespace ts { const nameType = getLiteralTypeFromPropertyName(name); if (!isTypeUsableAsPropertyName(nameType)) return errorType; const text = getPropertyNameFromType(nameType); - return getTypeOfPropertyOfType(type, text) || includeUndefinedInIndexSignature(getApplicableIndexInfoForName(type, text)?.type) || errorType; + return getTypeOfPropertyOfType(type, text) || includeUndefinedInIndexSignature(getApplicableIndexInfoForName(type, text)?.type, type) || errorType; } function getTypeOfDestructuredArrayElement(type: Type, index: number) { return everyType(type, isTupleLikeType) && getTupleElementType(type, index) || - includeUndefinedInIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined)) || + includeUndefinedInIndexSignature(checkIteratedTypeOrElementType(IterationUse.Destructuring, type, undefinedType, /*errorNode*/ undefined), type) || errorType; } - function includeUndefinedInIndexSignature(type: Type | undefined): Type | undefined { + function includeUndefinedInIndexSignature(type: Type | undefined, parentType: Type): Type | undefined { if (!type) return type; - return compilerOptions.noUncheckedIndexedAccess ? + return getFileLocalCompilerOption(getSourceFileOfNode(parentType.symbol?.valueDeclaration), compilerOptions, "noUncheckedIndexedAccess") ? getUnionType([type, undefinedType]) : type; } @@ -24447,7 +24526,7 @@ namespace ts { // on empty arrays are possible without implicit any errors and new element types can be inferred without // type mismatch errors. const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType); - if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && !(resultType.flags & TypeFlags.Never) && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) { + if (resultType === unreachableNeverType || reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && !(resultType.flags & TypeFlags.Never) && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull, reference).flags & TypeFlags.Never) { return declaredType; } // The non-null unknown type should never escape control flow analysis. @@ -24610,7 +24689,7 @@ namespace ts { } // for (const _ in ref) acts as a nonnull on ref if (isVariableDeclaration(node) && node.parent.parent.kind === SyntaxKind.ForInStatement && isMatchingReference(reference, node.parent.parent.expression)) { - return getNonNullableTypeIfNeeded(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent))); + return getNonNullableTypeIfNeeded(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent)), node); } // Assignment doesn't affect reference return undefined; @@ -24715,7 +24794,7 @@ namespace ts { type = narrowBySwitchOnTypeOf(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd); } else { - if (strictNullChecks) { + if (strictNullChecks(expr)) { if (optionalChainContainsReference(expr, reference)) { type = narrowTypeBySwitchOptionalChainContainment(type, flow.switchStatement, flow.clauseStart, flow.clauseEnd, t => !(t.flags & (TypeFlags.Undefined | TypeFlags.Never))); @@ -24870,6 +24949,32 @@ namespace ts { return result; } + /** + * This function preserves the non-strict mode behavior of `undefined` and `null` evaporating on contact with a union + * It uses `filterType` rather than `getTypeWithFacts` because `getTypeWithFacts` would consider generic constraints, which + * the old non-strict union-creation behavior never did. + */ + function filterNullAndUndefinedFromUnionIfNotStrict(type: Type) { + if (strictNullChecks(reference)) { + return type; + } + if (!(type.flags & TypeFlags.Union)) { + return type; + } + let containedNull: Type | undefined; + const filtered = filterType(type, t => { + if (t.flags & TypeFlags.Null) { + containedNull = t; + } + return !(t.flags & TypeFlags.Nullable); + }); + if (!(filtered.flags & TypeFlags.Never)) { + return filtered; + } + // only null/undefined union members - if both are present, historically, this makes the union evaluate to `null` + return containedNull || type; + } + // At flow control branch or loop junctions, if the type along every antecedent code path // is an evolving array type, we construct a combined evolving array type. Otherwise we // finalize all evolving array types. @@ -24877,7 +24982,7 @@ namespace ts { if (isEvolvingArrayTypeList(types)) { return getEvolvingArrayType(getUnionType(map(types, getElementTypeOfEvolvingArrayType))); } - const result = recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction)); + const result = filterNullAndUndefinedFromUnionIfNotStrict(recombineUnknownType(getUnionType(sameMap(types, finalizeEvolvingArrayType), subtypeReduction))); if (result !== declaredType && result.flags & declaredType.flags & TypeFlags.Union && arraysEqual((result as UnionType).types, (declaredType as UnionType).types)) { return declaredType; } @@ -24944,12 +25049,12 @@ namespace ts { if (propName === undefined) { return type; } - const removeNullable = strictNullChecks && isOptionalChain(access) && maybeTypeOfKind(type, TypeFlags.Nullable); - let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type, propName); + const removeNullable = strictNullChecks(access) && isOptionalChain(access) && maybeTypeOfKind(type, TypeFlags.Nullable); + let propType = getTypeOfPropertyOfType(removeNullable ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, access) : type, propName); if (!propType) { return type; } - propType = removeNullable ? getOptionalType(propType) : propType; + propType = removeNullable ? getOptionalType(propType, access) : propType; const narrowedPropType = narrowType(propType); return filterType(type, t => { const discriminantType = getTypeOfPropertyOrIndexSignature(t, propName); @@ -24985,14 +25090,14 @@ namespace ts { function narrowTypeByTruthiness(type: Type, expr: Expression, assumeTrue: boolean): Type { if (isMatchingReference(reference, expr)) { - return getAdjustedTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy); + return getAdjustedTypeWithFacts(type, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy, expr); } - if (strictNullChecks && assumeTrue && optionalChainContainsReference(expr, reference)) { - type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); + if (strictNullChecks(expr) && assumeTrue && optionalChainContainsReference(expr, reference)) { + type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, expr); } const access = getDiscriminantPropertyAccess(expr, type); if (access) { - return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy)); + return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumeTrue ? TypeFacts.Truthy : TypeFacts.Falsy, expr)); } return type; } @@ -25041,7 +25146,7 @@ namespace ts { if (isMatchingReference(reference, right)) { return narrowTypeByEquality(type, operator, left, assumeTrue); } - if (strictNullChecks) { + if (strictNullChecks(expr)) { if (optionalChainContainsReference(left, reference)) { type = narrowTypeByOptionalChainContainment(type, operator, right, assumeTrue); } @@ -25076,7 +25181,7 @@ namespace ts { const name = escapeLeadingUnderscores((leftType as StringLiteralType).value); if (containsMissingType(type) && isAccessExpression(reference) && isMatchingReference(reference.expression, target) && getAccessedPropertyName(reference) === name) { - return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined); + return getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined, expr); } if (isMatchingReference(reference, target)) { return narrowByInKeyword(type, name, assumeTrue); @@ -25134,7 +25239,7 @@ namespace ts { // Note that we include any and unknown in the exclusion test because their domain includes null and undefined. const removeNullable = equalsOperator !== assumeTrue && everyType(valueType, t => !!(t.flags & nullableFlags)) || equalsOperator === assumeTrue && everyType(valueType, t => !(t.flags & (TypeFlags.AnyOrUnknown | nullableFlags))); - return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; + return removeNullable ? getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, value) : type; } function narrowTypeByEquality(type: Type, operator: SyntaxKind, value: Expression, assumeTrue: boolean): Type { @@ -25155,7 +25260,7 @@ namespace ts { return type; } if (valueType.flags & TypeFlags.Nullable) { - if (!strictNullChecks) { + if (!strictNullChecks(value)) { return type; } const doubleEquals = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.ExclamationEqualsToken; @@ -25164,7 +25269,7 @@ namespace ts { valueType.flags & TypeFlags.Null ? assumeTrue ? TypeFacts.EQNull : TypeFacts.NENull : assumeTrue ? TypeFacts.EQUndefined : TypeFacts.NEUndefined; - return getAdjustedTypeWithFacts(type, facts); + return getAdjustedTypeWithFacts(type, facts, value); } if (assumeTrue) { const filterFn: (t: Type) => boolean = operator === SyntaxKind.EqualsEqualsToken ? @@ -25185,19 +25290,19 @@ namespace ts { } const target = getReferenceCandidate(typeOfExpr.expression); if (!isMatchingReference(reference, target)) { - if (strictNullChecks && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) { - return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); + if (strictNullChecks(typeOfExpr) && optionalChainContainsReference(target, reference) && assumeTrue === (literal.text !== "undefined")) { + return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, typeOfExpr); } return type; } return assumeTrue ? narrowTypeByTypeName(type, literal.text) : - getTypeWithFacts(type, typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject); + getTypeWithFacts(type, typeofNEFacts.get(literal.text) || TypeFacts.TypeofNEHostObject, typeOfExpr); } function narrowTypeBySwitchOptionalChainContainment(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number, clauseCheck: (type: Type) => boolean) { const everyClauseChecks = clauseStart !== clauseEnd && every(getSwitchClauseTypes(switchStatement).slice(clauseStart, clauseEnd), clauseCheck); - return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type; + return everyClauseChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, switchStatement) : type; } function narrowTypeBySwitchOnDiscriminant(type: Type, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number) { @@ -25263,14 +25368,14 @@ namespace ts { // the constituent based on its type facts. We use the strict subtype relation because it treats `object` // as a subtype of `{}`, and we need the type facts check because function types are subtypes of `object`, // but are classified as "function" according to `typeof`. - isTypeRelatedTo(t, impliedType, strictSubtypeRelation) ? getTypeFacts(t) & facts ? t : neverType : + isTypeRelatedTo(t, impliedType, strictSubtypeRelation) ? getTypeFacts(t, reference) & facts ? t : neverType : // We next check if the consituent is a supertype of the implied type. If so, we substitute the implied // type. This handles top types like `unknown` and `{}`, and supertypes like `{ toString(): string }`. isTypeSubtypeOf(impliedType, t) ? impliedType : // Neither the constituent nor the implied type is a subtype of the other, however their domains may still // overlap. For example, an unconstrained type parameter and type `string`. If the type facts indicate // possible overlap, we form an intersection. Otherwise, we eliminate the constituent. - getTypeFacts(t) & facts ? getIntersectionType([t, impliedType]) : + getTypeFacts(t, reference) & facts ? getIntersectionType([t, impliedType]) : neverType); } @@ -25285,7 +25390,7 @@ namespace ts { if (hasDefaultClause) { // In the default clause we filter constituents down to those that are not-equal to all handled cases. const notEqualFacts = getNotEqualFactsFromTypeofSwitch(clauseStart, clauseEnd, witnesses); - return filterType(type, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts); + return filterType(type, t => (getTypeFacts(t, switchStatement) & notEqualFacts) === notEqualFacts); } // In the non-default cause we create a union of the type narrowed by each of the listed cases. const clauseWitnesses = witnesses.slice(clauseStart, clauseEnd); @@ -25349,8 +25454,8 @@ namespace ts { function narrowTypeByInstanceof(type: Type, expr: BinaryExpression, assumeTrue: boolean): Type { const left = getReferenceCandidate(expr.left); if (!isMatchingReference(reference, left)) { - if (assumeTrue && strictNullChecks && optionalChainContainsReference(left, reference)) { - return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); + if (assumeTrue && strictNullChecks(expr) && optionalChainContainsReference(left, reference)) { + return getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, expr); } return type; } @@ -25435,7 +25540,7 @@ namespace ts { 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 getTypeWithFacts(type, assumeTrue ? TypeFacts.NEUndefined : TypeFacts.EQUndefined, argument); } } } @@ -25450,9 +25555,9 @@ namespace ts { if (isMatchingReference(reference, predicateArgument)) { return getNarrowedType(type, predicate.type, assumeTrue, /*checkDerived*/ false); } - if (strictNullChecks && assumeTrue && optionalChainContainsReference(predicateArgument, reference) && - !(getTypeFacts(predicate.type) & TypeFacts.EQUndefined)) { - type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull); + if (strictNullChecks(callExpression) && assumeTrue && optionalChainContainsReference(predicateArgument, reference) && + !(getTypeFacts(predicate.type, callExpression) & TypeFacts.EQUndefined)) { + type = getAdjustedTypeWithFacts(type, TypeFacts.NEUndefinedOrNull, callExpression); } const access = getDiscriminantPropertyAccess(predicateArgument, type); if (access) { @@ -25511,11 +25616,11 @@ namespace ts { function narrowTypeByOptionality(type: Type, expr: Expression, assumePresent: boolean): Type { if (isMatchingReference(reference, expr)) { - return getAdjustedTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull); + return getAdjustedTypeWithFacts(type, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull, expr); } const access = getDiscriminantPropertyAccess(expr, type); if (access) { - return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull)); + return narrowTypeByDiscriminant(type, access, t => getTypeWithFacts(t, assumePresent ? TypeFacts.NEUndefinedOrNull : TypeFacts.EQUndefinedOrNull, expr)); } return type; } @@ -25600,14 +25705,14 @@ namespace ts { /** remove undefined from the annotated type of a parameter when there is an initializer (that doesn't include undefined) */ function removeOptionalityFromDeclaredType(declaredType: Type, declaration: VariableLikeDeclaration): Type { if (pushTypeResolution(declaration.symbol, TypeSystemPropertyName.DeclaredType)) { - const annotationIncludesUndefined = strictNullChecks && + const annotationIncludesUndefined = strictNullChecks(declaration) && declaration.kind === SyntaxKind.Parameter && declaration.initializer && - getTypeFacts(declaredType) & TypeFacts.IsUndefined && - !(getTypeFacts(checkExpression(declaration.initializer)) & TypeFacts.IsUndefined); + getTypeFacts(declaredType, declaration) & TypeFacts.IsUndefined && + !(getTypeFacts(checkExpression(declaration.initializer), declaration) & TypeFacts.IsUndefined); popTypeResolution(); - return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined) : declaredType; + return annotationIncludesUndefined ? getTypeWithFacts(declaredType, TypeFacts.NEUndefined, declaration) : declaredType; } else { reportCircularityError(declaration.symbol); @@ -25793,6 +25898,19 @@ namespace ts { return errorType; } + if (symbol === undefinedSymbol) { + const assignmentKind = getAssignmentTargetKind(node); + if (assignmentKind) { + if (!(symbol.flags & SymbolFlags.Variable) && + !(isInJSFile(node) && symbol.flags & SymbolFlags.ValueModule)) { + const assignmentError = Diagnostics.Cannot_assign_to_0_because_it_is_not_a_variable; + error(node, assignmentError, symbolToString(symbol)); + return errorType; + } + } + return getUndefinedWideningType(node); + } + // As noted in ECMAScript 6 language spec, arrow functions never have an arguments objects. // Although in down-level emit of arrow function, we emit it using function expression which means that // arguments objects will be bound to the inner object; emitting arrow function natively in ES6, arguments objects @@ -25938,21 +26056,21 @@ namespace ts { // the entire control flow graph from the variable's declaration (i.e. when the flow container and // declaration container are the same). const assumeInitialized = isParameter || isAlias || isOuterVariable || isSpreadDestructuringAssignmentTarget || isModuleExports || isBindingElement(declaration) || - type !== autoType && type !== autoArrayType && (!strictNullChecks || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 || + type !== autoType && type !== autoArrayType && (!strictNullChecks(node) || (type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Void)) !== 0 || isInTypeQuery(node) || node.parent.kind === SyntaxKind.ExportSpecifier) || node.parent.kind === SyntaxKind.NonNullExpression || declaration.kind === SyntaxKind.VariableDeclaration && (declaration as VariableDeclaration).exclamationToken || declaration.flags & NodeFlags.Ambient; const initialType = assumeInitialized ? (isParameter ? removeOptionalityFromDeclaredType(type, declaration as VariableLikeDeclaration) : type) : type === autoType || type === autoArrayType ? undefinedType : - getOptionalType(type); + getOptionalType(type, node); const flowType = getFlowTypeOfReference(node, type, initialType, flowContainer); // A variable is considered uninitialized when it is possible to analyze the entire control flow graph // from declaration to use, and when the variable's declared type doesn't include undefined but the // control flow based type does include undefined. if (!isEvolvingArrayOperationTarget(node) && (type === autoType || type === autoArrayType)) { if (flowType === autoType || flowType === autoArrayType) { - if (noImplicitAny) { + if (noImplicitAny(node)) { error(getNameOfDeclaration(declaration), Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined, symbolToString(symbol), typeToString(flowType)); error(node, Diagnostics.Variable_0_implicitly_has_an_1_type, symbolToString(symbol), typeToString(flowType)); } @@ -26187,7 +26305,7 @@ namespace ts { } const type = tryGetThisTypeAt(node, /*includeGlobalThis*/ true, container); - if (noImplicitThis) { + if (noImplicitThis(getSourceFileOfNode(node))) { const globalThisType = getTypeOfSymbol(globalThisSymbol); if (type === globalThisType && capturedByArrowFunction) { error(node, Diagnostics.The_containing_arrow_function_captures_the_global_value_of_this); @@ -26589,7 +26707,7 @@ namespace ts { } } const inJs = isInJSFile(func); - if (noImplicitThis || inJs) { + if (noImplicitThis(getSourceFileOfNode(func)) || inJs) { const containingLiteral = getContainingObjectLiteral(func); if (containingLiteral) { // We have an object literal method. Check if the containing object literal has a contextual type @@ -26612,7 +26730,7 @@ namespace ts { // There was no contextual ThisType for the containing object literal, so the contextual type // for 'this' is the non-null form of the contextual type for the containing object literal or // the type of the object literal itself. - return getWidenedType(contextualType ? getNonNullableType(contextualType) : checkExpressionCached(containingLiteral)); + return getWidenedType(contextualType ? getNonNullableType(contextualType, literal) : checkExpressionCached(containingLiteral)); } // In an assignment of the form 'obj.xxx = function(...)' or 'obj[xxx] = function(...)', the // contextual type for 'this' is 'obj'. @@ -26654,7 +26772,7 @@ namespace ts { links.resolvedSignature = anySignature; const type = indexOfParameter < args.length ? getWidenedLiteralType(checkExpression(args[indexOfParameter])) : - parameter.initializer ? undefined : undefinedWideningType; + parameter.initializer ? undefined : getUndefinedWideningType(parameter); links.resolvedSignature = cached; return type; } @@ -27528,7 +27646,7 @@ namespace ts { } function getIntersectedSignatures(signatures: readonly Signature[]) { - return getStrictOptionValue(compilerOptions, "noImplicitAny") + return some(signatures, s => noImplicitAny(s.declaration)) ? reduceLeft( signatures, (left, right) => @@ -27759,7 +27877,7 @@ namespace ts { elementFlags.push(ElementFlags.Rest); } } - else if (exactOptionalPropertyTypes && e.kind === SyntaxKind.OmittedExpression) { + else if (exactOptionalPropertyTypes(e) && e.kind === SyntaxKind.OmittedExpression) { hasOmittedExpression = true; elementTypes.push(missingType); elementFlags.push(ElementFlags.Optional); @@ -27767,7 +27885,7 @@ namespace ts { else { const elementContextualType = getContextualTypeForElementExpression(contextualType, elementTypes.length); const type = checkExpressionForMutableLocation(e, checkMode, elementContextualType, forceTuple); - elementTypes.push(addOptionality(type, /*isProperty*/ true, hasOmittedExpression)); + elementTypes.push(addOptionality(type, e, /*isProperty*/ true, hasOmittedExpression)); elementFlags.push(hasOmittedExpression ? ElementFlags.Optional : ElementFlags.Required); if (contextualType && someType(contextualType, isTupleLikeType) && checkMode && checkMode & CheckMode.Inferential && !(checkMode & CheckMode.SkipContextSensitive) && isContextSensitive(e)) { const inferenceContext = getInferenceContext(node); @@ -27784,7 +27902,7 @@ namespace ts { } return createArrayLiteralType(createArrayType(elementTypes.length ? getUnionType(sameMap(elementTypes, (t, i) => elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), UnionReduction.Subtype) : - strictNullChecks ? implicitNeverType : undefinedWideningType, inConstContext)); + strictNullChecks(node) ? implicitNeverType : undefinedWideningType, inConstContext)); } function createArrayLiteralType(type: Type) { @@ -27896,7 +28014,7 @@ namespace ts { // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); - const allPropertiesTable = strictNullChecks ? createSymbolTable() : undefined; + const allPropertiesTable = strictNullChecks(node) ? createSymbolTable() : undefined; let propertiesTable = createSymbolTable(); let propertiesArray: Symbol[] = []; let spread: Type = emptyObjectType; @@ -28013,7 +28131,7 @@ namespace ts { hasComputedSymbolProperty = false; } const type = getReducedType(checkExpression(memberDecl.expression)); - if (isValidSpreadType(type)) { + if (isValidSpreadType(type, memberDecl)) { const mergedType = tryMergeUnionOfObjectTypeAndEmptyObject(type, inConstContext); if (allPropertiesTable) { checkSpreadPropOverrides(mergedType, allPropertiesTable, memberDecl); @@ -28117,10 +28235,10 @@ namespace ts { } } - function isValidSpreadType(type: Type): boolean { - const t = removeDefinitelyFalsyTypes(mapType(type, getBaseConstraintOrType)); + function isValidSpreadType(type: Type, context: Node | undefined): boolean { + const t = removeDefinitelyFalsyTypes(mapType(type, getBaseConstraintOrType), context); return !!(t.flags & (TypeFlags.Any | TypeFlags.NonPrimitive | TypeFlags.Object | TypeFlags.InstantiableNonPrimitive) || - t.flags & TypeFlags.UnionOrIntersection && every((t as UnionOrIntersectionType).types, isValidSpreadType)); + t.flags & TypeFlags.UnionOrIntersection && every((t as UnionOrIntersectionType).types, t => isValidSpreadType(t, context))); } function checkJsxSelfClosingElementDeferred(node: JsxSelfClosingElement) { @@ -28198,7 +28316,7 @@ namespace ts { */ function createJsxAttributesTypeFromAttributesProperty(openingLikeElement: JsxOpeningLikeElement, checkMode: CheckMode | undefined) { const attributes = openingLikeElement.attributes; - const allAttributesTable = strictNullChecks ? createSymbolTable() : undefined; + const allAttributesTable = strictNullChecks(openingLikeElement) ? createSymbolTable() : undefined; let attributesTable = createSymbolTable(); let spread: Type = emptyJsxObjectType; let hasSpreadAnyType = false; @@ -28237,7 +28355,7 @@ namespace ts { if (isTypeAny(exprType)) { hasSpreadAnyType = true; } - if (isValidSpreadType(exprType)) { + if (isValidSpreadType(exprType, attributeDecl)) { spread = getSpreadType(spread, exprType, attributes.symbol, objectFlags, /*readonly*/ false); if (allAttributesTable) { checkSpreadPropOverrides(exprType, allAttributesTable, attributeDecl); @@ -28389,7 +28507,7 @@ namespace ts { return links.resolvedSymbol = unknownSymbol; } else { - if (noImplicitAny) { + if (noImplicitAny(node)) { error(node, Diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, unescapeLeadingUnderscores(JsxNames.IntrinsicElements)); } return links.resolvedSymbol = unknownSymbol; @@ -28644,7 +28762,7 @@ namespace ts { } if (getJsxElementTypeAt(errorNode) === undefined) { - if (noImplicitAny) { + if (noImplicitAny(errorNode)) { error(errorNode, Diagnostics.JSX_element_implicitly_has_type_any_because_the_global_type_JSX_Element_does_not_exist); } } @@ -28954,12 +29072,12 @@ namespace ts { return checkNonNullType(checkExpression(node), node); } - function isNullableType(type: Type) { - return !!(getTypeFacts(type) & TypeFacts.IsUndefinedOrNull); + function isNullableType(type: Type, context: Node | undefined) { + return !!(getTypeFacts(type, context) & TypeFacts.IsUndefinedOrNull); } - function getNonNullableTypeIfNeeded(type: Type) { - return isNullableType(type) ? getNonNullableType(type) : type; + function getNonNullableTypeIfNeeded(type: Type, context: Node | undefined) { + return isNullableType(type, context) ? getNonNullableType(type, context) : type; } function reportObjectPossiblyNullOrUndefinedError(node: Node, facts: TypeFacts) { @@ -28983,14 +29101,19 @@ namespace ts { node: Node, reportError: (node: Node, facts: TypeFacts) => void ): Type { - if (strictNullChecks && type.flags & TypeFlags.Unknown) { + if (strictNullChecks(node) && type.flags & TypeFlags.Unknown) { error(node, Diagnostics.Object_is_of_type_unknown); return errorType; } - const facts = getTypeFacts(type); + const facts = getTypeFacts(type, node); if (facts & TypeFacts.IsUndefinedOrNull) { - reportError(node, facts); - const t = getNonNullableType(type); + // In non-strict-null-checks mode, traditionally unions have evaporated null/undefined upon construction (thus type facts would never have included them) + // _However_, non-union'd null/undefined could still exist... and still threw this error. It's oddly redundant + // and odd given the usual 'ignore null/undefined' behavior of non-strictNullChecks mode, but it's what we've done. + if (strictNullChecks(node) || !(type.flags & TypeFlags.Union)) { + reportError(node, facts); + } + const t = getNonNullableType(type, node); return t.flags & (TypeFlags.Nullable | TypeFlags.Never) ? errorType : t; } return type; @@ -29156,7 +29279,10 @@ namespace ts { function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined) { const parentSymbol = getNodeLinks(left).resolvedSymbol; const assignmentKind = getAssignmentTargetKind(node); - const apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType); + let apparentType = getApparentType(assignmentKind !== AssignmentKind.None || isMethodAccessForCall(node) ? getWidenedType(leftType) : leftType); + if (!strictNullChecks(node) && apparentType.flags & TypeFlags.Unknown) { + apparentType = emptyObjectType; + } const isAnyLike = isTypeAny(apparentType) || apparentType === silentNeverType; let prop: Symbol | undefined; if (isPrivateIdentifier(right)) { @@ -29225,14 +29351,14 @@ namespace ts { getApplicableIndexInfoForName(apparentType, right.escapedText) : undefined; if (!(indexInfo && indexInfo.type)) { const isUncheckedJS = isUncheckedJSSuggestion(node, leftType.symbol, /*excludeClasses*/ true); - if (!isUncheckedJS && isJSLiteralType(leftType)) { + if (!isUncheckedJS && isJSLiteralType(leftType, node)) { return anyType; } if (leftType.symbol === globalThisSymbol) { if (globalThisSymbol.exports!.has(right.escapedText) && (globalThisSymbol.exports!.get(right.escapedText)!.flags & SymbolFlags.BlockScoped)) { error(right, Diagnostics.Property_0_does_not_exist_on_type_1, unescapeLeadingUnderscores(right.escapedText), typeToString(leftType)); } - else if (noImplicitAny) { + else if (noImplicitAny(right)) { error(right, Diagnostics.Element_implicitly_has_an_any_type_because_type_0_has_no_index_signature, typeToString(leftType)); } return anyType; @@ -29246,8 +29372,8 @@ namespace ts { error(node, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(apparentType)); } - propType = (compilerOptions.noUncheckedIndexedAccess && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; - if (compilerOptions.noPropertyAccessFromIndexSignature && isPropertyAccessExpression(node)) { + propType = (getFileLocalCompilerOption(getSourceFileOfNode(node), compilerOptions, "noUncheckedIndexedAccess") && !isAssignmentTarget(node)) ? getUnionType([indexInfo.type, undefinedType]) : indexInfo.type; + if (getFileLocalCompilerOption(getSourceFileOfNode(node), compilerOptions, "noPropertyAccessFromIndexSignature") && isPropertyAccessExpression(node)) { error(right, Diagnostics.Property_0_comes_from_an_index_signature_so_it_must_be_accessed_with_0, unescapeLeadingUnderscores(right.escapedText)); } if (indexInfo.declaration && getCombinedNodeFlags(indexInfo.declaration) & NodeFlags.Deprecated) { @@ -29317,7 +29443,8 @@ namespace ts { // and if we are in a constructor of the same class as the property declaration, assume that // the property is uninitialized at the top of the control flow. let assumeUninitialized = false; - if (strictNullChecks && strictPropertyInitialization && isAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword) { + const file = getSourceFileOfNode(node); + if (strictNullChecks(node) && strictPropertyInitialization(file) && isAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword) { const declaration = prop && prop.valueDeclaration; if (declaration && isPropertyWithoutInitializer(declaration)) { if (!isStatic(declaration)) { @@ -29328,13 +29455,13 @@ namespace ts { } } } - else if (strictNullChecks && prop && prop.valueDeclaration && + else if (strictNullChecks(node) && prop && prop.valueDeclaration && isPropertyAccessExpression(prop.valueDeclaration) && getAssignmentDeclarationPropertyAccessKind(prop.valueDeclaration) && getControlFlowContainer(node) === getControlFlowContainer(prop.valueDeclaration)) { assumeUninitialized = true; } - const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType) : propType); + const flowType = getFlowTypeOfReference(node, propType, assumeUninitialized ? getOptionalType(propType, node) : propType); if (assumeUninitialized && !containsUndefinedType(propType) && containsUndefinedType(flowType)) { error(errorNode, Diagnostics.Property_0_is_used_before_being_assigned, symbolToString(prop!)); // TODO: GH#18217 // Return the declared type to reduce follow-on errors @@ -30018,7 +30145,7 @@ namespace ts { } for (let i = argCount; i < effectiveMinimumArguments; i++) { const type = getTypeAtPosition(signature, i); - if (filterType(type, isInJSFile(node) && !strictNullChecks ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid).flags & TypeFlags.Never) { + if (filterType(type, isInJSFile(node) && !strictNullChecks(node) ? acceptsVoidUndefinedUnknownOrAny : acceptsVoid).flags & TypeFlags.Never) { return false; } } @@ -30092,7 +30219,7 @@ namespace ts { return voidType; } const thisArgumentType = checkExpression(thisArgumentNode); - return isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType) : + return isOptionalChainRoot(thisArgumentNode.parent) ? getNonNullableType(thisArgumentType, thisArgumentNode) : isOptionalChain(thisArgumentNode.parent) ? removeOptionalTypeMarker(thisArgumentType) : thisArgumentType; } @@ -31360,7 +31487,7 @@ namespace ts { const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call); if (callSignatures.length) { const signature = resolveCall(node, callSignatures, candidatesOutArray, checkMode, SignatureFlags.None); - if (!noImplicitAny) { + if (!noImplicitAny(node)) { if (signature.declaration && !isJSConstructor(signature.declaration) && getReturnTypeOfSignature(signature) !== voidType) { error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword); } @@ -31919,7 +32046,7 @@ namespace ts { !isJSConstructor(declaration)) { // When resolved signature is a call signature (and not a construct signature) the result type is any - if (noImplicitAny) { + if (noImplicitAny(declaration)) { error(node, Diagnostics.new_expression_whose_target_lacks_a_construct_signature_implicitly_has_an_any_type); } return anyType; @@ -32085,7 +32212,7 @@ namespace ts { const anonymousSymbol = createSymbol(SymbolFlags.TypeLiteral, InternalSymbolName.Type); const defaultContainingObject = createDefaultPropertyWrapperForModule(symbol, originalSymbol, anonymousSymbol); anonymousSymbol.type = defaultContainingObject; - synthType.syntheticType = isValidSpreadType(type) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; + synthType.syntheticType = isValidSpreadType(type, file) ? getSpreadType(type, defaultContainingObject, anonymousSymbol, /*objectFlags*/ 0, /*readonly*/ false) : defaultContainingObject; } else { synthType.syntheticType = type; @@ -32202,12 +32329,12 @@ namespace ts { function checkNonNullChain(node: NonNullChain) { const leftType = checkExpression(node.expression); const nonOptionalType = getOptionalExpressionType(leftType, node.expression); - return propagateOptionalTypeMarker(getNonNullableType(nonOptionalType), node, nonOptionalType !== leftType); + return propagateOptionalTypeMarker(getNonNullableType(nonOptionalType, node), node, nonOptionalType !== leftType); } function checkNonNullAssertion(node: NonNullExpression) { return node.flags & NodeFlags.OptionalChain ? checkNonNullChain(node as NonNullChain) : - getNonNullableType(checkExpression(node.expression)); + getNonNullableType(checkExpression(node.expression), node); } function checkExpressionWithTypeArguments(node: ExpressionWithTypeArguments | TypeQueryNode) { @@ -32338,10 +32465,10 @@ namespace ts { function getTypeOfParameter(symbol: Symbol) { const type = getTypeOfSymbol(symbol); - if (strictNullChecks) { + if (strictNullChecks(symbol.valueDeclaration)) { const declaration = symbol.valueDeclaration; if (declaration && hasInitializer(declaration)) { - return getOptionalType(type); + return getOptionalType(type, declaration); } } return type; @@ -32795,7 +32922,8 @@ namespace ts { yieldType || neverType, returnType || fallbackReturnType, nextType || getContextualIterationType(IterationTypeKind.Next, func) || unknownType, - isAsync); + isAsync, + strictNullChecks(func)); } else { // From within an async function you can return either a non-promise value or a promise. Any @@ -32807,7 +32935,7 @@ namespace ts { } } - function createGeneratorReturnType(yieldType: Type, returnType: Type, nextType: Type, isAsyncGenerator: boolean) { + function createGeneratorReturnType(yieldType: Type, returnType: Type, nextType: Type, isAsyncGenerator: boolean, isStrictNullChecks: boolean) { const resolver = isAsyncGenerator ? asyncIterationTypesResolver : syncIterationTypesResolver; const globalGeneratorType = resolver.getGlobalGeneratorType(/*reportErrors*/ false); yieldType = resolver.resolveIterationType(yieldType, /*errorNode*/ undefined) || unknownType; @@ -32820,7 +32948,7 @@ namespace ts { const globalType = resolver.getGlobalIterableIteratorType(/*reportErrors*/ false); const iterationTypes = globalType !== emptyGenericType ? getIterationTypesOfGlobalIterableType(globalType, resolver) : undefined; const iterableIteratorReturnType = iterationTypes ? iterationTypes.returnType : anyType; - const iterableIteratorNextType = iterationTypes ? iterationTypes.nextType : undefinedType; + const iterableIteratorNextType = iterationTypes ? iterationTypes.nextType : isStrictNullChecks ? undefinedType : undefinedPermissiveType; if (isTypeAssignableTo(returnType, iterableIteratorReturnType) && isTypeAssignableTo(iterableIteratorNextType, nextType)) { if (globalType !== emptyGenericType) { @@ -32845,7 +32973,7 @@ namespace ts { const nextTypes: Type[] = []; const isAsync = (getFunctionFlags(func) & FunctionFlags.Async) !== 0; forEachYieldExpression(func.body as Block, yieldExpression => { - const yieldExpressionType = yieldExpression.expression ? checkExpression(yieldExpression.expression, checkMode) : undefinedWideningType; + const yieldExpressionType = yieldExpression.expression ? checkExpression(yieldExpression.expression, checkMode) : getUndefinedWideningType(func); pushIfUnique(yieldTypes, getYieldedTypeOfYieldExpression(yieldExpression, yieldExpressionType, anyType, isAsync)); let nextType: Type | undefined; if (yieldExpression.asteriskToken) { @@ -32901,7 +33029,7 @@ namespace ts { return (TypeFacts.AllTypeofNE & notEqualFacts) === TypeFacts.AllTypeofNE; } // A missing not-equal flag indicates that the type wasn't handled by some case. - return !someType(operandConstraint, t => (getTypeFacts(t) & notEqualFacts) === notEqualFacts); + return !someType(operandConstraint, t => (getTypeFacts(t, node) & notEqualFacts) === notEqualFacts); } const type = getTypeOfExpression(node.expression); if (!isLiteralType(type)) { @@ -32947,7 +33075,7 @@ namespace ts { if (aggregatedTypes.length === 0 && !hasReturnWithNoExpression && (hasReturnOfTypeNever || mayReturnNever(func))) { return undefined; } - if (strictNullChecks && aggregatedTypes.length && hasReturnWithNoExpression && + if (strictNullChecks(func) && aggregatedTypes.length && hasReturnWithNoExpression && !(isJSConstructor(func) && aggregatedTypes.some(t => t.symbol === func.symbol))) { // Javascript "callable constructors", containing eg `if (!(this instanceof A)) return new A()` should not add undefined pushIfUnique(aggregatedTypes, undefinedType); @@ -33005,10 +33133,10 @@ namespace ts { // this function does not conform to the specification. error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value); } - else if (type && strictNullChecks && !isTypeAssignableTo(undefinedType, type)) { + else if (type && strictNullChecks(func) && !isTypeAssignableTo(undefinedType, type)) { error(errorNode, Diagnostics.Function_lacks_ending_return_statement_and_return_type_does_not_include_undefined); } - else if (compilerOptions.noImplicitReturns) { + else if (getFileLocalCompilerOption(getSourceFileOfNode(errorNode), compilerOptions, "noImplicitReturns")) { if (!type) { // If return type annotation is omitted check if function has any explicit return statements. // If it does not have any - its inferred return type is void - don't do any checks. @@ -33294,9 +33422,9 @@ namespace ts { function checkDeleteExpressionMustBeOptional(expr: AccessExpression, symbol: Symbol) { const type = getTypeOfSymbol(symbol); - if (strictNullChecks && + if (strictNullChecks(expr) && !(type.flags & (TypeFlags.AnyOrUnknown | TypeFlags.Never)) && - !(exactOptionalPropertyTypes ? symbol.flags & SymbolFlags.Optional : getTypeFacts(type) & TypeFacts.IsUndefined)) { + !(exactOptionalPropertyTypes(expr) ? symbol.flags & SymbolFlags.Optional : getTypeFacts(type, expr) & TypeFacts.IsUndefined)) { error(expr, Diagnostics.The_operand_of_a_delete_operator_must_be_optional); } } @@ -33308,7 +33436,7 @@ namespace ts { function checkVoidExpression(node: VoidExpression): Type { checkExpression(node.expression); - return undefinedWideningType; + return getUndefinedWideningType(node); } function checkAwaitExpressionGrammar(node: AwaitExpression): void { @@ -33427,7 +33555,7 @@ namespace ts { return getUnaryResultType(operandType); case SyntaxKind.ExclamationToken: checkTruthinessExpression(node.operand); - const facts = getTypeFacts(operandType) & (TypeFacts.Truthy | TypeFacts.Falsy); + const facts = getTypeFacts(operandType, node) & (TypeFacts.Truthy | TypeFacts.Falsy); return facts === TypeFacts.Truthy ? falseType : facts === TypeFacts.Falsy ? trueType : booleanType; @@ -33613,7 +33741,7 @@ namespace ts { function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, rightIsThis?: boolean): Type { const properties = node.properties; - if (strictNullChecks && properties.length === 0) { + if (strictNullChecks(node) && properties.length === 0) { return checkNonNullType(sourceType, node); } for (let i = 0; i < properties.length; i++) { @@ -33676,7 +33804,7 @@ namespace ts { // present (aka the tuple element property). This call also checks that the parentType is in // fact an iterable or array (depending on target language). const possiblyOutOfBoundsType = checkIteratedTypeOrElementType(IterationUse.Destructuring | IterationUse.PossiblyOutOfBounds, sourceType, undefinedType, node) || errorType; - let inBoundsType: Type | undefined = compilerOptions.noUncheckedIndexedAccess ? undefined: possiblyOutOfBoundsType; + let inBoundsType: Type | undefined = getFileLocalCompilerOption(getSourceFileOfNode(node), compilerOptions, "noUncheckedIndexedAccess") ? undefined: possiblyOutOfBoundsType; for (let i = 0; i < elements.length; i++) { let type = possiblyOutOfBoundsType; if (node.elements[i].kind === SyntaxKind.SpreadElement) { @@ -33699,7 +33827,7 @@ namespace ts { // when the element is a SyntaxKind.ElementAccessExpression. const accessFlags = AccessFlags.ExpressionPosition | (hasDefaultValue(element) ? AccessFlags.NoTupleBoundsCheck : 0); const elementType = getIndexedAccessTypeOrUndefined(sourceType, indexType, accessFlags, createSyntheticExpression(element, indexType)) || errorType; - const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined) : elementType; + const assignedType = hasDefaultValue(element) ? getTypeWithFacts(elementType, TypeFacts.NEUndefined, node) : elementType; const type = getFlowTypeOfDestructuring(element, assignedType); return checkDestructuringAssignment(element, type, checkMode); } @@ -33732,9 +33860,9 @@ namespace ts { if (prop.objectAssignmentInitializer) { // In strict null checking mode, if a default value of a non-undefined type is specified, remove // undefined from the final type. - if (strictNullChecks && - !(getTypeFacts(checkExpression(prop.objectAssignmentInitializer)) & TypeFacts.IsUndefined)) { - sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); + if (strictNullChecks(exprOrAssignment) && + !(getTypeFacts(checkExpression(prop.objectAssignmentInitializer), exprOrAssignment) & TypeFacts.IsUndefined)) { + sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined, exprOrAssignment); } checkBinaryLikeExpression(prop.name, prop.equalsToken!, prop.objectAssignmentInitializer, checkMode); } @@ -33748,8 +33876,8 @@ namespace ts { checkBinaryExpression(target as BinaryExpression, checkMode); target = (target as BinaryExpression).left; // A default value is specified, so remove undefined from the final type. - if (strictNullChecks) { - sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); + if (strictNullChecks(exprOrAssignment)) { + sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined, exprOrAssignment); } } if (target.kind === SyntaxKind.ObjectLiteralExpression) { @@ -34185,8 +34313,8 @@ namespace ts { return checkInExpression(left, right, leftType, rightType); case SyntaxKind.AmpersandAmpersandToken: case SyntaxKind.AmpersandAmpersandEqualsToken: { - const resultType = getTypeFacts(leftType) & TypeFacts.Truthy ? - getUnionType([extractDefinitelyFalsyTypes(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : + const resultType = getTypeFacts(leftType, left) & TypeFacts.Truthy ? + getUnionType([extractDefinitelyFalsyTypes(strictNullChecks(left) ? leftType : getBaseTypeOfLiteralType(rightType)), rightType]) : leftType; if (operator === SyntaxKind.AmpersandAmpersandEqualsToken) { checkAssignmentOperator(rightType); @@ -34195,8 +34323,8 @@ namespace ts { } case SyntaxKind.BarBarToken: case SyntaxKind.BarBarEqualsToken: { - const resultType = getTypeFacts(leftType) & TypeFacts.Falsy ? - getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType)), rightType], UnionReduction.Subtype) : + const resultType = getTypeFacts(leftType, left) & TypeFacts.Falsy ? + getUnionType([getNonNullableType(removeDefinitelyFalsyTypes(leftType, left), left), rightType], UnionReduction.Subtype) : leftType; if (operator === SyntaxKind.BarBarEqualsToken) { checkAssignmentOperator(rightType); @@ -34205,8 +34333,8 @@ namespace ts { } case SyntaxKind.QuestionQuestionToken: case SyntaxKind.QuestionQuestionEqualsToken: { - const resultType = getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ? - getUnionType([getNonNullableType(leftType), rightType], UnionReduction.Subtype) : + const resultType = getTypeFacts(leftType, left) & TypeFacts.EQUndefinedOrNull ? + getUnionType([getNonNullableType(leftType, left), rightType], UnionReduction.Subtype) : leftType; if (operator === SyntaxKind.QuestionQuestionEqualsToken) { checkAssignmentOperator(rightType); @@ -34323,7 +34451,7 @@ namespace ts { && (!isIdentifier(left) || unescapeLeadingUnderscores(left.escapedText) !== "exports")) { let headMessage: DiagnosticMessage | undefined; - if (exactOptionalPropertyTypes && isPropertyAccessExpression(left) && maybeTypeOfKind(valueType, TypeFlags.Undefined)) { + if (exactOptionalPropertyTypes(left) && isPropertyAccessExpression(left) && maybeTypeOfKind(valueType, TypeFlags.Undefined)) { const target = getTypeOfPropertyOfType(getTypeOfExpression(left.expression), left.name.escapedText); if (isExactOptionalPropertyMismatch(valueType, target)) { headMessage = Diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target; @@ -34463,7 +34591,7 @@ namespace ts { const signatureYieldType = iterationTypes && iterationTypes.yieldType || anyType; const signatureNextType = iterationTypes && iterationTypes.nextType || anyType; const resolvedSignatureNextType = isAsync ? getAwaitedType(signatureNextType) || anyType : signatureNextType; - const yieldExpressionType = node.expression ? checkExpression(node.expression) : undefinedWideningType; + const yieldExpressionType = node.expression ? checkExpression(node.expression) : getUndefinedWideningType(node); const yieldedType = getYieldedTypeOfYieldExpression(node, yieldExpressionType, resolvedSignatureNextType, isAsync); if (returnType && yieldedType) { checkTypeAssignableToAndOptionallyElaborate(yieldedType, signatureYieldType, node.expression || node, node.expression); @@ -34482,7 +34610,7 @@ namespace ts { if (!type) { type = anyType; addLazyDiagnostic(() => { - if (noImplicitAny && !expressionResultIsUnused(node)) { + if (noImplicitAny(node) && !expressionResultIsUnused(node)) { const contextualType = getContextualType(node, /*contextFlags*/ undefined); if (!contextualType || isTypeAny(contextualType)) { error(node, Diagnostics.yield_expression_implicitly_results_in_an_any_type_because_its_containing_generator_lacks_a_return_type_annotation); @@ -34723,7 +34851,7 @@ namespace ts { if (signature && signature.typeParameters) { const contextualType = getApparentTypeOfContextualType(node as Expression, ContextFlags.NoConstraints); if (contextualType) { - const contextualSignature = getSingleSignature(getNonNullableType(contextualType), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembers*/ false); + const contextualSignature = getSingleSignature(getNonNullableType(contextualType, node), callSignature ? SignatureKind.Call : SignatureKind.Construct, /*allowMembers*/ false); if (contextualSignature && !contextualSignature.typeParameters) { if (checkMode & CheckMode.SkipGenericFunctions) { skippedGenericFunction(node, checkMode); @@ -35013,7 +35141,7 @@ namespace ts { case SyntaxKind.SuperKeyword: return checkSuperExpression(node); case SyntaxKind.NullKeyword: - return nullWideningType; + return getNullWideningType(node); case SyntaxKind.NoSubstitutionTemplateLiteral: case SyntaxKind.StringLiteral: return getFreshTypeOfLiteralType(getStringLiteralType((node as StringLiteralLike).text)); @@ -35088,7 +35216,7 @@ namespace ts { case SyntaxKind.SpreadElement: return checkSpreadExpression(node as SpreadElement, checkMode); case SyntaxKind.OmittedExpression: - return undefinedWideningType; + return getUndefinedWideningType(node); case SyntaxKind.YieldExpression: return checkYieldExpression(node as YieldExpression); case SyntaxKind.SyntheticExpression: @@ -35341,7 +35469,7 @@ namespace ts { function checkSignatureDeclarationDiagnostics() { checkCollisionWithArgumentsInGeneratedCode(node); const returnTypeNode = getEffectiveReturnTypeNode(node); - if (noImplicitAny && !returnTypeNode) { + if (noImplicitAny(node) && !returnTypeNode) { switch (node.kind) { case SyntaxKind.ConstructSignature: error(node, Diagnostics.Construct_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type); @@ -35369,7 +35497,7 @@ namespace ts { const generatorYieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, (functionFlags & FunctionFlags.Async) !== 0) || anyType; const generatorReturnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, (functionFlags & FunctionFlags.Async) !== 0) || generatorYieldType; const generatorNextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, (functionFlags & FunctionFlags.Async) !== 0) || unknownType; - const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async)); + const generatorInstantiation = createGeneratorReturnType(generatorYieldType, generatorReturnType, generatorNextType, !!(functionFlags & FunctionFlags.Async), strictNullChecks(node)); checkTypeAssignableTo(generatorInstantiation, returnType, returnTypeNode); } } @@ -35978,7 +36106,10 @@ namespace ts { } // Check if we're indexing with a numeric type and if either object or index types // is a generic type with a constraint that has a numeric index signature. - const apparentObjectType = getApparentType(objectType); + let apparentObjectType = getApparentType(objectType); + if (!strictNullChecks(accessNode) && apparentObjectType.flags & TypeFlags.Unknown) { + apparentObjectType = emptyObjectType; + } if (getIndexInfoOfType(apparentObjectType, numberType) && isTypeAssignableToKind(indexType, TypeFlags.NumberLike)) { return type; } @@ -36581,7 +36712,7 @@ namespace ts { return undefined; } - const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(candidates, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull); + const onfulfilledParameterType = getTypeWithFacts(getUnionType(map(candidates, getTypeOfFirstParameterOfSignature)), TypeFacts.NEUndefinedOrNull, errorNode); if (isTypeAny(onfulfilledParameterType)) { return undefined; } @@ -36615,14 +36746,14 @@ namespace ts { /** * Determines whether a type is an object with a callable `then` member. */ - function isThenableType(type: Type): boolean { + function isThenableType(type: Type, context: Node | undefined): boolean { if (allTypesAssignableToKind(type, TypeFlags.Primitive | TypeFlags.Never)) { // primitive types cannot be considered "thenable" since they are not objects. return false; } const thenFunction = getTypeOfPropertyOfType(type, "then" as __String); - return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull), SignatureKind.Call).length > 0; + return !!thenFunction && getSignaturesOfType(getTypeWithFacts(thenFunction, TypeFacts.NEUndefinedOrNull, context), SignatureKind.Call).length > 0; } interface AwaitedTypeInstantiation extends Type { @@ -36648,7 +36779,7 @@ namespace ts { type; } - function isAwaitedTypeNeeded(type: Type) { + function isAwaitedTypeNeeded(type: Type, context: Node | undefined) { // If this is already an `Awaited`, we shouldn't wrap it. This helps to avoid `Awaited>` in higher-order. if (isTypeAny(type) || isAwaitedTypeInstantiation(type)) { return false; @@ -36659,7 +36790,7 @@ namespace ts { const baseConstraint = getBaseConstraintOfType(type); // We only need `Awaited` if `T` has no base constraint, or the base constraint of `T` is `any`, `unknown`, `{}`, `object`, // or is promise-like. - if (!baseConstraint || (baseConstraint.flags & TypeFlags.AnyOrUnknown) || isEmptyObjectType(baseConstraint) || isThenableType(baseConstraint)) { + if (!baseConstraint || (baseConstraint.flags & TypeFlags.AnyOrUnknown) || isEmptyObjectType(baseConstraint) || isThenableType(baseConstraint, context)) { return true; } } @@ -36679,7 +36810,7 @@ namespace ts { return undefined; } - function createAwaitedTypeIfNeeded(type: Type): Type { + function createAwaitedTypeIfNeeded(type: Type, context: Node | undefined): Type { // We wrap type `T` in `Awaited` based on the following conditions: // - `T` is not already an `Awaited`, and // - `T` is generic, and @@ -36688,7 +36819,7 @@ namespace ts { // - The base constraint of `T` is `any`, `unknown`, `object`, or `{}`, or // - The base constraint of `T` is an object type with a callable `then` method. - if (isAwaitedTypeNeeded(type)) { + if (isAwaitedTypeNeeded(type, context)) { const awaitedType = tryCreateAwaitedType(type); if (awaitedType) { return awaitedType; @@ -36711,7 +36842,7 @@ namespace ts { */ function getAwaitedType(type: Type, errorNode?: Node, diagnosticMessage?: DiagnosticMessage, arg0?: string | number): Type | undefined { const awaitedType = getAwaitedTypeNoAlias(type, errorNode, diagnosticMessage, arg0); - return awaitedType && createAwaitedTypeIfNeeded(awaitedType); + return awaitedType && createAwaitedTypeIfNeeded(awaitedType, errorNode); } /** @@ -36754,7 +36885,7 @@ namespace ts { } // If `type` is generic and should be wrapped in `Awaited`, return it. - if (isAwaitedTypeNeeded(type)) { + if (isAwaitedTypeNeeded(type, errorNode)) { return typeAsAwaitable.awaitedTypeOfType = type; } @@ -36829,7 +36960,7 @@ namespace ts { // of a runtime problem. If the user wants to return this value from an async // function, they would need to wrap it in some other value. If they want it to // be treated as a promise, they can cast to . - if (isThenableType(type)) { + if (isThenableType(type, errorNode)) { if (errorNode) { Debug.assertIsDefined(diagnosticMessage); let chain: DiagnosticMessageChain | undefined; @@ -37070,7 +37201,7 @@ namespace ts { if (typeNode.kind === SyntaxKind.NeverKeyword) { continue; // Always elide `never` from the union/intersection if possible } - if (!strictNullChecks && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + if (!strictNullChecks(typeNode) && (typeNode.kind === SyntaxKind.LiteralType && (typeNode as LiteralTypeNode).literal.kind === SyntaxKind.NullKeyword || typeNode.kind === SyntaxKind.UndefinedKeyword)) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } const individualEntityName = getEntityNameForDecoratorMetadata(typeNode); @@ -38064,7 +38195,7 @@ namespace ts { const widenedType = getWidenedTypeForVariableLikeDeclaration(node); if (needCheckInitializer) { const initializerType = checkExpressionCached(node.initializer); - if (strictNullChecks && needCheckWidenedType) { + if (strictNullChecks(node) && needCheckWidenedType) { checkNonNullNonVoidType(initializerType, node); } else { @@ -38076,7 +38207,7 @@ namespace ts { if (isArrayBindingPattern(node.name)) { checkIteratedTypeOrElementType(IterationUse.Destructuring, widenedType, undefinedType, node); } - else if (strictNullChecks) { + else if (strictNullChecks(node)) { checkNonNullNonVoidType(widenedType, node); } } @@ -38218,7 +38349,7 @@ namespace ts { } function checkTestingKnownTruthyCallableOrAwaitableType(condExpr: Expression, body?: Statement | Expression) { - if (!strictNullChecks) return; + if (!strictNullChecks(condExpr)) return; helper(condExpr, body); while (isBinaryExpression(condExpr) && condExpr.operatorToken.kind === SyntaxKind.BarBarToken) { @@ -38234,7 +38365,7 @@ namespace ts { if (isModuleExportsAccessExpression(location)) return; const type = checkTruthinessExpression(location); const isPropertyExpressionCast = isPropertyAccessExpression(location) && isTypeAssertion(location.expression); - if (!(getTypeFacts(type) & TypeFacts.Truthy) || isPropertyExpressionCast) return; + if (!(getTypeFacts(type, condExpr) & TypeFacts.Truthy) || isPropertyExpressionCast) return; // While it technically should be invalid for any known-truthy value // to be tested, we de-scope to functions and Promises unreferenced in @@ -38449,7 +38580,12 @@ namespace ts { // Grammar checking checkGrammarForInOrForOfStatement(node); - const rightType = getNonNullableTypeIfNeeded(checkExpression(node.expression)); + const exprType = checkExpression(node.expression); + // Previosuly, in non-strictNullChecks mode, `getNonNullableTypeIfNeeded` internally skipped doing work. + // Since `null` can manifest in non-strict mode, it unconditionally does work now, however at this location that + // difference is visible - an exact `null` is mapped into `never` (and could then issue an error), whereas before it would stay as `null`. + // To preserve that non-erroring behavior, we flag stripping null behind strict here. + const rightType = strictNullChecks(node) ? getNonNullableTypeIfNeeded(exprType, node) : exprType; // TypeScript 1.0 spec (April 2014): 5.4 // In a 'for-in' statement of the form // for (let VarDecl in Expr) Statement @@ -38531,7 +38667,7 @@ namespace ts { const uplevelIteration = languageVersion >= ScriptTarget.ES2015; const downlevelIteration = !uplevelIteration && compilerOptions.downlevelIteration; - const possibleOutOfBounds = compilerOptions.noUncheckedIndexedAccess && !!(use & IterationUse.PossiblyOutOfBounds); + const possibleOutOfBounds = getFileLocalCompilerOption(getSourceFileOfNode(errorNode), compilerOptions, "noUncheckedIndexedAccess") && !!(use & IterationUse.PossiblyOutOfBounds); // Get the iterated type of an `Iterable` or `IterableIterator` only in ES2015 // or higher, when inside of an async generator or for-await-if, or when @@ -38553,7 +38689,7 @@ namespace ts { } } if (iterationTypes || uplevelIteration) { - return possibleOutOfBounds ? includeUndefinedInIndexSignature(iterationTypes && iterationTypes.yieldType) : (iterationTypes && iterationTypes.yieldType); + return possibleOutOfBounds ? includeUndefinedInIndexSignature(iterationTypes && iterationTypes.yieldType, inputType) : (iterationTypes && iterationTypes.yieldType); } } @@ -38590,7 +38726,7 @@ namespace ts { // Now that we've removed all the StringLike types, if no constituents remain, then the entire // arrayOrStringType was a string. if (arrayType.flags & TypeFlags.Never) { - return possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType; + return possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType, globalStringType) : stringType; } } } @@ -38610,20 +38746,20 @@ namespace ts { defaultDiagnostic, typeToString(arrayType)); } - return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType) : stringType : undefined; + return hasStringConstituent ? possibleOutOfBounds ? includeUndefinedInIndexSignature(stringType, globalStringType) : stringType : undefined; } const arrayElementType = getIndexTypeOfType(arrayType, numberType); if (hasStringConstituent && arrayElementType) { // This is just an optimization for the case where arrayOrStringType is string | string[] - if (arrayElementType.flags & TypeFlags.StringLike && !compilerOptions.noUncheckedIndexedAccess) { + if (arrayElementType.flags & TypeFlags.StringLike && !getFileLocalCompilerOption(getSourceFileOfNode(errorNode), compilerOptions, "noUncheckedIndexedAccess")) { return stringType; } return getUnionType(possibleOutOfBounds ? [arrayElementType, stringType, undefinedType] : [arrayElementType, stringType], UnionReduction.Subtype); } - return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType) : arrayElementType; + return (use & IterationUse.PossiblyOutOfBounds) ? includeUndefinedInIndexSignature(arrayElementType, arrayType) : arrayElementType; function getIterationDiagnosticDetails(allowsStrings: boolean, downlevelIteration: boolean | undefined): [error: DiagnosticMessage, maybeMissingAwait: boolean] { if (downlevelIteration) { @@ -39122,7 +39258,7 @@ namespace ts { } const methodType = method && !(methodName === "next" && (method.flags & SymbolFlags.Optional)) - ? methodName === "next" ? getTypeOfSymbol(method) : getTypeWithFacts(getTypeOfSymbol(method), TypeFacts.NEUndefinedOrNull) + ? methodName === "next" ? getTypeOfSymbol(method) : getTypeWithFacts(getTypeOfSymbol(method), TypeFacts.NEUndefinedOrNull, errorNode || method.valueDeclaration) : undefined; if (isTypeAny(methodType)) { @@ -39295,7 +39431,7 @@ namespace ts { const signature = getSignatureFromDeclaration(container); const returnType = getReturnTypeOfSignature(signature); const functionFlags = getFunctionFlags(container); - if (strictNullChecks || node.expression || returnType.flags & TypeFlags.Never) { + if (strictNullChecks(node) || node.expression || returnType.flags & TypeFlags.Never) { const exprType = node.expression ? checkExpressionCached(node.expression) : undefinedType; if (container.kind === SyntaxKind.SetAccessor) { if (node.expression) { @@ -39320,7 +39456,7 @@ namespace ts { } } } - else if (container.kind !== SyntaxKind.Constructor && compilerOptions.noImplicitReturns && !isUnwrappedReturnTypeVoidOrAny(container, returnType)) { + else if (container.kind !== SyntaxKind.Constructor && getFileLocalCompilerOption(getSourceFileOfNode(node), compilerOptions, "noImplicitReturns") && !isUnwrappedReturnTypeVoidOrAny(container, returnType)) { // The function has a return type, but the return statement doesn't have an expression. error(node, Diagnostics.Not_all_code_paths_return_a_value); } @@ -39369,7 +39505,7 @@ namespace ts { addLazyDiagnostic(createLazyCaseClauseDiagnostics(clause)); } forEach(clause.statements, checkSourceElement); - if (compilerOptions.noFallthroughCasesInSwitch && clause.fallthroughFlowNode && isReachableFlowNode(clause.fallthroughFlowNode)) { + if (getFileLocalCompilerOption(getSourceFileOfNode(clause), compilerOptions, "noFallthroughCasesInSwitch") && clause.fallthroughFlowNode && isReachableFlowNode(clause.fallthroughFlowNode)) { error(clause, Diagnostics.Fallthrough_case_in_switch); } @@ -39982,7 +40118,7 @@ namespace ts { ): MemberOverrideStatus { const isJs = isInJSFile(node); const nodeInAmbientContext = !!(node.flags & NodeFlags.Ambient); - if (baseWithThis && (memberHasOverrideModifier || compilerOptions.noImplicitOverride)) { + if (baseWithThis && (memberHasOverrideModifier || getFileLocalCompilerOption(getSourceFileOfNode(node), compilerOptions, "noImplicitOverride"))) { const memberEscapedName = escapeLeadingUnderscores(memberName); const thisType = memberIsStatic ? staticType : typeWithThis; const baseType = memberIsStatic ? baseStaticType : baseWithThis; @@ -40010,7 +40146,7 @@ namespace ts { } return MemberOverrideStatus.HasInvalidOverride; } - else if (prop && baseProp?.declarations && compilerOptions.noImplicitOverride && !nodeInAmbientContext) { + else if (prop && baseProp?.declarations && getFileLocalCompilerOption(getSourceFileOfNode(node), compilerOptions, "noImplicitOverride") && !nodeInAmbientContext) { const baseHasAbstract = some(baseProp.declarations, hasAbstractModifier); if (memberHasOverrideModifier) { return MemberOverrideStatus.Ok; @@ -40259,7 +40395,7 @@ namespace ts { if ((uninitialized as PropertyDeclaration).exclamationToken || !constructor || !isIdentifier(propName) - || !strictNullChecks + || !strictNullChecks(propName) || !isPropertyInitializedInConstructor(propName, type, constructor)) { const errorMessage = Diagnostics.Property_0_will_overwrite_the_base_property_in_1_If_this_is_intentional_add_an_initializer_Otherwise_add_a_declare_modifier_or_remove_the_redundant_declaration; error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType)); @@ -40359,7 +40495,7 @@ namespace ts { } function checkPropertyInitialization(node: ClassLikeDeclaration) { - if (!strictNullChecks || !strictPropertyInitialization || node.flags & NodeFlags.Ambient) { + if (!strictNullChecks(node) || !strictPropertyInitialization(getSourceFileOfNode(node)) || node.flags & NodeFlags.Ambient) { return; } const constructor = findConstructorDeclaration(node); @@ -40396,7 +40532,7 @@ namespace ts { setParent(reference.expression, reference); setParent(reference, staticBlock); reference.flowNode = staticBlock.returnFlowNode; - const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); + const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType, reference)); if (!containsUndefinedType(flowType)) { return true; } @@ -40412,7 +40548,7 @@ namespace ts { setParent(reference.expression, reference); setParent(reference, constructor); reference.flowNode = constructor.returnFlowNode; - const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType)); + const flowType = getFlowTypeOfReference(reference, propType, getOptionalType(propType, propName)); return !containsUndefinedType(flowType); } @@ -41785,7 +41921,7 @@ namespace ts { if (isParameter(parent) && isJSDocFunctionType(parent.parent)) { return createArrayType(type); } - return addOptionality(type); + return addOptionality(type, parent); } // Function and class expression bodies are checked after all statements in the enclosing body. This is @@ -41865,15 +42001,15 @@ namespace ts { tracing?.pop(); } - function unusedIsError(kind: UnusedKind, isAmbient: boolean): boolean { + function unusedIsError(kind: UnusedKind, isAmbient: boolean, file: SourceFile): boolean { if (isAmbient) { return false; } switch (kind) { case UnusedKind.Local: - return !!compilerOptions.noUnusedLocals; + return !!getFileLocalCompilerOption(file, compilerOptions, "noUnusedLocals"); case UnusedKind.Parameter: - return !!compilerOptions.noUnusedParameters; + return !!getFileLocalCompilerOption(file, compilerOptions, "noUnusedParameters"); default: return Debug.assertNever(kind); } @@ -41911,9 +42047,9 @@ namespace ts { addLazyDiagnostic(() => { // This relies on the results of other lazy diagnostics, so must be computed after them - if (!node.isDeclarationFile && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters)) { + if (!node.isDeclarationFile && (getFileLocalCompilerOption(node, compilerOptions, "noUnusedLocals") || getFileLocalCompilerOption(node, compilerOptions, "noUnusedParameters"))) { checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (containingNode, kind, diag) => { - if (!containsParseError(containingNode) && unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient))) { + if (!containsParseError(containingNode) && unusedIsError(kind, !!(containingNode.flags & NodeFlags.Ambient), node)) { diagnostics.add(diag); } }); @@ -42751,8 +42887,9 @@ namespace ts { function getAugmentedPropertiesOfType(type: Type): Symbol[] { type = getApparentType(type); const propsByName = createSymbolTable(getPropertiesOfType(type)); - const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType : - getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType : + const file = type.symbol?.valueDeclaration && getSourceFileOfNode(type.symbol.valueDeclaration); + const functionType = getSignaturesOfType(type, SignatureKind.Call).length ? globalCallableFunctionType(file) : + getSignaturesOfType(type, SignatureKind.Construct).length ? globalNewableFunctionType(file) : undefined; if (functionType) { forEach(getPropertiesOfType(functionType), p => { @@ -43074,7 +43211,7 @@ namespace ts { } function isRequiredInitializedParameter(parameter: ParameterDeclaration | JSDocParameterTag): boolean { - return !!strictNullChecks && + return !!strictNullChecks(parameter) && !isOptionalParameter(parameter) && !isJSDocParameterTag(parameter) && !!parameter.initializer && @@ -43082,7 +43219,7 @@ namespace ts { } function isOptionalUninitializedParameterProperty(parameter: ParameterDeclaration) { - return strictNullChecks && + return strictNullChecks(parameter) && isOptionalParameter(parameter) && !parameter.initializer && hasSyntacticModifier(parameter, ModifierFlags.ParameterPropertyModifier); @@ -43243,7 +43380,7 @@ namespace ts { flags |= NodeBuilderFlags.AllowUniqueESSymbolType; } if (addUndefined) { - type = getOptionalType(type); + type = getOptionalType(type, declarationIn); } return nodeBuilder.typeToTypeNode(type, enclosingDeclaration, flags | NodeBuilderFlags.MultilineObjectLiterals, tracker); } @@ -43658,7 +43795,7 @@ namespace ts { // Setup global builtins addToSymbolTable(globals, builtinGlobals, Diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0); - getSymbolLinks(undefinedSymbol).type = undefinedWideningType; + getSymbolLinks(undefinedSymbol).type = undefinedType; // `checkIdentifier` overrides this with the widening type when relevant getSymbolLinks(argumentsSymbol).type = getGlobalType("IArguments" as __String, /*arity*/ 0, /*reportErrors*/ true); getSymbolLinks(unknownSymbol).type = errorType; getSymbolLinks(globalThisSymbol).type = createObjectType(ObjectFlags.Anonymous, globalThisSymbol); @@ -43667,8 +43804,8 @@ namespace ts { globalArrayType = getGlobalType("Array" as __String, /*arity*/ 1, /*reportErrors*/ true); globalObjectType = getGlobalType("Object" as __String, /*arity*/ 0, /*reportErrors*/ true); globalFunctionType = getGlobalType("Function" as __String, /*arity*/ 0, /*reportErrors*/ true); - globalCallableFunctionType = strictBindCallApply && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; - globalNewableFunctionType = strictBindCallApply && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; + globalCallableFunctionType = (file: SourceFile | undefined) => strictBindCallApply(file) && getGlobalType("CallableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; + globalNewableFunctionType = (file: SourceFile | undefined) => strictBindCallApply(file) && getGlobalType("NewableFunction" as __String, /*arity*/ 0, /*reportErrors*/ true) || globalFunctionType; globalStringType = getGlobalType("String" as __String, /*arity*/ 0, /*reportErrors*/ true); globalNumberType = getGlobalType("Number" as __String, /*arity*/ 0, /*reportErrors*/ true); globalBooleanType = getGlobalType("Boolean" as __String, /*arity*/ 0, /*reportErrors*/ true); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 370461abd8559..c9ccc0ff0dd94 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -4,6 +4,7 @@ namespace ts { name: "compileOnSave", type: "boolean", defaultValueDescription: false, + category: Diagnostics.Editor_Support }; const jsxOptionMap = new Map(getEntries({ @@ -163,6 +164,7 @@ namespace ts { type: "list", element: { name: "excludeDirectory", + category: Diagnostics.Watch_and_Build_Modes, type: "string", isFilePath: true, extraValidation: specToDiagnostic @@ -175,6 +177,7 @@ namespace ts { type: "list", element: { name: "excludeFile", + category: Diagnostics.Watch_and_Build_Modes, type: "string", isFilePath: true, extraValidation: specToDiagnostic @@ -185,7 +188,7 @@ namespace ts { ]; /* @internal */ - export const commonOptionsWithBuild: CommandLineOption[] = [ + export const commonOptionsWithBuild = is()([ { name: "help", shortName: "h", @@ -200,6 +203,7 @@ namespace ts { shortName: "?", type: "boolean", defaultValueDescription: false, + category: Diagnostics.Command_line_Options, }, { name: "watch", @@ -314,10 +318,10 @@ namespace ts { description: Diagnostics.Set_the_language_of_the_messaging_from_TypeScript_This_does_not_affect_emit, defaultValueDescription: Diagnostics.Platform_specific }, - ]; + ] as const); /* @internal */ - export const targetOptionDeclaration: CommandLineOptionOfCustomType = { + export const targetOptionDeclaration = is()({ name: "target", shortName: "t", type: new Map(getEntries({ @@ -343,10 +347,10 @@ namespace ts { category: Diagnostics.Language_and_Environment, description: Diagnostics.Set_the_JavaScript_language_version_for_emitted_JavaScript_and_include_compatible_library_declarations, defaultValueDescription: ScriptTarget.ES3, - }; + } as const); /*@internal*/ - export const moduleOptionDeclaration: CommandLineOptionOfCustomType = { + export const moduleOptionDeclaration = is()({ name: "module", shortName: "m", type: new Map(getEntries({ @@ -371,9 +375,9 @@ namespace ts { category: Diagnostics.Modules, description: Diagnostics.Specify_what_module_code_is_generated, defaultValueDescription: undefined, - }; + }); - const commandOptionsWithoutBuild: CommandLineOption[] = [ + const commandOptionsWithoutBuild = is()([ // CommandLine only options { name: "all", @@ -449,6 +453,7 @@ namespace ts { element: { name: "lib", type: libMap, + category: Diagnostics.Language_and_Environment, defaultValueDescription: undefined, }, affectsProgramStructure: true, @@ -668,6 +673,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Enable_all_strict_type_checking_options, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noImplicitAny", @@ -677,7 +683,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.Enable_error_reporting_for_expressions_and_declarations_with_an_implied_any_type, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, { name: "strictNullChecks", @@ -687,7 +694,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.When_type_checking_take_into_account_null_and_undefined, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, { name: "strictFunctionTypes", @@ -697,7 +705,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.When_assigning_functions_check_to_ensure_parameters_and_the_return_values_are_subtype_compatible, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, { name: "strictBindCallApply", @@ -707,7 +716,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.Check_that_the_arguments_for_bind_call_and_apply_methods_match_the_original_function, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, { name: "strictPropertyInitialization", @@ -717,7 +727,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.Check_for_class_properties_that_are_declared_but_not_set_in_the_constructor, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, { name: "noImplicitThis", @@ -727,7 +738,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.Enable_error_reporting_when_this_is_given_the_type_any, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, { name: "useUnknownInCatchVariables", @@ -738,6 +750,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Default_catch_clause_variables_as_unknown_instead_of_any, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "alwaysStrict", @@ -748,7 +761,8 @@ namespace ts { strictFlag: true, category: Diagnostics.Type_Checking, description: Diagnostics.Ensure_use_strict_is_always_emitted, - defaultValueDescription: Diagnostics.false_unless_strict_is_set + defaultValueDescription: Diagnostics.false_unless_strict_is_set, + allowedAsPragma: true, }, // Additional Checks @@ -760,6 +774,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Enable_error_reporting_when_local_variables_aren_t_read, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noUnusedParameters", @@ -769,6 +784,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Raise_an_error_when_a_function_parameter_isn_t_read, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "exactOptionalPropertyTypes", @@ -778,6 +794,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Interpret_optional_property_types_as_written_rather_than_adding_undefined, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noImplicitReturns", @@ -787,6 +804,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Enable_error_reporting_for_codepaths_that_do_not_explicitly_return_in_a_function, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noFallthroughCasesInSwitch", @@ -797,6 +815,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Enable_error_reporting_for_fallthrough_cases_in_switch_statements, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noUncheckedIndexedAccess", @@ -806,6 +825,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Add_undefined_to_a_type_when_accessed_using_an_index, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noImplicitOverride", @@ -815,6 +835,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Ensure_overriding_members_in_derived_classes_are_marked_with_an_override_modifier, defaultValueDescription: false, + allowedAsPragma: true, }, { name: "noPropertyAccessFromIndexSignature", @@ -825,6 +846,7 @@ namespace ts { category: Diagnostics.Type_Checking, description: Diagnostics.Enforces_using_indexed_accessors_for_keys_declared_using_an_indexed_type, defaultValueDescription: false, + allowedAsPragma: true, }, // Module Resolution @@ -870,6 +892,7 @@ namespace ts { element: { name: "rootDirs", type: "string", + category: Diagnostics.Modules, isFilePath: true }, affectsModuleResolution: true, @@ -884,6 +907,7 @@ namespace ts { element: { name: "typeRoots", type: "string", + category: Diagnostics.Modules, isFilePath: true }, affectsModuleResolution: true, @@ -895,6 +919,7 @@ namespace ts { type: "list", element: { name: "types", + category: Diagnostics.Modules, type: "string" }, affectsProgramStructure: true, @@ -944,6 +969,7 @@ namespace ts { type: "list", element: { name: "suffix", + category: Diagnostics.Modules, type: "string", }, listPreserveFalsyValues: true, @@ -1334,6 +1360,7 @@ namespace ts { isTSConfigOnly: true, element: { name: "plugin", + category: Diagnostics.Editor_Support, type: "object" }, description: Diagnostics.Specify_a_list_of_language_service_plugins_to_include, @@ -1352,37 +1379,129 @@ namespace ts { category: Diagnostics.Language_and_Environment, defaultValueDescription: Diagnostics.auto_Colon_Treat_files_with_imports_exports_import_meta_jsx_with_jsx_Colon_react_jsx_or_esm_format_with_module_Colon_node16_as_modules, } - ]; + ] as const); /* @internal */ - export const optionDeclarations: CommandLineOption[] = [ + export const optionDeclarations = is()([ ...commonOptionsWithBuild, ...commandOptionsWithoutBuild, - ]; + ] as const); + + /* @internal */ + type WithTrue = T extends unknown ? K extends unknown ? T[K] extends true ? T : never : never : never; + + function isAffectsSemanticDiagnosticsOption(option: T): option is WithTrue { + return !!option.affectsSemanticDiagnostics; + } + + /* @internal */ + export const semanticDiagnosticsOptionDeclarations = optionDeclarations.filter(isAffectsSemanticDiagnosticsOption); + + function isAffectsEmitOption(option: T): option is WithTrue { + return !!option.affectsEmit; + } + + /* @internal */ + export const affectsEmitOptionDeclarations = optionDeclarations.filter(isAffectsEmitOption); + + function isAffectsDeclarationPathOption(option: T): option is WithTrue { + return !!option.affectsDeclarationPath; + } + + /* @internal */ + export const affectsDeclarationPathOptionDeclarations = optionDeclarations.filter(isAffectsDeclarationPathOption); + + function isAffectsModuleResolutionOption(option: T): option is WithTrue { + return !!option.affectsModuleResolution; + } /* @internal */ - export const semanticDiagnosticsOptionDeclarations: readonly CommandLineOption[] = - optionDeclarations.filter(option => !!option.affectsSemanticDiagnostics); + export const moduleResolutionOptionDeclarations = optionDeclarations.filter(isAffectsModuleResolutionOption); + + function isSourceFileAffectingOptions(option: T): option is WithTrue { + return !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics; + } /* @internal */ - export const affectsEmitOptionDeclarations: readonly CommandLineOption[] = - optionDeclarations.filter(option => !!option.affectsEmit); + export const sourceFileAffectingCompilerOptions = optionDeclarations.filter(isSourceFileAffectingOptions); + + function isAffectsProgramStructureOption(option: T): option is WithTrue { + return !!option.affectsProgramStructure; + } /* @internal */ - export const affectsDeclarationPathOptionDeclarations: readonly CommandLineOption[] = - optionDeclarations.filter(option => !!option.affectsDeclarationPath); + export const optionsAffectingProgramStructure = optionDeclarations.filter(isAffectsProgramStructureOption); /* @internal */ - export const moduleResolutionOptionDeclarations: readonly CommandLineOption[] = - optionDeclarations.filter(option => !!option.affectsModuleResolution); + export function isStrictOption(option: T): option is WithTrue { + return !!option.strictFlag === true; + } + + function isAllowedAsPragmaOption(option: T): option is WithTrue { + return !!option.allowedAsPragma; + } /* @internal */ - export const sourceFileAffectingCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => - !!option.affectsSourceFile || !!option.affectsModuleResolution || !!option.affectsBindDiagnostics); + export const optionsAllowedAsPragmaOption = optionDeclarations.filter(isAllowedAsPragmaOption); /* @internal */ - export const optionsAffectingProgramStructure: readonly CommandLineOption[] = - optionDeclarations.filter(option => !!option.affectsProgramStructure); + type CompilerOptionsIntoPragmaDefinitions = UnionToIntersection}`]: { readonly kind: PragmaKindFlags, readonly args: readonly [{ readonly name: "value", readonly optional: true }] }} : never>; + + function convertCompilerOptionsIntoPragmasSpecs(options: T): CompilerOptionsIntoPragmaDefinitions { + const result = {} as CompilerOptionsIntoPragmaDefinitions; + for (const elem of options) { + result[`ts-${elem.name.toLowerCase()}` as keyof typeof result] = { + args: [{ name: "value", optional: true }], + kind: PragmaKindFlags.SingleLine | PragmaKindFlags.MultiLine + } as any; + } + return result; + } + + /* @internal */ + export const commentPragmas = { + "reference": { + args: [ + { name: "types", optional: true, captureSpan: true }, + { name: "lib", optional: true, captureSpan: true }, + { name: "path", optional: true, captureSpan: true }, + { name: "no-default-lib", optional: true }, + { name: "resolution-mode", optional: true } + ], + kind: PragmaKindFlags.TripleSlashXML + }, + "amd-dependency": { + args: [{ name: "path" }, { name: "name", optional: true }], + kind: PragmaKindFlags.TripleSlashXML + }, + "amd-module": { + args: [{ name: "name" }], + kind: PragmaKindFlags.TripleSlashXML + }, + "ts-check": { + kind: PragmaKindFlags.SingleLine + }, + "ts-nocheck": { + kind: PragmaKindFlags.SingleLine + }, + "jsx": { + args: [{ name: "factory" }], + kind: PragmaKindFlags.MultiLine + }, + "jsxfrag": { + args: [{ name: "factory" }], + kind: PragmaKindFlags.MultiLine + }, + "jsximportsource": { + args: [{ name: "factory" }], + kind: PragmaKindFlags.MultiLine + }, + "jsxruntime": { + args: [{ name: "factory" }], + kind: PragmaKindFlags.MultiLine + }, + ...convertCompilerOptionsIntoPragmasSpecs(optionsAllowedAsPragmaOption) + } as const; /* @internal */ export const transpileOptionValueCompilerOptions: readonly CommandLineOption[] = optionDeclarations.filter(option => @@ -1438,11 +1557,13 @@ namespace ts { */ name: "enableAutoDiscovery", type: "boolean", + category: Diagnostics.File_Management, defaultValueDescription: false, }, { name: "enable", type: "boolean", + category: Diagnostics.File_Management, defaultValueDescription: false, }, { @@ -1450,20 +1571,25 @@ namespace ts { type: "list", element: { name: "include", + category: Diagnostics.File_Management, type: "string" - } + }, + category: Diagnostics.File_Management, }, { name: "exclude", type: "list", element: { name: "exclude", + category: Diagnostics.File_Management, type: "string" - } + }, + category: Diagnostics.File_Management, }, { name: "disableFilenameBasedTypeAcquisition", type: "boolean", + category: Diagnostics.File_Management, defaultValueDescription: false, }, ]; @@ -1670,10 +1796,11 @@ namespace ts { } } - function parseOptionValue( + /* @internal */ + export function parseOptionValue( args: readonly string[], i: number, - diagnostics: ParseCommandLineWorkerDiagnostics, + diagnostics: ParseCommandLineWorkerDiagnostics | undefined, opt: CommandLineOption, options: OptionsBase, errors: Diagnostic[] @@ -1701,7 +1828,7 @@ namespace ts { } else { // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). - if (!args[i] && opt.type !== "boolean") { + if (!args[i] && opt.type !== "boolean" && diagnostics) { errors.push(createCompilerDiagnostic(diagnostics.optionTypeMismatchDiagnostic, opt.name, getCompilerOptionValueTypeString(opt))); } @@ -1977,30 +2104,35 @@ namespace ts { _tsconfigRootOptions = { name: undefined!, // should never be needed since this is root type: "object", + category: Diagnostics.Command_line_Options, elementOptions: commandLineOptionsToMap([ { name: "compilerOptions", type: "object", elementOptions: getCommandLineCompilerOptionsMap(), extraKeyDiagnostics: compilerOptionsDidYouMeanDiagnostics, + category: Diagnostics.Command_line_Options, }, { name: "watchOptions", type: "object", elementOptions: getCommandLineWatchOptionsMap(), extraKeyDiagnostics: watchOptionsDidYouMeanDiagnostics, + category: Diagnostics.Command_line_Options, }, { name: "typingOptions", type: "object", elementOptions: getCommandLineTypeAcquisitionMap(), extraKeyDiagnostics: typeAcquisitionDidYouMeanDiagnostics, + category: Diagnostics.Command_line_Options, }, { name: "typeAcquisition", type: "object", elementOptions: getCommandLineTypeAcquisitionMap(), - extraKeyDiagnostics: typeAcquisitionDidYouMeanDiagnostics + extraKeyDiagnostics: typeAcquisitionDidYouMeanDiagnostics, + category: Diagnostics.Command_line_Options, }, { name: "extends", @@ -2012,6 +2144,7 @@ namespace ts { type: "list", element: { name: "references", + category: Diagnostics.Projects, type: "object" }, category: Diagnostics.Projects, @@ -2021,6 +2154,7 @@ namespace ts { type: "list", element: { name: "files", + category: Diagnostics.File_Management, type: "string" }, category: Diagnostics.File_Management, @@ -2030,6 +2164,7 @@ namespace ts { type: "list", element: { name: "include", + category: Diagnostics.File_Management, type: "string" }, category: Diagnostics.File_Management, @@ -2040,6 +2175,7 @@ namespace ts { type: "list", element: { name: "exclude", + category: Diagnostics.File_Management, type: "string" }, category: Diagnostics.File_Management, @@ -2583,7 +2719,7 @@ namespace ts { const { category } = option; if (isAllowedOptionForOutput(option)) { - categorizedOptions.add(getLocaleSpecificMessage(category!), option); + categorizedOptions.add(getLocaleSpecificMessage(category), option); } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 24e69cbe33e2d..b1234b664d733 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -2104,7 +2104,7 @@ namespace ts { * (0.4 allows 1 substitution/transposition for every 5 characters, * and 1 insertion/deletion at 3 characters) */ - export function getSpellingSuggestion(name: string, candidates: T[], getName: (candidate: T) => string | undefined): T | undefined { + export function getSpellingSuggestion(name: string, candidates: readonly T[], getName: (candidate: T) => string | undefined): T | undefined { const maximumLengthDifference = Math.max(2, Math.floor(name.length * 0.34)); let bestDistance = Math.floor(name.length * 0.4) + 1; // If the best result is worse than this, don't bother. let bestCandidate: T | undefined; @@ -2510,4 +2510,8 @@ namespace ts { } return s.slice(0, end + 1); } + + export function is(): (arg: U) => U { + return identity; + } } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f9aa3e57498ed..9cf75cf89d285 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -9516,6 +9516,7 @@ namespace ts { export interface PragmaContext { languageVersion: ScriptTarget; pragmas?: PragmaMap; + localOptions?: CompilerOptions; checkJsDirective?: CheckJsDirective; referencedFiles: FileReference[]; typeReferenceDirectives: FileReference[]; @@ -9523,6 +9524,7 @@ namespace ts { amdDependencies: AmdDependency[]; hasNoDefaultLib?: boolean; moduleName?: string; + } function parseResolutionMode(mode: string | undefined, pos: number, end: number, reportDiagnostic: PragmaDiagnosticReporter): ModuleKind.ESNext | ModuleKind.CommonJS | undefined { @@ -9639,12 +9641,54 @@ namespace ts { }); break; } + case "ts-strict": + case "ts-noimplicitany": + case "ts-strictnullchecks": + case "ts-strictfunctiontypes": + case "ts-strictbindcallapply": + case "ts-noimplicitthis": + case "ts-strictpropertyinitialization": + case "ts-useunknownincatchvariables": + case "ts-alwaysstrict": + case "ts-nounusedlocals": + case "ts-nounusedparameters": + case "ts-exactoptionalpropertytypes": + case "ts-nopropertyaccessfromindexsignature": + case "ts-noimplicitreturns": + case "ts-nofallthroughcasesinswitch": + case "ts-nouncheckedindexedaccess": + case "ts-noimplicitoverride": { + const optName = key.slice(3); + const opt = find(optionsAllowedAsPragmaOption, o => o.name.toLowerCase() === optName)!; + const entry = (isArray(entryOrList) ? last(entryOrList) : entryOrList); + const unparsedValue = (entry.arguments as PragmaArgumentType<`ts-${Lowercase}`>).value; + const optContainer: OptionsBase = {}; + const errors: Diagnostic[] = []; + const parsedValue = unparsedValue === undefined ? true : (parseOptionValue([unparsedValue], 0, /*diagnostics*/ undefined, opt, optContainer, errors), optContainer[opt.name]); + if (unparsedValue === undefined && opt.type !== "boolean") { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, optName)); + } + for (const err of errors) { + reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, { + category: err.category, + code: err.code, + message: err.messageText as string, + reportsDeprecated: err.reportsDeprecated, + reportsUnnecessary: err.reportsUnnecessary, + key: err.messageText as string + }); + } + if (!length(errors)) { + (context.localOptions ??= {})[opt.name as string] = parsedValue; + } + break; + } case "jsx": case "jsxfrag": case "jsximportsource": case "jsxruntime": return; // Accessed directly - default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future? + default: Debug.assertNever(key, `Unhandled pragma kind: ${key}`); } }); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 6de1792d361f7..df885f8ed6679 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -3259,7 +3259,7 @@ namespace ts { // Don't add the file if it has a bad extension (e.g. 'tsx' if we don't have '--allowJs') // This may still end up being an untyped module -- the file won't be included but imports will be allowed. const shouldAddFile = resolvedFileName - && !getResolutionDiagnostic(optionsForFile, resolution) + && !getResolutionDiagnostic(file, optionsForFile, resolution) && !optionsForFile.noResolve && index < file.imports.length && !elideImport @@ -3361,10 +3361,10 @@ namespace ts { } function verifyCompilerOptions() { - if (options.strictPropertyInitialization && !getStrictOptionValue(options, "strictNullChecks")) { + if (options.strictPropertyInitialization && !getStrictOptionValue(/*file*/ undefined, options, "strictNullChecks")) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "strictPropertyInitialization", "strictNullChecks"); } - if (options.exactOptionalPropertyTypes && !getStrictOptionValue(options, "strictNullChecks")) { + if (options.exactOptionalPropertyTypes && !getStrictOptionValue(/*file*/ undefined, options, "strictNullChecks")) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "exactOptionalPropertyTypes", "strictNullChecks"); } @@ -3493,7 +3493,7 @@ namespace ts { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"); } - if (options.noImplicitUseStrict && getStrictOptionValue(options, "alwaysStrict")) { + if (options.noImplicitUseStrict && getStrictOptionValue(/*file*/ undefined, options, "alwaysStrict")) { createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noImplicitUseStrict", "alwaysStrict"); } @@ -4293,7 +4293,7 @@ namespace ts { * The DiagnosticMessage's parameters are the imported module name, and the filename it resolved to. * This returns a diagnostic even if the module will be an untyped module. */ - export function getResolutionDiagnostic(options: CompilerOptions, { extension }: ResolvedModuleFull): DiagnosticMessage | undefined { + export function getResolutionDiagnostic(file: SourceFile, options: CompilerOptions, { extension }: ResolvedModuleFull): DiagnosticMessage | undefined { switch (extension) { case Extension.Ts: case Extension.Dts: @@ -4313,7 +4313,7 @@ namespace ts { return options.jsx ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_jsx_is_not_set; } function needAllowJs() { - return getAllowJSCompilerOption(options) || !getStrictOptionValue(options, "noImplicitAny") ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; + return getAllowJSCompilerOption(options) || !getStrictOptionValue(file, options, "noImplicitAny") ? undefined : Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type; } function needResolveJsonModule() { return options.resolveJsonModule ? undefined : Diagnostics.Module_0_was_resolved_to_1_but_resolveJsonModule_is_not_used; diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 9b3b8e6ee1283..2e5dab06c085a 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -93,7 +93,7 @@ namespace ts { startLexicalEnvironment(); const statements: Statement[] = []; - const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); + const ensureUseStrict = getStrictOptionValue(node, compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict && !isJsonSourceFile(node), topLevelVisitor); if (shouldEmitUnderscoreUnderscoreESModule()) { diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 869c1c18d7245..0f6c7aa9dad72 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -222,7 +222,7 @@ namespace ts { startLexicalEnvironment(); // Add any prologue directives. - const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); + const ensureUseStrict = getStrictOptionValue(node, compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile)); const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict, topLevelVisitor); // var __moduleName = context_1 && context_1.id; diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 52242ccba4582..21747203d0f11 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -574,7 +574,7 @@ namespace ts { } function visitSourceFile(node: SourceFile) { - const alwaysStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") && + const alwaysStrict = getStrictOptionValue(node, compilerOptions, "alwaysStrict") && !(isExternalModule(node) && moduleKind >= ModuleKind.ES2015) && !isJsonSourceFile(node); diff --git a/src/compiler/transformers/typeSerializer.ts b/src/compiler/transformers/typeSerializer.ts index 9504bcde8864d..ceff03655be72 100644 --- a/src/compiler/transformers/typeSerializer.ts +++ b/src/compiler/transformers/typeSerializer.ts @@ -63,7 +63,6 @@ namespace ts { const resolver = context.getEmitResolver(); const compilerOptions = context.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); - const strictNullChecks = getStrictOptionValue(compilerOptions, "strictNullChecks"); let currentLexicalScope: SourceFile | CaseBlock | ModuleBlock | Block; let currentNameScope: ClassLikeDeclaration | undefined; @@ -344,7 +343,7 @@ namespace ts { return factory.createIdentifier("Object"); // Reduce to `any` in a union or intersection } - if (!strictNullChecks && ((isLiteralTypeNode(typeNode) && typeNode.literal.kind === SyntaxKind.NullKeyword) || typeNode.kind === SyntaxKind.UndefinedKeyword)) { + if (!getStrictOptionValue(getSourceFileOfNode(currentLexicalScope), compilerOptions, "strictNullChecks") && ((isLiteralTypeNode(typeNode) && typeNode.literal.kind === SyntaxKind.NullKeyword) || typeNode.kind === SyntaxKind.UndefinedKeyword)) { continue; // Elide null and undefined from unions for metadata, just like what we did prior to the implementation of strict null checks } diff --git a/src/compiler/tsbuildPublic.ts b/src/compiler/tsbuildPublic.ts index 23bcc47607a80..8d30f913c444b 100644 --- a/src/compiler/tsbuildPublic.ts +++ b/src/compiler/tsbuildPublic.ts @@ -188,7 +188,7 @@ namespace ts { function getCompilerOptionsOfBuildOptions(buildOptions: BuildOptions): CompilerOptions { const result = {} as CompilerOptions; commonOptionsWithBuild.forEach(option => { - if (hasProperty(buildOptions, option.name)) result[option.name] = buildOptions[option.name]; + if (hasProperty(buildOptions, option.name)) result[option.name as string] = buildOptions[option.name]; }); return result; } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f93f36c369157..fe2c0dd5c32f5 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3857,6 +3857,7 @@ namespace ts { /* @internal */ checkJsDirective?: CheckJsDirective; /* @internal */ version: string; /* @internal */ pragmas: ReadonlyPragmaMap; + /* @internal */ localOptions?: CompilerOptions; /* @internal */ localJsxNamespace?: __String; /* @internal */ localJsxFragmentNamespace?: __String; /* @internal */ localJsxFactory?: EntityName; @@ -4385,9 +4386,9 @@ namespace ts { /* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type; /* @internal */ getParameterIdentifierNameAtPosition(signature: Signature, parameterIndex: number): [parameterName: __String, isRestParameter: boolean] | undefined; getNullableType(type: Type, flags: TypeFlags): Type; - getNonNullableType(type: Type): Type; + getNonNullableType(type: Type, context?: Node | undefined): Type; /* @internal */ getNonOptionalType(type: Type): Type; - /* @internal */ isNullableType(type: Type): boolean; + /* @internal */ isNullableType(type: Type, context?: Node | undefined): boolean; getTypeArguments(type: TypeReference): readonly Type[]; // TODO: GH#18217 `xToDeclaration` calls are frequently asserted as defined. @@ -4519,8 +4520,8 @@ namespace ts { /* @internal */ getFalseType(fresh?: boolean): Type; /* @internal */ getTrueType(fresh?: boolean): Type; /* @internal */ getVoidType(): Type; - /* @internal */ getUndefinedType(): Type; - /* @internal */ getNullType(): Type; + /* @internal */ getUndefinedType(widening?: boolean): Type; + /* @internal */ getNullType(widening?: boolean): Type; /* @internal */ getESSymbolType(): Type; /* @internal */ getNeverType(): Type; /* @internal */ getOptionalType(): Type; @@ -5336,6 +5337,7 @@ namespace ts { skipDirectInference?: true; // Flag set by the API `getContextualType` call on a node when `Completions` is passed to force the checker to skip making inferences to a node's type declarationRequiresScopeChange?: boolean; // Set by `useOuterVariableScopeInParameter` in checker when downlevel emit would change the name resolution scope inside of a parameter. serializedTypes?: ESMap; // Collection of types serialized at this location + sourceFile?: SourceFile | undefined; // Cached lookup result of `getSourceFileOfNode` } export const enum TypeFlags { @@ -5414,12 +5416,12 @@ namespace ts { Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive, // The following flags are aggregated during union and intersection type construction /* @internal */ - IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral, + IncludesMask = Any | Unknown | Primitive | Never | Object | Union | Intersection | NonPrimitive | TemplateLiteral | Index | StringMapping, // The following flags are used for different purposes during union and intersection type construction /* @internal */ IncludesMissingType = TypeParameter, /* @internal */ - IncludesNonWideningType = Index, + IncludesNonWideningType = 1 << 29, // repurpose for true typeflag when needed /* @internal */ IncludesWildcard = IndexedAccess, /* @internal */ @@ -6605,7 +6607,7 @@ namespace ts { isTSConfigOnly?: boolean; // True if option can only be specified via tsconfig.json file isCommandLineOnly?: boolean; showInSimplifiedHelpView?: boolean; - category?: DiagnosticMessage; + category: DiagnosticMessage; strictFlag?: true; // true if the option is one of the flag under strict affectsSourceFile?: true; // true if we should recreate SourceFiles after this option changes affectsModuleResolution?: true; // currently same effect as `affectsSourceFile` @@ -6618,6 +6620,7 @@ namespace ts { affectsBundleEmitBuildInfo?: true; // true if this options should be emitted in buildInfo with --out transpileOptionValue?: boolean | undefined; // If set this means that the option should be set to this value when transpiling extraValidation?: (value: CompilerOptionsValue) => [DiagnosticMessage, ...string[]] | undefined; // Additional validation to be performed for the value to be valid + allowedAsPragma?: boolean; // True if this option is allowed as a comment pragma to be toggled on a per-file basis (eg, `// @ts-strict false`) } /* @internal */ @@ -6653,7 +6656,7 @@ namespace ts { /* @internal */ export interface DidYouMeanOptionsDiagnostics { alternateMode?: AlternateModeDiagnostics; - optionDeclarations: CommandLineOption[]; + optionDeclarations: readonly CommandLineOption[]; unknownOptionDiagnostic: DiagnosticMessage, unknownDidYouMeanDiagnostic: DiagnosticMessage, } @@ -8864,52 +8867,6 @@ namespace ts { kind?: PragmaKindFlags; } - // While not strictly a type, this is here because `PragmaMap` needs to be here to be used with `SourceFile`, and we don't - // fancy effectively defining it twice, once in value-space and once in type-space - /* @internal */ - export const commentPragmas = { - "reference": { - args: [ - { name: "types", optional: true, captureSpan: true }, - { name: "lib", optional: true, captureSpan: true }, - { name: "path", optional: true, captureSpan: true }, - { name: "no-default-lib", optional: true }, - { name: "resolution-mode", optional: true } - ], - kind: PragmaKindFlags.TripleSlashXML - }, - "amd-dependency": { - args: [{ name: "path" }, { name: "name", optional: true }], - kind: PragmaKindFlags.TripleSlashXML - }, - "amd-module": { - args: [{ name: "name" }], - kind: PragmaKindFlags.TripleSlashXML - }, - "ts-check": { - kind: PragmaKindFlags.SingleLine - }, - "ts-nocheck": { - kind: PragmaKindFlags.SingleLine - }, - "jsx": { - args: [{ name: "factory" }], - kind: PragmaKindFlags.MultiLine - }, - "jsxfrag": { - args: [{ name: "factory" }], - kind: PragmaKindFlags.MultiLine - }, - "jsximportsource": { - args: [{ name: "factory" }], - kind: PragmaKindFlags.MultiLine - }, - "jsxruntime": { - args: [{ name: "factory" }], - kind: PragmaKindFlags.MultiLine - }, - } as const; - /* @internal */ type PragmaArgTypeMaybeCapture = TDesc extends {captureSpan: true} ? {value: string, pos: number, end: number} : string; @@ -8920,7 +8877,7 @@ namespace ts { : {[K in TName]: PragmaArgTypeMaybeCapture}; /* @internal */ - type UnionToIntersection = + export type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; /* @internal */ @@ -8932,7 +8889,7 @@ namespace ts { * Maps a pragma definition into the desired shape for its arguments object */ /* @internal */ - type PragmaArgumentType = + export type PragmaArgumentType = ConcretePragmaSpecs[KPrag] extends { args: readonly PragmaArgumentSpecification[] } ? UnionToIntersection> : never; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 4ec193839e680..d2f4dee38ec1c 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -835,7 +835,7 @@ namespace ts { return false; } // If `alwaysStrict` is set, then treat the file as strict. - if (getStrictOptionValue(compilerOptions, "alwaysStrict")) { + if (getStrictOptionValue(node, compilerOptions, "alwaysStrict")) { return true; } // Starting with a "use strict" directive indicates the file is strict. @@ -6450,6 +6450,17 @@ namespace ts { return !!(options.incremental || options.composite); } + export type FileLocalOptionName = (typeof optionsAllowedAsPragmaOption)[number]["name"]; + + export function getFileLocalCompilerOption(file: SourceFile | undefined, opts: CompilerOptions, name: T, isStrictFlag?: boolean): CompilerOptions[T] { + const localStrictValue = (file?.localOptions && hasProperty(file.localOptions, "strict")) ? file.localOptions.strict : undefined; + const strict = localStrictValue === undefined ? opts.strict : localStrictValue; + if (file?.localOptions && hasProperty(file.localOptions, name)) { + return file.localOptions[name] !== undefined ? file.localOptions[name] : opts[name] !== undefined ? opts[name] : isStrictFlag ? strict : undefined; + } + return opts[name] !== undefined ? opts[name] : isStrictFlag ? strict : undefined; + } + export type StrictOptionName = | "noImplicitAny" | "noImplicitThis" @@ -6461,8 +6472,8 @@ namespace ts { | "useUnknownInCatchVariables" ; - export function getStrictOptionValue(compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { - return compilerOptions[flag] === undefined ? !!compilerOptions.strict : !!compilerOptions[flag]; + export function getStrictOptionValue(file: SourceFile | undefined, compilerOptions: CompilerOptions, flag: StrictOptionName): boolean { + return !!getFileLocalCompilerOption(file, compilerOptions, flag, /*isStrictFlag*/ true); } export function getAllowJSCompilerOption(compilerOptions: CompilerOptions): boolean { @@ -6486,7 +6497,7 @@ namespace ts { } export function getCompilerOptionValue(options: CompilerOptions, option: CommandLineOption): unknown { - return option.strictFlag ? getStrictOptionValue(options, option.name as StrictOptionName) : options[option.name]; + return option.strictFlag ? options[option.name] === undefined ? !!options.strict : !!options[option.name] : options[option.name]; } export function getJSXTransformEnabled(options: CompilerOptions): boolean { diff --git a/src/executeCommandLine/executeCommandLine.ts b/src/executeCommandLine/executeCommandLine.ts index 68d2e51e9d4eb..6a77538434991 100644 --- a/src/executeCommandLine/executeCommandLine.ts +++ b/src/executeCommandLine/executeCommandLine.ts @@ -82,7 +82,7 @@ namespace ts { // Sort our options by their names, (e.g. "--noImplicitAny" comes before "--watch") return !!commandLine.options.all ? sort(optionDeclarations, (a, b) => compareStringsCaseInsensitive(a.name, b.name)) : - filter(optionDeclarations.slice(), v => !!v.showInSimplifiedHelpView); + filter(optionDeclarations.slice(), v => !!(v as CommandLineOption).showInSimplifiedHelpView); } function printVersion(sys: System) { diff --git a/src/harness/harnessIO.ts b/src/harness/harnessIO.ts index 2786498d41e1f..025ee7c9a9341 100644 --- a/src/harness/harnessIO.ts +++ b/src/harness/harnessIO.ts @@ -304,21 +304,21 @@ namespace Harness { // Additional options not already in ts.optionDeclarations const harnessOptionDeclarations: ts.CommandLineOption[] = [ - { name: "allowNonTsExtensions", type: "boolean", defaultValueDescription: false }, - { name: "useCaseSensitiveFileNames", type: "boolean", defaultValueDescription: false }, - { name: "baselineFile", type: "string" }, - { name: "includeBuiltFile", type: "string" }, - { name: "fileName", type: "string" }, - { name: "libFiles", type: "string" }, - { name: "noErrorTruncation", type: "boolean", defaultValueDescription: false }, - { name: "suppressOutputPathCheck", type: "boolean", defaultValueDescription: false }, - { name: "noImplicitReferences", type: "boolean", defaultValueDescription: false }, - { name: "currentDirectory", type: "string" }, - { name: "symlink", type: "string" }, - { name: "link", type: "string" }, - { name: "noTypesAndSymbols", type: "boolean", defaultValueDescription: false }, + { name: "allowNonTsExtensions", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "useCaseSensitiveFileNames", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "baselineFile", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "includeBuiltFile", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "fileName", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "libFiles", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "noErrorTruncation", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "suppressOutputPathCheck", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "noImplicitReferences", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "currentDirectory", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "symlink", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "link", type: "string", category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, + { name: "noTypesAndSymbols", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, // Emitted js baseline will print full paths for every output file - { name: "fullEmitPaths", type: "boolean", defaultValueDescription: false }, + { name: "fullEmitPaths", type: "boolean", defaultValueDescription: false, category: ts.Diagnostics.ALL_COMPILER_OPTIONS }, ]; let optionsIndex: ts.ESMap; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 6cca27c033587..b95b8ef2a9430 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -157,7 +157,7 @@ namespace ts.server { [name: string]: { match: RegExp, exclude?: (string | number)[][], types?: string[] }; } - function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: CommandLineOption[]): ESMap> { + function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: readonly CommandLineOption[]): ESMap> { const map = new Map>(); for (const option of commandLineOptions) { if (typeof option.type === "object") { diff --git a/src/services/codefixes/inferFromUsage.ts b/src/services/codefixes/inferFromUsage.ts index 643d64f2c21af..0498476eff30b 100644 --- a/src/services/codefixes/inferFromUsage.ts +++ b/src/services/codefixes/inferFromUsage.ts @@ -113,6 +113,7 @@ namespace ts.codefix { return undefined; } + const isStrictNullChecks = getStrictOptionValue(sourceFile, program.getCompilerOptions(), "strictNullChecks"); const { parent } = token; const importAdder = createImportAdder(sourceFile, program, preferences, host); errorCode = mapSuggestionDiagnostic(errorCode); @@ -121,12 +122,12 @@ namespace ts.codefix { case Diagnostics.Member_0_implicitly_has_an_1_type.code: case Diagnostics.Variable_0_implicitly_has_type_1_in_some_locations_where_its_type_cannot_be_determined.code: if ((isVariableDeclaration(parent) && markSeen(parent)) || isPropertyDeclaration(parent) || isPropertySignature(parent)) { // handle bad location - annotateVariableDeclaration(changes, importAdder, sourceFile, parent, program, host, cancellationToken); + annotateVariableDeclaration(changes, importAdder, sourceFile, parent, program, host, cancellationToken, isStrictNullChecks); importAdder.writeFixes(changes); return parent; } if (isPropertyAccessExpression(parent)) { - const type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken); + const type = inferTypeForVariableFromUsage(parent.name, program, cancellationToken, isStrictNullChecks); const typeNode = getTypeNodeIfAccessible(type, parent, program, host); if (typeNode) { // Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags @@ -141,7 +142,7 @@ namespace ts.codefix { case Diagnostics.Variable_0_implicitly_has_an_1_type.code: { const symbol = program.getTypeChecker().getSymbolAtLocation(token); if (symbol && symbol.valueDeclaration && isVariableDeclaration(symbol.valueDeclaration) && markSeen(symbol.valueDeclaration)) { - annotateVariableDeclaration(changes, importAdder, getSourceFileOfNode(symbol.valueDeclaration), symbol.valueDeclaration, program, host, cancellationToken); + annotateVariableDeclaration(changes, importAdder, getSourceFileOfNode(symbol.valueDeclaration), symbol.valueDeclaration, program, host, cancellationToken, isStrictNullChecks); importAdder.writeFixes(changes); return symbol.valueDeclaration; } @@ -159,7 +160,7 @@ namespace ts.codefix { // Parameter declarations case Diagnostics.Parameter_0_implicitly_has_an_1_type.code: if (isSetAccessorDeclaration(containingFunction)) { - annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken); + annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken, isStrictNullChecks); declaration = containingFunction; break; } @@ -167,7 +168,7 @@ namespace ts.codefix { case Diagnostics.Rest_parameter_0_implicitly_has_an_any_type.code: if (markSeen(containingFunction)) { const param = cast(parent, isParameter); - annotateParameters(changes, importAdder, sourceFile, param, containingFunction, program, host, cancellationToken); + annotateParameters(changes, importAdder, sourceFile, param, containingFunction, program, host, cancellationToken, isStrictNullChecks); declaration = param; } break; @@ -176,7 +177,7 @@ namespace ts.codefix { case Diagnostics.Property_0_implicitly_has_type_any_because_its_get_accessor_lacks_a_return_type_annotation.code: case Diagnostics._0_which_lacks_return_type_annotation_implicitly_has_an_1_return_type.code: if (isGetAccessorDeclaration(containingFunction) && isIdentifier(containingFunction.name)) { - annotate(changes, importAdder, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken), program, host); + annotate(changes, importAdder, sourceFile, containingFunction, inferTypeForVariableFromUsage(containingFunction.name, program, cancellationToken, isStrictNullChecks), program, host); declaration = containingFunction; } break; @@ -184,7 +185,7 @@ namespace ts.codefix { // Set Accessor declarations case Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_parameter_type_annotation.code: if (isSetAccessorDeclaration(containingFunction)) { - annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken); + annotateSetAccessor(changes, importAdder, sourceFile, containingFunction, program, host, cancellationToken, isStrictNullChecks); declaration = containingFunction; } break; @@ -192,7 +193,7 @@ namespace ts.codefix { // Function 'this' case Diagnostics.this_implicitly_has_type_any_because_it_does_not_have_a_type_annotation.code: if (textChanges.isThisTypeAnnotatable(containingFunction) && markSeen(containingFunction)) { - annotateThis(changes, sourceFile, containingFunction, program, host, cancellationToken); + annotateThis(changes, sourceFile, containingFunction, program, host, cancellationToken, isStrictNullChecks); declaration = containingFunction; } break; @@ -213,9 +214,10 @@ namespace ts.codefix { program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, + isStrictNullChecks: boolean, ): void { if (isIdentifier(declaration.name)) { - annotate(changes, importAdder, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken), program, host); + annotate(changes, importAdder, sourceFile, declaration, inferTypeForVariableFromUsage(declaration.name, program, cancellationToken, isStrictNullChecks), program, host); } } @@ -228,12 +230,13 @@ namespace ts.codefix { program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, + isStrictNullChecks: boolean, ): void { if (!isIdentifier(parameterDeclaration.name)) { return; } - const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken); + const parameterInferences = inferTypeForParametersFromUsage(containingFunction, sourceFile, program, cancellationToken, isStrictNullChecks); Debug.assert(containingFunction.parameters.length === parameterInferences.length, "Parameter count and inference count should match"); if (isInJSFile(containingFunction)) { @@ -251,12 +254,12 @@ namespace ts.codefix { } } - function annotateThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: textChanges.ThisTypeAnnotatable, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken) { + function annotateThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: textChanges.ThisTypeAnnotatable, program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, isStrictNullChecks: boolean) { const references = getFunctionReferences(containingFunction, sourceFile, program, cancellationToken); if (!references || !references.length) { return; } - const thisInference = inferTypeFromReferences(program, references, cancellationToken).thisParameter(); + const thisInference = inferTypeFromReferences(program, references, cancellationToken, isStrictNullChecks).thisParameter(); const typeNode = getTypeNodeIfAccessible(thisInference, containingFunction, program, host); if (!typeNode) { return; @@ -284,13 +287,13 @@ namespace ts.codefix { program: Program, host: LanguageServiceHost, cancellationToken: CancellationToken, - + isStrictNullChecks: boolean, ): void { const param = firstOrUndefined(setAccessorDeclaration.parameters); if (param && isIdentifier(setAccessorDeclaration.name) && isIdentifier(param.name)) { - let type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken); + let type = inferTypeForVariableFromUsage(setAccessorDeclaration.name, program, cancellationToken, isStrictNullChecks); if (type === program.getTypeChecker().getAnyType()) { - type = inferTypeForVariableFromUsage(param.name, program, cancellationToken); + type = inferTypeForVariableFromUsage(param.name, program, cancellationToken, isStrictNullChecks); } if (isInJSFile(setAccessorDeclaration)) { annotateJSDocParameters(changes, sourceFile, [{ declaration: param, type }], program, host); @@ -388,17 +391,17 @@ namespace ts.codefix { entry.kind !== FindAllReferences.EntryKind.Span ? tryCast(entry.node, isIdentifier) : undefined); } - function inferTypeForVariableFromUsage(token: Identifier | PrivateIdentifier, program: Program, cancellationToken: CancellationToken): Type { + function inferTypeForVariableFromUsage(token: Identifier | PrivateIdentifier, program: Program, cancellationToken: CancellationToken, isStrictNullChecks: boolean): Type { const references = getReferences(token, program, cancellationToken); - return inferTypeFromReferences(program, references, cancellationToken).single(); + return inferTypeFromReferences(program, references, cancellationToken, isStrictNullChecks).single(); } - function inferTypeForParametersFromUsage(func: SignatureDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken) { + function inferTypeForParametersFromUsage(func: SignatureDeclaration, sourceFile: SourceFile, program: Program, cancellationToken: CancellationToken, isStrictNullChecks: boolean) { const references = getFunctionReferences(func, sourceFile, program, cancellationToken); - return references && inferTypeFromReferences(program, references, cancellationToken).parameters(func) || + return references && inferTypeFromReferences(program, references, cancellationToken, isStrictNullChecks).parameters(func) || func.parameters.map(p => ({ declaration: p, - type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken) : program.getTypeChecker().getAnyType() + type: isIdentifier(p.name) ? inferTypeForVariableFromUsage(p.name, program, cancellationToken, isStrictNullChecks) : program.getTypeChecker().getAnyType() })); } @@ -435,7 +438,7 @@ namespace ts.codefix { readonly isOptional?: boolean; } - function inferTypeFromReferences(program: Program, references: readonly Identifier[], cancellationToken: CancellationToken) { + function inferTypeFromReferences(program: Program, references: readonly Identifier[], cancellationToken: CancellationToken, isStrictNullChecks: boolean) { const checker = program.getTypeChecker(); const builtinConstructors: { [s: string]: (t: Type) => Type } = { string: () => checker.getStringType(), @@ -546,7 +549,9 @@ namespace ts.codefix { for (const call of calls) { if (call.argumentTypes.length <= parameterIndex) { isOptional = isInJSFile(declaration); - types.push(checker.getUndefinedType()); + if (isStrictNullChecks) { + types.push(checker.getUndefinedType(!isStrictNullChecks)); + } } else if (isRest) { for (let i = parameterIndex; i < call.argumentTypes.length; i++) { @@ -872,6 +877,45 @@ namespace ts.codefix { return combineTypes(inferTypes(usage)); } + function remapIntoWideningTypes(type: Type) { + if (isStrictNullChecks) { + return type; + } + if (type === checker.getNullType()) { + // in non-strict mode map bare `null` into the widening `null`, which historically is all that's existed until mixed-mode checking became a thing + return checker.getNullType(/*widening*/ true); + } + else if (type === checker.getUndefinedType()) { + // likewise, in non-strict mode map bare `undefined` into the widening `undefined` + return checker.getUndefinedType(/*widening*/ true); + } + return type; + } + + /** + * This function preserves the non-strict mode behavior of `undefined` and `null` evaporating on contact with a union + */ + function filterNullAndUndefinedFromUnionIfNotStrict(type: Type) { + if (isStrictNullChecks) { + return type; + } + if (!(type.flags & TypeFlags.Union)) { + return type; + } + let containedNull: Type | undefined; + const filtered = checker.getUnionType(filter((type as UnionType).types, t => { + if (t.flags & TypeFlags.Null) { + containedNull = t; + } + return !(t.flags & TypeFlags.Nullable); + })); + if (!(filtered.flags & TypeFlags.Never)) { + return filtered; + } + // only null/undefined union members - if both are present, historically, this makes the union evaluate to `null` + return containedNull || type; + } + function combineTypes(inferences: readonly Type[]): Type { if (!inferences.length) return checker.getAnyType(); @@ -898,7 +942,7 @@ namespace ts.codefix { good = good.filter(i => !(getObjectFlags(i) & ObjectFlags.Anonymous)); good.push(combineAnonymousTypes(anons)); } - return checker.getWidenedType(checker.getUnionType(good.map(checker.getBaseTypeOfLiteralType), UnionReduction.Subtype)); + return checker.getWidenedType(remapIntoWideningTypes(filterNullAndUndefinedFromUnionIfNotStrict(checker.getUnionType(good.map(checker.getBaseTypeOfLiteralType), UnionReduction.Subtype)))); } function combineAnonymousTypes(anons: AnonymousType[]) { @@ -1108,7 +1152,7 @@ namespace ts.codefix { const length = Math.max(...calls.map(c => c.argumentTypes.length)); for (let i = 0; i < length; i++) { const symbol = checker.createSymbol(SymbolFlags.FunctionScopedVariable, escapeLeadingUnderscores(`arg${i}`)); - symbol.type = combineTypes(calls.map(call => call.argumentTypes[i] || checker.getUndefinedType())); + symbol.type = combineTypes(calls.map(call => call.argumentTypes[i] || checker.getUndefinedType(!isStrictNullChecks))); if (calls.some(call => call.argumentTypes[i] === undefined)) { symbol.flags |= SymbolFlags.Optional; } diff --git a/src/services/transpile.ts b/src/services/transpile.ts index b2d8951e43b7e..217664f79285b 100644 --- a/src/services/transpile.ts +++ b/src/services/transpile.ts @@ -125,7 +125,7 @@ namespace ts { export function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions { // Lazily create this value to fix module loading errors. commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || - filter(optionDeclarations, o => typeof o.type === "object" && !forEachEntry(o.type, v => typeof v !== "number")) as CommandLineOptionOfCustomType[]; + filter(optionDeclarations, o => typeof o.type === "object" && !forEachEntry((o as CommandLineOptionOfCustomType).type, v => typeof v !== "number")) as CommandLineOptionOfCustomType[]; options = cloneCompilerOptions(options); diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 23bfc30ee197c..36780cab71ecc 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -2323,7 +2323,7 @@ declare namespace ts { getWidenedType(type: Type): Type; getReturnTypeOfSignature(signature: Signature): Type; getNullableType(type: Type, flags: TypeFlags): Type; - getNonNullableType(type: Type): Type; + getNonNullableType(type: Type, context?: Node | undefined): Type; getTypeArguments(type: TypeReference): readonly Type[]; /** Note that the resulting nodes cannot be checked. */ typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeNode | undefined; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 18ef4ee23f826..492fdb763b3e3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -2323,7 +2323,7 @@ declare namespace ts { getWidenedType(type: Type): Type; getReturnTypeOfSignature(signature: Signature): Type; getNullableType(type: Type, flags: TypeFlags): Type; - getNonNullableType(type: Type): Type; + getNonNullableType(type: Type, context?: Node | undefined): Type; getTypeArguments(type: TypeReference): readonly Type[]; /** Note that the resulting nodes cannot be checked. */ typeToTypeNode(type: Type, enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined): TypeNode | undefined; diff --git a/tests/baselines/reference/booleanLiteralsContextuallyTypedFromUnion.errors.txt b/tests/baselines/reference/booleanLiteralsContextuallyTypedFromUnion.errors.txt deleted file mode 100644 index 5b8fb9b0ea85d..0000000000000 --- a/tests/baselines/reference/booleanLiteralsContextuallyTypedFromUnion.errors.txt +++ /dev/null @@ -1,31 +0,0 @@ -error TS2318: Cannot find global type 'CallableFunction'. -error TS2318: Cannot find global type 'NewableFunction'. - - -!!! error TS2318: Cannot find global type 'CallableFunction'. -!!! error TS2318: Cannot find global type 'NewableFunction'. -==== tests/cases/compiler/booleanLiteralsContextuallyTypedFromUnion.tsx (0 errors) ==== - interface A { isIt: true; text: string; } - interface B { isIt: false; value: number; } - type C = A | B; - const isIt = Math.random() > 0.5; - const c: C = isIt ? { isIt, text: 'hey' } : { isIt, value: 123 }; - const cc: C = isIt ? { isIt: isIt, text: 'hey' } : { isIt: isIt, value: 123 }; - - type ComponentProps = - | { - optionalBool: true; - mandatoryFn: () => void; - } - | { - optionalBool: false; - }; - - let Funk = (_props: ComponentProps) =>
Hello
; - - let Fail1 = () => { }} optionalBool={true} /> - let Fail2 = () => { }} optionalBool={true as true} /> - let True = true as true; - let Fail3 = () => { }} optionalBool={True} /> - let attrs2 = { optionalBool: true as true, mandatoryFn: () => { } } - let Success = () => \ No newline at end of file diff --git a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt index 88ffa05ad4deb..500274bffda0a 100644 --- a/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt +++ b/tests/baselines/reference/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.errors.txt @@ -5,27 +5,58 @@ tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfin Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. Type 'GetProps[P]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P] : GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. ==== tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfiniteInstantiationDepth.ts (1 errors) ==== @@ -100,25 +131,56 @@ tests/cases/compiler/circularlyConstrainedMappedTypeContainingConditionalNoInfin !!! error TS2344: Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. !!! error TS2344: Type 'GetProps[P]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. !!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P] : GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. \ No newline at end of file diff --git a/tests/baselines/reference/collectionPatternNoError.types b/tests/baselines/reference/collectionPatternNoError.types index de8e960f095d1..fc42829c4d48e 100644 --- a/tests/baselines/reference/collectionPatternNoError.types +++ b/tests/baselines/reference/collectionPatternNoError.types @@ -23,7 +23,7 @@ function fetchMsg(protoCtor: MsgConstructor): V { >protoCtor : MsgConstructor return null!; ->null! : null +>null! : never >null : null } diff --git a/tests/baselines/reference/conditionalTypes2.errors.txt b/tests/baselines/reference/conditionalTypes2.errors.txt index a96ab6ac3a5d0..c42681790a53c 100644 --- a/tests/baselines/reference/conditionalTypes2.errors.txt +++ b/tests/baselines/reference/conditionalTypes2.errors.txt @@ -148,7 +148,6 @@ tests/cases/conformance/types/conditional/conditionalTypes2.ts(75,12): error TS2 !!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. !!! error TS2345: Type 'Extract' is not assignable to type '{ foo: string; bat: string; }'. !!! error TS2345: Property 'bat' is missing in type 'Bar & Foo' but required in type '{ foo: string; bat: string; }'. -!!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here. !!! related TS2728 tests/cases/conformance/types/conditional/conditionalTypes2.ts:62:43: 'bat' is declared here. fooBat(y); // Error ~ diff --git a/tests/baselines/reference/declarationEmitMappedTypeDistributivityPreservesConstraints.types b/tests/baselines/reference/declarationEmitMappedTypeDistributivityPreservesConstraints.types index 41b6e4b4bd372..48949f0ba5971 100644 --- a/tests/baselines/reference/declarationEmitMappedTypeDistributivityPreservesConstraints.types +++ b/tests/baselines/reference/declarationEmitMappedTypeDistributivityPreservesConstraints.types @@ -15,7 +15,7 @@ function fn }>(sliceIndex: T): AllArg { >sliceIndex : T return null!; ->null! : null +>null! : never >null : null } diff --git a/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=commonjs).types b/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=commonjs).types index b2615eac81b73..95df13899c15e 100644 --- a/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=commonjs).types +++ b/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=commonjs).types @@ -80,7 +80,7 @@ class HelloWorld { handleEvent3(event: C3): T1 { return undefined! } // Ok, Error >handleEvent3 : (event: C3) => T1 >event : C3 ->undefined! : undefined +>undefined! : never >undefined : undefined } diff --git a/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=esnext).types b/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=esnext).types index b2615eac81b73..95df13899c15e 100644 --- a/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=esnext).types +++ b/tests/baselines/reference/emitDecoratorMetadata_isolatedModules(module=esnext).types @@ -80,7 +80,7 @@ class HelloWorld { handleEvent3(event: C3): T1 { return undefined! } // Ok, Error >handleEvent3 : (event: C3) => T1 >event : C3 ->undefined! : undefined +>undefined! : never >undefined : undefined } diff --git a/tests/baselines/reference/errorInfoForRelatedIndexTypesNoConstraintElaboration.errors.txt b/tests/baselines/reference/errorInfoForRelatedIndexTypesNoConstraintElaboration.errors.txt index 1626db671f242..da0279d050d68 100644 --- a/tests/baselines/reference/errorInfoForRelatedIndexTypesNoConstraintElaboration.errors.txt +++ b/tests/baselines/reference/errorInfoForRelatedIndexTypesNoConstraintElaboration.errors.txt @@ -1,9 +1,10 @@ tests/cases/compiler/errorInfoForRelatedIndexTypesNoConstraintElaboration.ts(6,15): error TS2322: Type 'IntrinsicElements[T1]' is not assignable to type 'IntrinsicElements[T2]'. Type 'T1' is not assignable to type 'T2'. 'T1' is assignable to the constraint of type 'T2', but 'T2' could be instantiated with a different subtype of constraint 'keyof IntrinsicElements'. +tests/cases/compiler/errorInfoForRelatedIndexTypesNoConstraintElaboration.ts(6,15): error TS2590: Expression produces a union type that is too complex to represent. -==== tests/cases/compiler/errorInfoForRelatedIndexTypesNoConstraintElaboration.ts (1 errors) ==== +==== tests/cases/compiler/errorInfoForRelatedIndexTypesNoConstraintElaboration.ts (2 errors) ==== /// class I { @@ -14,5 +15,7 @@ tests/cases/compiler/errorInfoForRelatedIndexTypesNoConstraintElaboration.ts(6,1 !!! error TS2322: Type 'IntrinsicElements[T1]' is not assignable to type 'IntrinsicElements[T2]'. !!! error TS2322: Type 'T1' is not assignable to type 'T2'. !!! error TS2322: 'T1' is assignable to the constraint of type 'T2', but 'T2' could be instantiated with a different subtype of constraint 'keyof IntrinsicElements'. + ~~ +!!! error TS2590: Expression produces a union type that is too complex to represent. } } \ No newline at end of file diff --git a/tests/baselines/reference/genericConditionalConstrainedToUnknownNotAssignableToConcreteObject.errors.txt b/tests/baselines/reference/genericConditionalConstrainedToUnknownNotAssignableToConcreteObject.errors.txt index 2063b58b4e3dc..f14f6292a27b4 100644 --- a/tests/baselines/reference/genericConditionalConstrainedToUnknownNotAssignableToConcreteObject.errors.txt +++ b/tests/baselines/reference/genericConditionalConstrainedToUnknownNotAssignableToConcreteObject.errors.txt @@ -9,7 +9,7 @@ tests/cases/compiler/genericConditionalConstrainedToUnknownNotAssignableToConcre Type 'unknown' is not assignable to type 'A'. Type 'ReturnType[string]>' is not assignable to type 'A'. Type 'unknown' is not assignable to type 'A'. - Property 'x' is missing in type '{}' but required in type 'A'. + Type 'unknown' is not assignable to type 'A'. ==== tests/cases/compiler/genericConditionalConstrainedToUnknownNotAssignableToConcreteObject.ts (1 errors) ==== @@ -38,8 +38,7 @@ tests/cases/compiler/genericConditionalConstrainedToUnknownNotAssignableToConcre !!! error TS2322: Type 'unknown' is not assignable to type 'A'. !!! error TS2322: Type 'ReturnType[string]>' is not assignable to type 'A'. !!! error TS2322: Type 'unknown' is not assignable to type 'A'. -!!! error TS2322: Property 'x' is missing in type '{}' but required in type 'A'. -!!! related TS2728 tests/cases/compiler/genericConditionalConstrainedToUnknownNotAssignableToConcreteObject.ts:1:15: 'x' is declared here. +!!! error TS2322: Type 'unknown' is not assignable to type 'A'. } // Original CFA report of the above issue diff --git a/tests/baselines/reference/inDoesNotOperateOnPrimitiveTypes.types b/tests/baselines/reference/inDoesNotOperateOnPrimitiveTypes.types index f56bbf9395d40..047e1168a3479 100644 --- a/tests/baselines/reference/inDoesNotOperateOnPrimitiveTypes.types +++ b/tests/baselines/reference/inDoesNotOperateOnPrimitiveTypes.types @@ -79,7 +79,7 @@ function union2(thing: T | U) { "key" in thing; // Ok >"key" in thing : boolean >"key" : "key" ->thing : T +>thing : T | (T & null) | (U & null) } } @@ -146,7 +146,7 @@ function union5(p: T | U) "key" in p; >"key" in p : boolean >"key" : "key" ->p : (T & object) | (U & object) +>p : (T & object) | (U & object) | (T & null) | (U & null) } } diff --git a/tests/baselines/reference/intersectionReduction.types b/tests/baselines/reference/intersectionReduction.types index fc04d01441c43..69252142cb5ad 100644 --- a/tests/baselines/reference/intersectionReduction.types +++ b/tests/baselines/reference/intersectionReduction.types @@ -40,12 +40,12 @@ type N1 = 'a' & 'b'; >N1 : never type N2 = { a: string } & null; ->N2 : null +>N2 : never >a : string >null : null type N3 = { a: string } & undefined; ->N3 : undefined +>N3 : never >a : string type N4 = string & number; @@ -255,10 +255,10 @@ declare let s2: string & Tag2; >s2 : never declare let t1: string & Tag1 | undefined; ->t1 : undefined +>t1 : never declare let t2: string & Tag2 | undefined; ->t2 : undefined +>t2 : never s1 = s2; >s1 = s2 : never @@ -271,14 +271,14 @@ s2 = s1; >s1 : never t1 = t2; ->t1 = t2 : undefined ->t1 : undefined ->t2 : undefined +>t1 = t2 : never +>t1 : never +>t2 : never t2 = t1; ->t2 = t1 : undefined ->t2 : undefined ->t1 : undefined +>t2 = t1 : never +>t2 : never +>t1 : never // Repro from #36736 diff --git a/tests/baselines/reference/jsxSpreadOverwritesAttributeStrict.errors.txt b/tests/baselines/reference/jsxSpreadOverwritesAttributeStrict.errors.txt index fefbc6cac4da0..0a3c1eb206661 100644 --- a/tests/baselines/reference/jsxSpreadOverwritesAttributeStrict.errors.txt +++ b/tests/baselines/reference/jsxSpreadOverwritesAttributeStrict.errors.txt @@ -1,4 +1,3 @@ -error TS2318: Cannot find global type 'CallableFunction'. error TS2318: Cannot find global type 'NewableFunction'. tests/cases/conformance/jsx/file.tsx(19,17): error TS2783: 'a' is specified more than once, so this usage will be overwritten. tests/cases/conformance/jsx/file.tsx(20,17): error TS2783: 'a' is specified more than once, so this usage will be overwritten. @@ -10,7 +9,6 @@ tests/cases/conformance/jsx/file.tsx(22,17): error TS2783: 'a' is specified more tests/cases/conformance/jsx/file.tsx(22,23): error TS2783: 'd' is specified more than once, so this usage will be overwritten. -!!! error TS2318: Cannot find global type 'CallableFunction'. !!! error TS2318: Cannot find global type 'NewableFunction'. ==== tests/cases/conformance/jsx/file.tsx (8 errors) ==== import React = require('react'); diff --git a/tests/baselines/reference/localTypeParameterInferencePriority.types b/tests/baselines/reference/localTypeParameterInferencePriority.types index 9834da9c9d92a..fada2121c42ce 100644 --- a/tests/baselines/reference/localTypeParameterInferencePriority.types +++ b/tests/baselines/reference/localTypeParameterInferencePriority.types @@ -20,7 +20,7 @@ class Table { >getRows : () => Array>> return null! ->null! : null +>null! : never >null : null } } diff --git a/tests/baselines/reference/mappedTypeRelationships.errors.txt b/tests/baselines/reference/mappedTypeRelationships.errors.txt index 33c20572d127c..20981577b6412 100644 --- a/tests/baselines/reference/mappedTypeRelationships.errors.txt +++ b/tests/baselines/reference/mappedTypeRelationships.errors.txt @@ -17,12 +17,18 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(40,5): error TS2 tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(41,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'U[keyof T] | undefined'. Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'. + Type 'T[string]' is not assignable to type 'U[keyof T]'. + Type 'T' is not assignable to type 'U'. + 'U' could be instantiated with an arbitrary type which could be unrelated to 'T'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(45,5): error TS2322: Type 'U[K] | undefined' is not assignable to type 'T[K]'. Type 'undefined' is not assignable to type 'T[K]'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(46,5): error TS2322: Type 'T[K]' is not assignable to type 'U[K] | undefined'. Type 'T[keyof T]' is not assignable to type 'U[K] | undefined'. Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'U[K] | undefined'. Type 'T[string]' is not assignable to type 'U[K] | undefined'. + Type 'T[string]' is not assignable to type 'U[K]'. + Type 'T' is not assignable to type 'U'. + 'U' could be instantiated with an arbitrary type which could be unrelated to 'T'. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(51,5): error TS2542: Index signature in type 'Readonly' only permits reading. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(56,5): error TS2542: Index signature in type 'Readonly' only permits reading. tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(61,5): error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T]'. @@ -146,6 +152,10 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS !!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[keyof T] | undefined'. !!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'U[keyof T] | undefined'. !!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T] | undefined'. +!!! error TS2322: Type 'T[string]' is not assignable to type 'U[keyof T]'. +!!! error TS2322: Type 'T' is not assignable to type 'U'. +!!! error TS2322: 'U' could be instantiated with an arbitrary type which could be unrelated to 'T'. +!!! related TS2208 tests/cases/conformance/types/mapped/mappedTypeRelationships.ts:39:14: This type parameter might need an `extends U` constraint. } function f13(x: T, y: Partial, k: K) { @@ -159,6 +169,10 @@ tests/cases/conformance/types/mapped/mappedTypeRelationships.ts(168,5): error TS !!! error TS2322: Type 'T[keyof T]' is not assignable to type 'U[K] | undefined'. !!! error TS2322: Type 'T[string] | T[number] | T[symbol]' is not assignable to type 'U[K] | undefined'. !!! error TS2322: Type 'T[string]' is not assignable to type 'U[K] | undefined'. +!!! error TS2322: Type 'T[string]' is not assignable to type 'U[K]'. +!!! error TS2322: Type 'T' is not assignable to type 'U'. +!!! error TS2322: 'U' could be instantiated with an arbitrary type which could be unrelated to 'T'. +!!! related TS2208 tests/cases/conformance/types/mapped/mappedTypeRelationships.ts:44:14: This type parameter might need an `extends U` constraint. } function f20(x: T, y: Readonly, k: keyof T) { diff --git a/tests/baselines/reference/metadataOfUnionWithNull.types b/tests/baselines/reference/metadataOfUnionWithNull.types index 588c21911202a..20c7af3323563 100644 --- a/tests/baselines/reference/metadataOfUnionWithNull.types +++ b/tests/baselines/reference/metadataOfUnionWithNull.types @@ -54,7 +54,7 @@ class B { >PropDeco : (target: Object, propKey: string | symbol) => void d: undefined | null; ->d : null +>d : never >null : null @PropDeco diff --git a/tests/baselines/reference/noImplicitAnyForIn.types b/tests/baselines/reference/noImplicitAnyForIn.types index bd8cb1c8c200c..6fcd13004a276 100644 --- a/tests/baselines/reference/noImplicitAnyForIn.types +++ b/tests/baselines/reference/noImplicitAnyForIn.types @@ -59,8 +59,8 @@ for (var a in x) { >b : any var c = a || b; ->c : string ->a || b : string +>c : string | undefined +>a || b : string | undefined >a : string >b : undefined } diff --git a/tests/baselines/reference/nonNullableReductionNonStrict.types b/tests/baselines/reference/nonNullableReductionNonStrict.types index 075ee5a41fd1b..6bb2f98177e4c 100644 --- a/tests/baselines/reference/nonNullableReductionNonStrict.types +++ b/tests/baselines/reference/nonNullableReductionNonStrict.types @@ -17,7 +17,7 @@ function test(f1: Transform1, f2: Transform2) { f1?.("hello"); >f1?.("hello") : T ->f1 : (value: string) => T +>f1 : ((value: string) => T) | undefined >"hello" : "hello" f2?.("hello"); @@ -28,23 +28,23 @@ function test(f1: Transform1, f2: Transform2) { function f1(x: T | (string extends T ? null | undefined : never)) { >f1 : (x: T | (string extends T ? null | undefined : never)) => void ->x : T | (string extends T ? null : never) +>x : T | (string extends T ? never : never) >null : null let z = x!; // NonNullable ->z : T | (string extends T ? null : never) ->x! : T | (string extends T ? null : never) ->x : T | (string extends T ? null : never) +>z : T +>x! : T +>x : T | (string extends T ? never : never) } function f2(x: T | U) { ->f2 : (x: T | U) => void +>f2 : (x: T | U) => void >null : null >x : T | U let z = x!; // NonNullable ->z : T | U ->x! : T | U +>z : T +>x! : T >x : T | U } diff --git a/tests/baselines/reference/nullishCoalescingOperator_not_strict.types b/tests/baselines/reference/nullishCoalescingOperator_not_strict.types index adfdce759dce5..c5f69d43819ad 100644 --- a/tests/baselines/reference/nullishCoalescingOperator_not_strict.types +++ b/tests/baselines/reference/nullishCoalescingOperator_not_strict.types @@ -30,7 +30,7 @@ declare const a7: unknown | null >null : null declare const a8: never | null ->a8 : null +>a8 : never >null : null declare const a9: any | null @@ -81,9 +81,9 @@ const aa7 = a7 ?? 'whatever' >'whatever' : "whatever" const aa8 = a8 ?? 'whatever' ->aa8 : "whatever" ->a8 ?? 'whatever' : "whatever" ->a8 : null +>aa8 : never +>a8 ?? 'whatever' : never +>a8 : never >'whatever' : "whatever" const aa9 = a9 ?? 'whatever' diff --git a/tests/baselines/reference/privateFieldAssignabilityFromUnknown.errors.txt b/tests/baselines/reference/privateFieldAssignabilityFromUnknown.errors.txt index 22f50eec6ff01..bdf2d4116dbee 100644 --- a/tests/baselines/reference/privateFieldAssignabilityFromUnknown.errors.txt +++ b/tests/baselines/reference/privateFieldAssignabilityFromUnknown.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/privateFieldAssignabilityFromUnknown.ts(2,3): error TS18028: Private identifiers are only available when targeting ECMAScript 2015 and higher. -tests/cases/compiler/privateFieldAssignabilityFromUnknown.ts(5,7): error TS2741: Property '#field' is missing in type '{}' but required in type 'Class'. +tests/cases/compiler/privateFieldAssignabilityFromUnknown.ts(5,7): error TS2322: Type 'unknown' is not assignable to type 'Class'. ==== tests/cases/compiler/privateFieldAssignabilityFromUnknown.ts (2 errors) ==== @@ -11,6 +11,5 @@ tests/cases/compiler/privateFieldAssignabilityFromUnknown.ts(5,7): error TS2741: const task: Class = {} as unknown; ~~~~ -!!! error TS2741: Property '#field' is missing in type '{}' but required in type 'Class'. -!!! related TS2728 tests/cases/compiler/privateFieldAssignabilityFromUnknown.ts:2:3: '#field' is declared here. +!!! error TS2322: Type 'unknown' is not assignable to type 'Class'. \ No newline at end of file diff --git a/tests/baselines/reference/propertyAccessOnTypeParameterWithoutConstraints.symbols b/tests/baselines/reference/propertyAccessOnTypeParameterWithoutConstraints.symbols index fbbfb557ef6f1..b0531585c744a 100644 --- a/tests/baselines/reference/propertyAccessOnTypeParameterWithoutConstraints.symbols +++ b/tests/baselines/reference/propertyAccessOnTypeParameterWithoutConstraints.symbols @@ -72,7 +72,6 @@ var r3: string = a().toString(); var r3b: string = a()['toString'](); >r3b : Symbol(r3b, Decl(propertyAccessOnTypeParameterWithoutConstraints.ts, 21, 3)) >a : Symbol(a, Decl(propertyAccessOnTypeParameterWithoutConstraints.ts, 17, 3)) ->'toString' : Symbol(Object.toString, Decl(lib.es5.d.ts, --, --)) var b = { >b : Symbol(b, Decl(propertyAccessOnTypeParameterWithoutConstraints.ts, 23, 3)) diff --git a/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.errors.txt b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.errors.txt index 9b6e0228efeaa..ef879e148dfc1 100644 --- a/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.errors.txt +++ b/tests/baselines/reference/reactReduxLikeDeferredInferenceAllowsAssignment.errors.txt @@ -5,27 +5,58 @@ tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts(76,50): Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. Type 'GetProps[P]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. - Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. + Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P] : GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. + Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. ==== tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts (1 errors) ==== @@ -113,27 +144,58 @@ tests/cases/compiler/reactReduxLikeDeferredInferenceAllowsAssignment.ts(76,50): !!! error TS2344: Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. !!! error TS2344: Type 'GetProps[P]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. !!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. -!!! error TS2344: Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type '(Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]) | (Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>])' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & string] extends GetProps[keyof TInjectedProps & string] ? GetProps[keyof TInjectedProps & string] : TInjectedProps[keyof TInjectedProps & string] : GetProps[string]' is not assignable to type '(TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never) | undefined'. +!!! error TS2344: Type 'keyof GetProps & string extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string] : GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]) | GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & keyof GetProps & string] extends GetProps[keyof TInjectedProps & keyof GetProps & string] ? GetProps[keyof TInjectedProps & keyof GetProps & string] : TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string] | TInjectedProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type '(TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]) | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'TInjectedProps[keyof TInjectedProps & Extract>] extends GetProps[keyof TInjectedProps & Extract>] ? GetProps[keyof TInjectedProps & Extract>] : TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>] | TInjectedProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof TInjectedProps & Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'Extract> extends keyof TInjectedProps ? TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>] : GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>] | (TInjectedProps[Extract>] extends GetProps[Extract>] ? GetProps[Extract>] : TInjectedProps[Extract>])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'P extends keyof TInjectedProps ? TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P] : GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[P] | (TInjectedProps[P] extends GetProps[P] ? GetProps[P] : TInjectedProps[P])' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[P]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>] | GetProps[Extract>] | GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[Extract>]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[keyof GetProps & string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. +!!! error TS2344: Type 'GetProps[string]' is not assignable to type 'TInjectedProps[P] extends GetProps[P] ? GetProps[P] : never'. >; declare const connect: { diff --git a/tests/baselines/reference/spellingSuggestionJSXAttribute.types b/tests/baselines/reference/spellingSuggestionJSXAttribute.types index 619ceb73e36ee..1a76683ef9961 100644 --- a/tests/baselines/reference/spellingSuggestionJSXAttribute.types +++ b/tests/baselines/reference/spellingSuggestionJSXAttribute.types @@ -4,13 +4,13 @@ import * as React from "react"; >React : typeof React function MyComp2(props: { className?: string, htmlFor?: string }) { ->MyComp2 : (props: { className?: string; htmlFor?: string;}) => any +>MyComp2 : (props: { className?: string; htmlFor?: string;}) => never >props : { className?: string; htmlFor?: string; } >className : string >htmlFor : string return null!; ->null! : null +>null! : never >null : null } class MyComp extends React.Component<{ className?: string, htmlFor?: string }> { } @@ -49,7 +49,7 @@ class MyComp extends React.Component<{ className?: string, htmlFor?: string }> { ; > : JSX.Element ->MyComp2 : (props: { className?: string; htmlFor?: string; }) => any +>MyComp2 : (props: { className?: string; htmlFor?: string; }) => never >class : string ; @@ -59,6 +59,6 @@ class MyComp extends React.Component<{ className?: string, htmlFor?: string }> { ; > : JSX.Element ->MyComp2 : (props: { className?: string; htmlFor?: string; }) => any +>MyComp2 : (props: { className?: string; htmlFor?: string; }) => never >for : string diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js index e3fc789404c06..95dd4f1b18ce0 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/declarationDir-is-specified.js @@ -134,14 +134,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -159,7 +155,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:40 AM] Found 11 errors. Watching for file changes. +[12:00:40 AM] Found 9 errors. Watching for file changes. @@ -269,14 +265,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -294,7 +286,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:48 AM] Found 11 errors. Watching for file changes. +[12:00:48 AM] Found 9 errors. Watching for file changes. diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js index 620c42fa2a32c..dddc59ba07bcc 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-and-declarationDir-is-specified.js @@ -134,14 +134,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -159,7 +155,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:46 AM] Found 11 errors. Watching for file changes. +[12:00:46 AM] Found 9 errors. Watching for file changes. @@ -269,14 +265,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -294,7 +286,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:54 AM] Found 11 errors. Watching for file changes. +[12:00:54 AM] Found 9 errors. Watching for file changes. diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js index 6800711e1a42f..d20ab69c4d003 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/when-outDir-is-specified.js @@ -134,14 +134,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -159,7 +155,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:36 AM] Found 11 errors. Watching for file changes. +[12:00:36 AM] Found 9 errors. Watching for file changes. @@ -261,14 +257,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -286,7 +278,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:42 AM] Found 11 errors. Watching for file changes. +[12:00:42 AM] Found 9 errors. Watching for file changes. diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js index 7b96140fceb23..0f5cdb5205d46 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/with-outFile.js @@ -134,14 +134,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -159,7 +155,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:31 AM] Found 11 errors. Watching for file changes. +[12:00:31 AM] Found 9 errors. Watching for file changes. @@ -256,14 +252,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -281,7 +273,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:38 AM] Found 11 errors. Watching for file changes. +[12:00:38 AM] Found 9 errors. Watching for file changes. diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js index 1b21f2ca83fcc..99fcffdb3d621 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified-with-declaration-enabled.js @@ -134,14 +134,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -159,7 +155,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:34 AM] Found 11 errors. Watching for file changes. +[12:00:34 AM] Found 9 errors. Watching for file changes. @@ -269,14 +265,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -294,7 +286,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:42 AM] Found 11 errors. Watching for file changes. +[12:00:42 AM] Found 9 errors. Watching for file changes. diff --git a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js index 1b80ab46e46ad..1acfcafc944a2 100644 --- a/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js +++ b/tests/baselines/reference/tscWatch/programUpdates/should-not-trigger-recompilation-because-of-program-emit/without-outDir-or-outFile-is-specified.js @@ -134,14 +134,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -159,7 +155,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:30 AM] Found 11 errors. Watching for file changes. +[12:00:30 AM] Found 9 errors. Watching for file changes. @@ -261,14 +257,10 @@ Output:: error TS2318: Cannot find global type 'Boolean'. -error TS2318: Cannot find global type 'CallableFunction'. - error TS2318: Cannot find global type 'Function'. error TS2318: Cannot find global type 'IArguments'. -error TS2318: Cannot find global type 'NewableFunction'. - error TS2318: Cannot find global type 'Number'. error TS2318: Cannot find global type 'Object'. @@ -286,7 +278,7 @@ Output::    ~~~~~~~~ File is default library for target specified here. -[12:00:36 AM] Found 11 errors. Watching for file changes. +[12:00:36 AM] Found 9 errors. Watching for file changes. diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.types b/tests/baselines/reference/typeGuardTypeOfUndefined.types index 79f87e101caa8..ffc82e57e6693 100644 --- a/tests/baselines/reference/typeGuardTypeOfUndefined.types +++ b/tests/baselines/reference/typeGuardTypeOfUndefined.types @@ -242,7 +242,7 @@ function test9(a: boolean | number) { } else { a; ->a : undefined +>a : never } } @@ -259,7 +259,7 @@ function test10(a: boolean | number) { if (typeof a === "boolean") { >typeof a === "boolean" : boolean >typeof a : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" ->a : undefined +>a : never >"boolean" : "boolean" a; @@ -267,7 +267,7 @@ function test10(a: boolean | number) { } else { a; ->a : undefined +>a : never } } else { diff --git a/tests/baselines/reference/typeParameterExplicitlyExtendsAny.errors.txt b/tests/baselines/reference/typeParameterExplicitlyExtendsAny.errors.txt index 07d7cee05f610..f646db7a2fcf4 100644 --- a/tests/baselines/reference/typeParameterExplicitlyExtendsAny.errors.txt +++ b/tests/baselines/reference/typeParameterExplicitlyExtendsAny.errors.txt @@ -2,9 +2,9 @@ tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(3,7): error TS2339: Pr tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(9,7): error TS2339: Property 'blah' does not exist on type 'T'. tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(14,7): error TS2339: Property 'children' does not exist on type 'T'. tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(15,5): error TS2349: This expression is not callable. - Type '{}' has no call signatures. + Type 'unknown' has no call signatures. tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(16,9): error TS2351: This expression is not constructable. - Type '{}' has no construct signatures. + Type 'unknown' has no construct signatures. tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(30,14): error TS2339: Property 'children' does not exist on type 'T'. @@ -32,11 +32,11 @@ tests/cases/compiler/typeParameterExplicitlyExtendsAny.ts(30,14): error TS2339: x(); ~ !!! error TS2349: This expression is not callable. -!!! error TS2349: Type '{}' has no call signatures. +!!! error TS2349: Type 'unknown' has no call signatures. new x(); ~ !!! error TS2351: This expression is not constructable. -!!! error TS2351: Type '{}' has no construct signatures. +!!! error TS2351: Type 'unknown' has no construct signatures. x[100]; x['hello']; } diff --git a/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt b/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt index 017c3ada88cd0..1217ddd0c4fa7 100644 --- a/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt +++ b/tests/baselines/reference/useUnknownInCatchVariables01.errors.txt @@ -1,7 +1,7 @@ tests/cases/compiler/useUnknownInCatchVariables01.ts(6,12): error TS2339: Property 'toUpperCase' does not exist on type 'unknown'. tests/cases/compiler/useUnknownInCatchVariables01.ts(7,10): error TS2356: An arithmetic operand must be of type 'any', 'number', 'bigint' or an enum type. tests/cases/compiler/useUnknownInCatchVariables01.ts(8,10): error TS2349: This expression is not callable. - Type '{}' has no call signatures. + Type 'unknown' has no call signatures. ==== tests/cases/compiler/useUnknownInCatchVariables01.ts (3 errors) ==== @@ -19,7 +19,7 @@ tests/cases/compiler/useUnknownInCatchVariables01.ts(8,10): error TS2349: This e void e(); ~ !!! error TS2349: This expression is not callable. -!!! error TS2349: Type '{}' has no call signatures. +!!! error TS2349: Type 'unknown' has no call signatures. if (typeof e === "string") { // works! diff --git a/tests/cases/fourslash/codeFixInferFromUsageCallBodyBoth.ts b/tests/cases/fourslash/codeFixInferFromUsageCallBodyBoth.ts index f59d1bc190758..09c9cd83ff10a 100644 --- a/tests/cases/fourslash/codeFixInferFromUsageCallBodyBoth.ts +++ b/tests/cases/fourslash/codeFixInferFromUsageCallBodyBoth.ts @@ -13,4 +13,4 @@ ////f(new C()) -verify.rangeAfterCodeFix("x: number | C, y: undefined",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0); +verify.rangeAfterCodeFix("x: number | C, y: any",/*includeWhiteSpace*/ undefined, /*errorCode*/ undefined, 0); diff --git a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess10.ts b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess10.ts index 7161dd18d7cfa..1b565b5fa7bfd 100644 --- a/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess10.ts +++ b/tests/cases/fourslash/refactorConvertToGetAccessAndSetAccess10.ts @@ -10,11 +10,11 @@ edit.applyRefactor({ actionName: "Generate 'get' and 'set' accessors", actionDescription: "Generate 'get' and 'set' accessors", newContent: `class A { - private /*RENAME*/_a?: string = "foo"; - public get a(): string { + private /*RENAME*/_a?: string | undefined = "foo"; + public get a(): string | undefined { return this._a; } - public set a(value: string) { + public set a(value: string | undefined) { this._a = value; } }`,