This commit is contained in:
Gabriela Araujo Britto 2024-10-07 13:36:11 -07:00
Родитель 76718d8755
Коммит 20b79eb8c8
7 изменённых файлов: 59 добавлений и 84 удалений

Просмотреть файл

@ -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)); }
};
};