refactor
This commit is contained in:
Родитель
76718d8755
Коммит
20b79eb8c8
|
@ -20286,13 +20286,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
return result;
|
||||
}
|
||||
|
||||
function getConditionalTypeInstantiation(
|
||||
type: ConditionalType,
|
||||
mapper: TypeMapper,
|
||||
forConstraint: boolean,
|
||||
aliasSymbol?: Symbol,
|
||||
aliasTypeArguments?: readonly Type[],
|
||||
): Type {
|
||||
function getConditionalTypeInstantiation(type: ConditionalType, mapper: TypeMapper, forConstraint: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
|
||||
const root = type.root;
|
||||
if (root.outerTypeParameters) {
|
||||
// We are instantiating a conditional type that has one or more type parameters in scope. Apply the
|
||||
|
@ -20315,22 +20309,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
|
||||
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
|
||||
if (distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never)) {
|
||||
const mapperCallback = narrowingBaseType ?
|
||||
(t: Type) =>
|
||||
getConditionalType(
|
||||
root,
|
||||
prependTypeMapping(checkType, getSubstitutionType(narrowingBaseType, t, /*isNarrowed*/ true), newMapper),
|
||||
forConstraint,
|
||||
/*aliasSymbol*/ undefined,
|
||||
/*aliasTypeArguments*/ undefined,
|
||||
forNarrowing,
|
||||
) :
|
||||
(t: Type) => getConditionalType(root, prependTypeMapping(checkType, t, newMapper), forConstraint);
|
||||
if (narrowingBaseType) {
|
||||
result = mapType(distributionType, mapperCallback, /*noReductions*/ undefined, /*toIntersection*/ true);
|
||||
result = mapType(
|
||||
distributionType,
|
||||
(t: Type) =>
|
||||
getConditionalType(
|
||||
root,
|
||||
prependTypeMapping(checkType, getSubstitutionType(narrowingBaseType, t, /*isNarrowed*/ true), newMapper),
|
||||
forConstraint,
|
||||
/*aliasSymbol*/ undefined,
|
||||
/*aliasTypeArguments*/ undefined,
|
||||
forNarrowing,
|
||||
),
|
||||
/*noReductions*/ undefined,
|
||||
/*toIntersection*/ true,
|
||||
);
|
||||
}
|
||||
else {
|
||||
result = mapTypeWithAlias(distributionType, mapperCallback, aliasSymbol, aliasTypeArguments);
|
||||
result = mapTypeWithAlias(distributionType, (t: Type) => getConditionalType(root, prependTypeMapping(checkType, t, newMapper), forConstraint), aliasSymbol, aliasTypeArguments);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -20369,12 +20365,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
return result;
|
||||
}
|
||||
|
||||
function instantiateTypeWorker(
|
||||
type: Type,
|
||||
mapper: TypeMapper,
|
||||
aliasSymbol: Symbol | undefined,
|
||||
aliasTypeArguments: readonly Type[] | undefined,
|
||||
): Type {
|
||||
function instantiateTypeWorker(type: Type, mapper: TypeMapper, aliasSymbol: Symbol | undefined, aliasTypeArguments: readonly Type[] | undefined): Type {
|
||||
const flags = type.flags;
|
||||
if (flags & TypeFlags.TypeParameter) {
|
||||
return getMappedType(type, mapper);
|
||||
|
@ -20450,10 +20441,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
return type;
|
||||
}
|
||||
|
||||
function isGenericIndexedOrConditionalReturnType(type: Type): type is IndexedAccessType | ConditionalType {
|
||||
return !!(type.flags & (TypeFlags.IndexedAccess | TypeFlags.Conditional) && couldContainTypeVariables(type));
|
||||
}
|
||||
|
||||
function instantiateReverseMappedType(type: ReverseMappedType, mapper: TypeMapper) {
|
||||
const innerMappedType = instantiateType(type.mappedType, mapper);
|
||||
if (!(getObjectFlags(innerMappedType) & ObjectFlags.Mapped)) {
|
||||
|
@ -21669,7 +21656,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
for (const t of type.types) {
|
||||
hasInstantiable ||= !!(t.flags & TypeFlags.Instantiable);
|
||||
hasNullableOrEmpty ||= !!(t.flags & TypeFlags.Nullable) || isEmptyAnonymousObjectType(t);
|
||||
hasSubstitution ||= isNarrowingSubstitutionType(t); // This avoids displaying error messages with types like `T & T`
|
||||
hasSubstitution ||= isNarrowingSubstitutionType(t); // This avoids displaying error messages with types like `T & T` when narrowing a return type
|
||||
if (hasInstantiable && hasNullableOrEmpty || hasSubstitution) return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -29441,12 +29428,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
// up to five levels of aliased conditional expressions that are themselves declared as const variables.
|
||||
if (!isMatchingReference(reference, expr) && inlineLevel < 5) {
|
||||
const symbol = getResolvedSymbol(expr as Identifier);
|
||||
const inlineExpression = getNarrowableInlineExpression(symbol);
|
||||
if (inlineExpression && isConstantReference(reference)) {
|
||||
inlineLevel++;
|
||||
const result = narrowType(type, inlineExpression, assumeTrue);
|
||||
inlineLevel--;
|
||||
return result;
|
||||
if (isConstantVariable(symbol)) {
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isConstantReference(reference)) {
|
||||
inlineLevel++;
|
||||
const result = narrowType(type, declaration.initializer, assumeTrue);
|
||||
inlineLevel--;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
// falls through
|
||||
|
@ -29483,15 +29472,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
}
|
||||
}
|
||||
|
||||
function getNarrowableInlineExpression(symbol: Symbol): Expression | undefined {
|
||||
if (isConstantVariable(symbol)) {
|
||||
const declaration = symbol.valueDeclaration;
|
||||
if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer) {
|
||||
return declaration.initializer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeOfSymbolAtLocation(symbol: Symbol, location: Node) {
|
||||
symbol = getExportSymbolOfValueSymbolIfExported(symbol);
|
||||
|
||||
|
@ -45667,7 +45647,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
if (expr) {
|
||||
const unwrappedExpr = skipParentheses(expr);
|
||||
if (isConditionalExpression(unwrappedExpr)) {
|
||||
return checkReturnConditionalExpression(container, returnType, node, unwrappedExpr);
|
||||
return checkConditionalReturnExpression(container, returnType, node, unwrappedExpr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45688,19 +45668,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!isGenericIndexedOrConditionalReturnType(unwrappedReturnType)) {
|
||||
if (!(unwrappedReturnType.flags & (TypeFlags.IndexedAccess | TypeFlags.Conditional)) || !couldContainTypeVariables(unwrappedReturnType)) {
|
||||
checkTypeAssignableToAndOptionallyElaborate(unwrappedExprType, unwrappedReturnType, errorNode, expr);
|
||||
return;
|
||||
}
|
||||
const allTypeParameters = appendTypeParameters(getOuterTypeParameters(container, /*includeThisTypes*/ false), getEffectiveTypeParameterDeclarations(container as DeclarationWithTypeParameters));
|
||||
const narrowableTypeParameters = allTypeParameters && getNarrowableTypeParameters(allTypeParameters);
|
||||
|
||||
// >> TODO: another optimization would be to check if any of the narrowable type parameters
|
||||
// match the types in the return type that can be narrowed
|
||||
if (
|
||||
!narrowableTypeParameters ||
|
||||
!narrowableTypeParameters.length ||
|
||||
!isNarrowableReturnType(unwrappedReturnType)
|
||||
!isNarrowableReturnType(unwrappedReturnType as ConditionalType | IndexedAccessType)
|
||||
) {
|
||||
checkTypeAssignableToAndOptionallyElaborate(unwrappedExprType, unwrappedReturnType, errorNode, expr);
|
||||
return;
|
||||
|
@ -45779,7 +45757,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
checkTypeAssignableToAndOptionallyElaborate(narrowedUnwrappedExprType, narrowedReturnType, errorNode, expr);
|
||||
}
|
||||
|
||||
function checkReturnConditionalExpression(
|
||||
function checkConditionalReturnExpression(
|
||||
container: SignatureDeclaration,
|
||||
returnType: Type,
|
||||
node: ReturnStatement,
|
||||
|
@ -45860,8 +45838,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
|||
}
|
||||
}
|
||||
|
||||
// A narrowable indexed access type is one that has the shape `A[T]`,
|
||||
// where `T` is a narrowable type parameter.
|
||||
function isNarrowableReturnType(returnType: IndexedAccessType | ConditionalType): boolean {
|
||||
return isConditionalType(returnType)
|
||||
? isNarrowableConditionalType(returnType)
|
||||
|
|
|
@ -6917,7 +6917,6 @@ export interface SubstitutionType extends InstantiableType {
|
|||
objectFlags: ObjectFlags;
|
||||
baseType: Type; // Target type
|
||||
constraint: Type; // Constraint that target type is known to satisfy
|
||||
/** @internal */
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
|
|
@ -4445,12 +4445,12 @@ export function canHaveFlowNode(node: Node): node is HasFlowNode {
|
|||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.QualifiedName:
|
||||
case SyntaxKind.MetaProperty:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.BindingElement:
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
|
|
|
@ -10,8 +10,8 @@ module M2 {
|
|||
import A = M1
|
||||
export function compose() {
|
||||
A.reduce(arguments, compose2);
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
return function (x) { return g(f(x)); }
|
||||
};
|
||||
};
|
||||
|
|
|
@ -44,30 +44,30 @@ module M2 {
|
|||
>A : Symbol(A, Decl(returnTypeParameterWithModules.ts, 5, 11))
|
||||
>reduce : Symbol(A.reduce, Decl(returnTypeParameterWithModules.ts, 0, 11))
|
||||
>arguments : Symbol(arguments)
|
||||
>compose2 : Symbol(compose2, Decl(returnTypeParameterWithModules.ts, 9, 4))
|
||||
>compose2 : Symbol(compose2, Decl(returnTypeParameterWithModules.ts, 9, 6))
|
||||
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
>compose2 : Symbol(compose2, Decl(returnTypeParameterWithModules.ts, 9, 4))
|
||||
>B : Symbol(B, Decl(returnTypeParameterWithModules.ts, 10, 27))
|
||||
>C : Symbol(C, Decl(returnTypeParameterWithModules.ts, 10, 29))
|
||||
>D : Symbol(D, Decl(returnTypeParameterWithModules.ts, 10, 32))
|
||||
>g : Symbol(g, Decl(returnTypeParameterWithModules.ts, 10, 36))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 10, 40))
|
||||
>B : Symbol(B, Decl(returnTypeParameterWithModules.ts, 10, 27))
|
||||
>C : Symbol(C, Decl(returnTypeParameterWithModules.ts, 10, 29))
|
||||
>f : Symbol(f, Decl(returnTypeParameterWithModules.ts, 10, 51))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 10, 56))
|
||||
>D : Symbol(D, Decl(returnTypeParameterWithModules.ts, 10, 32))
|
||||
>B : Symbol(B, Decl(returnTypeParameterWithModules.ts, 10, 27))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 10, 70))
|
||||
>D : Symbol(D, Decl(returnTypeParameterWithModules.ts, 10, 32))
|
||||
>C : Symbol(C, Decl(returnTypeParameterWithModules.ts, 10, 29))
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
>compose2 : Symbol(compose2, Decl(returnTypeParameterWithModules.ts, 9, 6))
|
||||
>B : Symbol(B, Decl(returnTypeParameterWithModules.ts, 10, 29))
|
||||
>C : Symbol(C, Decl(returnTypeParameterWithModules.ts, 10, 31))
|
||||
>D : Symbol(D, Decl(returnTypeParameterWithModules.ts, 10, 34))
|
||||
>g : Symbol(g, Decl(returnTypeParameterWithModules.ts, 10, 38))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 10, 42))
|
||||
>B : Symbol(B, Decl(returnTypeParameterWithModules.ts, 10, 29))
|
||||
>C : Symbol(C, Decl(returnTypeParameterWithModules.ts, 10, 31))
|
||||
>f : Symbol(f, Decl(returnTypeParameterWithModules.ts, 10, 53))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 10, 58))
|
||||
>D : Symbol(D, Decl(returnTypeParameterWithModules.ts, 10, 34))
|
||||
>B : Symbol(B, Decl(returnTypeParameterWithModules.ts, 10, 29))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 10, 72))
|
||||
>D : Symbol(D, Decl(returnTypeParameterWithModules.ts, 10, 34))
|
||||
>C : Symbol(C, Decl(returnTypeParameterWithModules.ts, 10, 31))
|
||||
|
||||
return function (x) { return g(f(x)); }
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 11, 21))
|
||||
>g : Symbol(g, Decl(returnTypeParameterWithModules.ts, 10, 36))
|
||||
>f : Symbol(f, Decl(returnTypeParameterWithModules.ts, 10, 51))
|
||||
>g : Symbol(g, Decl(returnTypeParameterWithModules.ts, 10, 38))
|
||||
>f : Symbol(f, Decl(returnTypeParameterWithModules.ts, 10, 53))
|
||||
>x : Symbol(x, Decl(returnTypeParameterWithModules.ts, 11, 21))
|
||||
|
||||
};
|
||||
|
|
|
@ -70,8 +70,8 @@ module M2 {
|
|||
>compose2 : <B, C, D>(g: (x: B) => C, f: (x: D) => B) => (x: D) => C
|
||||
> : ^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^
|
||||
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
>compose2 : <B, C, D>(g: (x: B) => C, f: (x: D) => B) => (x: D) => C
|
||||
> : ^ ^^ ^^ ^^ ^^ ^^ ^^ ^^^^^
|
||||
>g : (x: B) => C
|
||||
|
|
|
@ -7,8 +7,8 @@ module M2 {
|
|||
import A = M1
|
||||
export function compose() {
|
||||
A.reduce(arguments, compose2);
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
};
|
||||
export function compose2<B, C, D>(g: (x: B) => C, f: (x: D) => B): (x: D) => C {
|
||||
return function (x) { return g(f(x)); }
|
||||
};
|
||||
};
|
Загрузка…
Ссылка в новой задаче