mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-29 16:29:19 -05:00
Propagate type comparer function in contextual signature instantiation
This commit is contained in:
@@ -8017,7 +8017,7 @@ namespace ts {
|
||||
|
||||
function cloneTypeMapper(mapper: TypeMapper): TypeMapper {
|
||||
return mapper && isInferenceContext(mapper) ?
|
||||
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.inferences) :
|
||||
createInferenceContext(mapper.signature, mapper.flags | InferenceFlags.NoDefault, mapper.compareTypes, mapper.inferences) :
|
||||
mapper;
|
||||
}
|
||||
|
||||
@@ -8458,7 +8458,7 @@ namespace ts {
|
||||
ignoreReturnTypes: boolean,
|
||||
reportErrors: boolean,
|
||||
errorReporter: ErrorReporter,
|
||||
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
|
||||
compareTypes: TypeComparer): Ternary {
|
||||
// TODO (drosen): De-duplicate code between related functions.
|
||||
if (source === target) {
|
||||
return Ternary.True;
|
||||
@@ -8468,7 +8468,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (source.typeParameters) {
|
||||
source = instantiateSignatureInContextOf(source, target);
|
||||
source = instantiateSignatureInContextOf(source, target, /*contextualMapper*/ undefined, compareTypes);
|
||||
}
|
||||
|
||||
let result = Ternary.True;
|
||||
@@ -10216,13 +10216,14 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function createInferenceContext(signature: Signature, flags: InferenceFlags, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
function createInferenceContext(signature: Signature, flags: InferenceFlags, compareTypes?: TypeComparer, baseInferences?: InferenceInfo[]): InferenceContext {
|
||||
const inferences = baseInferences ? map(baseInferences, cloneInferenceInfo) : map(signature.typeParameters, createInferenceInfo);
|
||||
const context = mapper as InferenceContext;
|
||||
context.mappedTypes = signature.typeParameters;
|
||||
context.signature = signature;
|
||||
context.inferences = inferences;
|
||||
context.flags = flags;
|
||||
context.compareTypes = compareTypes || compareTypesAssignable;
|
||||
return context;
|
||||
|
||||
function mapper(t: Type): Type {
|
||||
@@ -10670,7 +10671,7 @@ namespace ts {
|
||||
const constraint = getConstraintOfTypeParameter(context.signature.typeParameters[index]);
|
||||
if (constraint) {
|
||||
const instantiatedConstraint = instantiateType(constraint, context);
|
||||
if (!isTypeAssignableTo(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
|
||||
if (!context.compareTypes(inferredType, getTypeWithThisArgument(instantiatedConstraint, inferredType))) {
|
||||
inference.inferredType = inferredType = instantiatedConstraint;
|
||||
}
|
||||
}
|
||||
@@ -15071,8 +15072,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
// Instantiate a generic signature in the context of a non-generic signature (section 3.8.5 in TypeScript spec)
|
||||
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper): Signature {
|
||||
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes);
|
||||
function instantiateSignatureInContextOf(signature: Signature, contextualSignature: Signature, contextualMapper?: TypeMapper, compareTypes?: TypeComparer): Signature {
|
||||
const context = createInferenceContext(signature, InferenceFlags.InferUnionTypes, compareTypes);
|
||||
forEachMatchingParameterType(contextualSignature, signature, (source, target) => {
|
||||
// Type parameters from outer context referenced by source type are fixed by instantiation of the source type
|
||||
inferTypes(context.inferences, instantiateType(source, contextualMapper || identityMapper), target);
|
||||
|
||||
@@ -11,20 +11,6 @@ namespace ts {
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
/**
|
||||
* Ternary values are defined such that
|
||||
* x & y is False if either x or y is False.
|
||||
* x & y is Maybe if either x or y is Maybe, but neither x or y is False.
|
||||
* x & y is True if both x and y are True.
|
||||
* x | y is False if both x and y are False.
|
||||
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
|
||||
* x | y is True if either x or y is True.
|
||||
*/
|
||||
export const enum Ternary {
|
||||
False = 0,
|
||||
Maybe = 1,
|
||||
True = -1
|
||||
}
|
||||
|
||||
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
|
||||
export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator(/*locales*/ undefined, { usage: "sort", sensitivity: "accent" }) : undefined;
|
||||
|
||||
@@ -3425,11 +3425,29 @@ namespace ts {
|
||||
AnyDefault = 1 << 2, // Infer anyType for no inferences (otherwise emptyObjectType)
|
||||
}
|
||||
|
||||
/**
|
||||
* Ternary values are defined such that
|
||||
* x & y is False if either x or y is False.
|
||||
* x & y is Maybe if either x or y is Maybe, but neither x or y is False.
|
||||
* x & y is True if both x and y are True.
|
||||
* x | y is False if both x and y are False.
|
||||
* x | y is Maybe if either x or y is Maybe, but neither x or y is True.
|
||||
* x | y is True if either x or y is True.
|
||||
*/
|
||||
export const enum Ternary {
|
||||
False = 0,
|
||||
Maybe = 1,
|
||||
True = -1
|
||||
}
|
||||
|
||||
export type TypeComparer = (s: Type, t: Type, reportErrors?: boolean) => Ternary;
|
||||
|
||||
/* @internal */
|
||||
export interface InferenceContext extends TypeMapper {
|
||||
signature: Signature; // Generic signature for which inferences are made
|
||||
inferences: InferenceInfo[]; // Inferences made for each type parameter
|
||||
flags: InferenceFlags; // Inference flags
|
||||
compareTypes: TypeComparer; // Type comparer function
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
Reference in New Issue
Block a user