mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-25 15:01:36 -05:00
merge with origin/master
This commit is contained in:
@@ -3507,7 +3507,7 @@ namespace ts {
|
||||
|
||||
function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature {
|
||||
for (const s of signatureList) {
|
||||
if (compareSignatures(s, signature, partialMatch, ignoreReturnTypes, compareTypes)) {
|
||||
if (compareSignaturesIdentical(s, signature, partialMatch, ignoreReturnTypes, compareTypesIdentical)) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -3768,11 +3768,14 @@ namespace ts {
|
||||
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
|
||||
const types = containingType.types;
|
||||
let props: Symbol[];
|
||||
// Flags we want to propagate to the result if they exist in all source symbols
|
||||
let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) {
|
||||
commonFlags &= prop.flags;
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
@@ -3800,7 +3803,12 @@ namespace ts {
|
||||
}
|
||||
propTypes.push(getTypeOfSymbol(prop));
|
||||
}
|
||||
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name);
|
||||
const result = <TransientSymbol>createSymbol(
|
||||
SymbolFlags.Property |
|
||||
SymbolFlags.Transient |
|
||||
SymbolFlags.SyntheticProperty |
|
||||
commonFlags,
|
||||
name);
|
||||
result.containingType = containingType;
|
||||
result.declarations = declarations;
|
||||
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
@@ -4959,7 +4967,7 @@ namespace ts {
|
||||
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
|
||||
}
|
||||
|
||||
function compareTypes(source: Type, target: Type): Ternary {
|
||||
function compareTypesIdentical(source: Type, target: Type): Ternary {
|
||||
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False;
|
||||
}
|
||||
|
||||
@@ -4979,10 +4987,96 @@ namespace ts {
|
||||
return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain);
|
||||
}
|
||||
|
||||
function isSignatureAssignableTo(source: Signature, target: Signature): boolean {
|
||||
const sourceType = getOrCreateTypeFromSignature(source);
|
||||
const targetType = getOrCreateTypeFromSignature(target);
|
||||
return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined);
|
||||
/**
|
||||
* See signatureRelatedTo, compareSignaturesIdentical
|
||||
*/
|
||||
function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean {
|
||||
// TODO (drosen): De-duplicate code between related functions.
|
||||
if (source === target) {
|
||||
return true;
|
||||
}
|
||||
if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spec 1.0 Section 3.8.3 & 3.8.4:
|
||||
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
|
||||
source = getErasedSignature(source);
|
||||
target = getErasedSignature(target);
|
||||
|
||||
const sourceMax = getNumNonRestParameters(source);
|
||||
const targetMax = getNumNonRestParameters(target);
|
||||
const checkCount = getNumParametersToCheckForSignatureRelatability(source, sourceMax, target, targetMax);
|
||||
for (let i = 0; i < checkCount; i++) {
|
||||
const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
|
||||
const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
|
||||
const related = isTypeAssignableTo(t, s) || isTypeAssignableTo(s, t);
|
||||
if (!related) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignoreReturnTypes) {
|
||||
const targetReturnType = getReturnTypeOfSignature(target);
|
||||
if (targetReturnType === voidType) {
|
||||
return true;
|
||||
}
|
||||
const sourceReturnType = getReturnTypeOfSignature(source);
|
||||
|
||||
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
|
||||
if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) {
|
||||
if (!(sourceReturnType.flags & TypeFlags.PredicateType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return isTypeAssignableTo(sourceReturnType, targetReturnType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean {
|
||||
const erasedSource = getErasedSignature(implementation);
|
||||
const erasedTarget = getErasedSignature(overload);
|
||||
|
||||
// First see if the return types are compatible in either direction.
|
||||
const sourceReturnType = getReturnTypeOfSignature(erasedSource);
|
||||
const targetReturnType = getReturnTypeOfSignature(erasedTarget);
|
||||
if (targetReturnType === voidType
|
||||
|| checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)
|
||||
|| checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) {
|
||||
|
||||
return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function getNumNonRestParameters(signature: Signature) {
|
||||
const numParams = signature.parameters.length;
|
||||
return signature.hasRestParameter ?
|
||||
numParams - 1 :
|
||||
numParams;
|
||||
}
|
||||
|
||||
function getNumParametersToCheckForSignatureRelatability(source: Signature, sourceNonRestParamCount: number, target: Signature, targetNonRestParamCount: number) {
|
||||
if (source.hasRestParameter === target.hasRestParameter) {
|
||||
if (source.hasRestParameter) {
|
||||
// If both have rest parameters, get the max and add 1 to
|
||||
// compensate for the rest parameter.
|
||||
return Math.max(sourceNonRestParamCount, targetNonRestParamCount) + 1;
|
||||
}
|
||||
else {
|
||||
return Math.min(sourceNonRestParamCount, targetNonRestParamCount);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Return the count for whichever signature doesn't have rest parameters.
|
||||
return source.hasRestParameter ?
|
||||
targetNonRestParamCount :
|
||||
sourceNonRestParamCount;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5574,7 +5668,7 @@ namespace ts {
|
||||
shouldElaborateErrors = false;
|
||||
}
|
||||
}
|
||||
// don't elaborate the primitive apparent types (like Number)
|
||||
// don't elaborate the primitive apparent types (like Number)
|
||||
// because the actual primitives will have already been reported.
|
||||
if (shouldElaborateErrors && !isPrimitiveApparentType(source)) {
|
||||
reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1,
|
||||
@@ -5621,7 +5715,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See signatureAssignableTo, signatureAssignableTo
|
||||
*/
|
||||
function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary {
|
||||
// TODO (drosen): De-duplicate code between related functions.
|
||||
if (source === target) {
|
||||
return Ternary.True;
|
||||
}
|
||||
@@ -5673,10 +5771,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
const targetReturnType = getReturnTypeOfSignature(target);
|
||||
if (targetReturnType === voidType) return result;
|
||||
if (targetReturnType === voidType) {
|
||||
return result;
|
||||
}
|
||||
const sourceReturnType = getReturnTypeOfSignature(source);
|
||||
|
||||
// The follow block preserves old behavior forbidding boolean returning functions from being assignable to type guard returning functions
|
||||
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
|
||||
if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) {
|
||||
if (!(sourceReturnType.flags & TypeFlags.PredicateType)) {
|
||||
if (reportErrors) {
|
||||
@@ -5697,7 +5797,7 @@ namespace ts {
|
||||
}
|
||||
let result = Ternary.True;
|
||||
for (let i = 0, len = sourceSignatures.length; i < len; ++i) {
|
||||
const related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo);
|
||||
const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo);
|
||||
if (!related) {
|
||||
return Ternary.False;
|
||||
}
|
||||
@@ -5830,7 +5930,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
|
||||
return compareProperties(sourceProp, targetProp, compareTypes) !== Ternary.False;
|
||||
return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False;
|
||||
}
|
||||
|
||||
function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary {
|
||||
@@ -5877,7 +5977,11 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
|
||||
/**
|
||||
* See signatureRelatedTo, compareSignaturesIdentical
|
||||
*/
|
||||
function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
|
||||
// TODO (drosen): De-duplicate code between related functions.
|
||||
if (source === target) {
|
||||
return Ternary.True;
|
||||
}
|
||||
@@ -7605,7 +7709,7 @@ namespace ts {
|
||||
// This signature will contribute to contextual union signature
|
||||
signatureList = [signature];
|
||||
}
|
||||
else if (!compareSignatures(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypes)) {
|
||||
else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) {
|
||||
// Signatures aren't identical, do not use
|
||||
return undefined;
|
||||
}
|
||||
@@ -8280,9 +8384,9 @@ namespace ts {
|
||||
// Props is of type 'any' or unknown
|
||||
return links.resolvedJsxType = attributesType;
|
||||
}
|
||||
else if (!(attributesType.flags & TypeFlags.ObjectType)) {
|
||||
// Props is not an object type
|
||||
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType));
|
||||
else if (attributesType.flags & TypeFlags.Union) {
|
||||
// Props cannot be a union type
|
||||
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType));
|
||||
return links.resolvedJsxType = anyType;
|
||||
}
|
||||
else {
|
||||
@@ -11626,7 +11730,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
for (const otherSignature of signaturesToCheck) {
|
||||
if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) {
|
||||
if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature, /*ignoreReturnTypes*/ false)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -11873,7 +11977,7 @@ namespace ts {
|
||||
//
|
||||
// The implementation is completely unrelated to the specialized signature, yet we do not check this.
|
||||
for (const signature of signatures) {
|
||||
if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) {
|
||||
if (!signature.hasStringLiterals && !isImplementationCompatibleWithOverload(bodySignature, signature)) {
|
||||
error(signature.declaration, Diagnostics.Overload_signature_is_not_compatible_with_function_implementation);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1691,7 +1691,7 @@
|
||||
"category": "Error",
|
||||
"code": 2528
|
||||
},
|
||||
"JSX element attributes type '{0}' must be an object type.": {
|
||||
"JSX element attributes type '{0}' may not be a union type.": {
|
||||
"category": "Error",
|
||||
"code": 2600
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user