From 7f11456f4afd816776c08208389e10d8c5a62dd8 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 13 Mar 2024 08:48:21 -0700 Subject: [PATCH 01/10] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#57751=20(Excl?= =?UTF-8?q?ude=20generic=20string-like=20types=20f...)=20into=20release-5.?= =?UTF-8?q?4=20(#57753)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anders Hejlsberg --- src/compiler/checker.ts | 11 ++- ...tionReductionGenericStringLikeType.symbols | 77 +++++++++++++++++++ ...ectionReductionGenericStringLikeType.types | 44 +++++++++++ ...ersectionReductionGenericStringLikeType.ts | 31 ++++++++ 4 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/intersectionReductionGenericStringLikeType.symbols create mode 100644 tests/baselines/reference/intersectionReductionGenericStringLikeType.types create mode 100644 tests/cases/compiler/intersectionReductionGenericStringLikeType.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f9ab74b053256..583c4827e63c8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17624,7 +17624,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const typeVarIndex = typeSet[0].flags & TypeFlags.TypeVariable ? 0 : 1; const typeVariable = typeSet[typeVarIndex]; const primitiveType = typeSet[1 - typeVarIndex]; - if (typeVariable.flags & TypeFlags.TypeVariable && (primitiveType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) || includes & TypeFlags.IncludesEmptyObject)) { + if ( + typeVariable.flags & TypeFlags.TypeVariable && + (primitiveType.flags & (TypeFlags.Primitive | TypeFlags.NonPrimitive) && !isGenericStringLikeType(primitiveType) || includes & TypeFlags.IncludesEmptyObject) + ) { // We have an intersection T & P or P & T, where T is a type variable and P is a primitive type, the object type, or {}. const constraint = getBaseConstraintOfType(typeVariable); // Check that T's constraint is similarly composed of primitive types, the object type, or {}. @@ -18374,6 +18377,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { !!(type.flags & TypeFlags.StringMapping) && isPatternLiteralPlaceholderType((type as StringMappingType).type); } + function isGenericStringLikeType(type: Type) { + return !!(type.flags & (TypeFlags.TemplateLiteral | TypeFlags.StringMapping)) && !isPatternLiteralType(type); + } + function isGenericType(type: Type): boolean { return !!getGenericObjectFlags(type); } @@ -18402,7 +18409,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return (type as SubstitutionType).objectFlags & ObjectFlags.IsGenericType; } return (type.flags & TypeFlags.InstantiableNonPrimitive || isGenericMappedType(type) || isGenericTupleType(type) ? ObjectFlags.IsGenericObjectType : 0) | - (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index | TypeFlags.TemplateLiteral | TypeFlags.StringMapping) && !isPatternLiteralType(type) ? ObjectFlags.IsGenericIndexType : 0); + (type.flags & (TypeFlags.InstantiableNonPrimitive | TypeFlags.Index) || isGenericStringLikeType(type) ? ObjectFlags.IsGenericIndexType : 0); } function getSimplifiedType(type: Type, writing: boolean): Type { diff --git a/tests/baselines/reference/intersectionReductionGenericStringLikeType.symbols b/tests/baselines/reference/intersectionReductionGenericStringLikeType.symbols new file mode 100644 index 0000000000000..ad256535dde14 --- /dev/null +++ b/tests/baselines/reference/intersectionReductionGenericStringLikeType.symbols @@ -0,0 +1,77 @@ +//// [tests/cases/compiler/intersectionReductionGenericStringLikeType.ts] //// + +=== intersectionReductionGenericStringLikeType.ts === +// https://github.com/microsoft/TypeScript/issues/57736 + +type obj = { +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) + + foo: 1; +>foo : Symbol(foo, Decl(intersectionReductionGenericStringLikeType.ts, 2, 12)) + + bar: 2; +>bar : Symbol(bar, Decl(intersectionReductionGenericStringLikeType.ts, 3, 11)) + +}; + +type keyContaining1< +>keyContaining1 : Symbol(keyContaining1, Decl(intersectionReductionGenericStringLikeType.ts, 5, 2)) + + str extends string, +>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 7, 20)) + + keys extends keyof obj = keyof obj, +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 8, 23)) +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) + +> = keys extends infer key extends keyof obj +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 8, 23)) +>key : Symbol(key, Decl(intersectionReductionGenericStringLikeType.ts, 10, 22)) +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) + + ? key extends `${string}${str}${string}` +>key : Symbol(key, Decl(intersectionReductionGenericStringLikeType.ts, 10, 22)) +>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 7, 20)) + + ? obj[key] +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) +>key : Symbol(key, Decl(intersectionReductionGenericStringLikeType.ts, 10, 22)) + + : never + : never; + +type _1 = keyContaining1<"foo">; // 1 +>_1 : Symbol(_1, Decl(intersectionReductionGenericStringLikeType.ts, 14, 12)) +>keyContaining1 : Symbol(keyContaining1, Decl(intersectionReductionGenericStringLikeType.ts, 5, 2)) + +type keyContaining2< +>keyContaining2 : Symbol(keyContaining2, Decl(intersectionReductionGenericStringLikeType.ts, 16, 32)) + + str extends string, +>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 18, 20)) + + keys extends keyof obj = keyof obj, +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23)) +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) + +> = keys extends keys +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23)) +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23)) + + ? keys extends `${string}${str}${string}` +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23)) +>str : Symbol(str, Decl(intersectionReductionGenericStringLikeType.ts, 18, 20)) + + ? obj[keys] +>obj : Symbol(obj, Decl(intersectionReductionGenericStringLikeType.ts, 0, 0)) +>keys : Symbol(keys, Decl(intersectionReductionGenericStringLikeType.ts, 19, 23)) + + : never + : never; + +type _2 = keyContaining2<"foo">; // 1 +>_2 : Symbol(_2, Decl(intersectionReductionGenericStringLikeType.ts, 25, 12)) +>keyContaining2 : Symbol(keyContaining2, Decl(intersectionReductionGenericStringLikeType.ts, 16, 32)) + diff --git a/tests/baselines/reference/intersectionReductionGenericStringLikeType.types b/tests/baselines/reference/intersectionReductionGenericStringLikeType.types new file mode 100644 index 0000000000000..0d3af56acf2ad --- /dev/null +++ b/tests/baselines/reference/intersectionReductionGenericStringLikeType.types @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/intersectionReductionGenericStringLikeType.ts] //// + +=== intersectionReductionGenericStringLikeType.ts === +// https://github.com/microsoft/TypeScript/issues/57736 + +type obj = { +>obj : { foo: 1; bar: 2; } + + foo: 1; +>foo : 1 + + bar: 2; +>bar : 2 + +}; + +type keyContaining1< +>keyContaining1 : keyContaining1 + + str extends string, + keys extends keyof obj = keyof obj, +> = keys extends infer key extends keyof obj + ? key extends `${string}${str}${string}` + ? obj[key] + : never + : never; + +type _1 = keyContaining1<"foo">; // 1 +>_1 : 1 + +type keyContaining2< +>keyContaining2 : keyContaining2 + + str extends string, + keys extends keyof obj = keyof obj, +> = keys extends keys + ? keys extends `${string}${str}${string}` + ? obj[keys] + : never + : never; + +type _2 = keyContaining2<"foo">; // 1 +>_2 : 1 + diff --git a/tests/cases/compiler/intersectionReductionGenericStringLikeType.ts b/tests/cases/compiler/intersectionReductionGenericStringLikeType.ts new file mode 100644 index 0000000000000..c59a4321d074d --- /dev/null +++ b/tests/cases/compiler/intersectionReductionGenericStringLikeType.ts @@ -0,0 +1,31 @@ +// @strict: true +// @noEmit: true + +// https://github.com/microsoft/TypeScript/issues/57736 + +type obj = { + foo: 1; + bar: 2; +}; + +type keyContaining1< + str extends string, + keys extends keyof obj = keyof obj, +> = keys extends infer key extends keyof obj + ? key extends `${string}${str}${string}` + ? obj[key] + : never + : never; + +type _1 = keyContaining1<"foo">; // 1 + +type keyContaining2< + str extends string, + keys extends keyof obj = keyof obj, +> = keys extends keys + ? keys extends `${string}${str}${string}` + ? obj[keys] + : never + : never; + +type _2 = keyContaining2<"foo">; // 1 From 485c7c5d08f985528a83d9879658912181ef7f11 Mon Sep 17 00:00:00 2001 From: Gabriela Araujo Britto Date: Fri, 15 Mar 2024 12:26:01 -0700 Subject: [PATCH 02/10] =?UTF-8?q?Revert=20"Allow=20(non-assert)=20type=20p?= =?UTF-8?q?redicates=20to=20narrow=20by=20discriminant"=E2=80=A6=20(#57795?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/compiler/checker.ts | 98 ++++++------- src/compiler/commandLineParser.ts | 1 + .../discriminantNarrowingCouldBeCircular.js | 69 +++++++++ ...scriminantNarrowingCouldBeCircular.symbols | 129 ++++++++++++++++ ...discriminantNarrowingCouldBeCircular.types | 138 ++++++++++++++++++ ...ePredicatesCanNarrowByDiscriminant.symbols | 8 +- ...ypePredicatesCanNarrowByDiscriminant.types | 12 +- .../discriminantNarrowingCouldBeCircular.ts | 40 +++++ 8 files changed, 434 insertions(+), 61 deletions(-) create mode 100644 tests/baselines/reference/discriminantNarrowingCouldBeCircular.js create mode 100644 tests/baselines/reference/discriminantNarrowingCouldBeCircular.symbols create mode 100644 tests/baselines/reference/discriminantNarrowingCouldBeCircular.types create mode 100644 tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 583c4827e63c8..cf16285cdb1a8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26741,11 +26741,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function hasMatchingArgument(expression: CallExpression | NewExpression, reference: Node) { if (expression.arguments) { for (const argument of expression.arguments) { - if ( - isOrContainsMatchingReference(reference, argument) - || optionalChainContainsReference(argument, reference) - || getCandidateDiscriminantPropertyAccess(argument, reference) - ) { + if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference)) { return true; } } @@ -26759,51 +26755,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function getCandidateDiscriminantPropertyAccess(expr: Expression, reference: Node) { - if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { - // When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in - // getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or - // parameter declared in the same parameter list is a candidate. - if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - const declaration = symbol.valueDeclaration; - if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { - return declaration; - } - } - } - else if (isAccessExpression(expr)) { - // An access expression is a candidate if the reference matches the left hand expression. - if (isMatchingReference(reference, expr.expression)) { - return expr; - } - } - else if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - if (isConstantVariable(symbol)) { - const declaration = symbol.valueDeclaration!; - // Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind' - if ( - isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && - isMatchingReference(reference, declaration.initializer.expression) - ) { - return declaration.initializer; - } - // Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind' - if (isBindingElement(declaration) && !declaration.initializer) { - const parent = declaration.parent.parent; - if ( - isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && - isMatchingReference(reference, parent.initializer) - ) { - return declaration; - } - } - } - } - return undefined; - } - function getFlowNodeId(flow: FlowNode): number { if (!flow.id || flow.id < 0) { flow.id = nextFlowId; @@ -28160,12 +28111,57 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } + function getCandidateDiscriminantPropertyAccess(expr: Expression) { + if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { + // When the reference is a binding pattern or function or arrow expression, we are narrowing a pesudo-reference in + // getNarrowedTypeOfSymbol. An identifier for a destructuring variable declared in the same binding pattern or + // parameter declared in the same parameter list is a candidate. + if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + const declaration = symbol.valueDeclaration; + if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { + return declaration; + } + } + } + else if (isAccessExpression(expr)) { + // An access expression is a candidate if the reference matches the left hand expression. + if (isMatchingReference(reference, expr.expression)) { + return expr; + } + } + else if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + if (isConstantVariable(symbol)) { + const declaration = symbol.valueDeclaration!; + // Given 'const x = obj.kind', allow 'x' as an alias for 'obj.kind' + if ( + isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && + isMatchingReference(reference, declaration.initializer.expression) + ) { + return declaration.initializer; + } + // Given 'const { kind: x } = obj', allow 'x' as an alias for 'obj.kind' + if (isBindingElement(declaration) && !declaration.initializer) { + const parent = declaration.parent.parent; + if ( + isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && + isMatchingReference(reference, parent.initializer) + ) { + return declaration; + } + } + } + } + return undefined; + } + function getDiscriminantPropertyAccess(expr: Expression, computedType: Type) { // As long as the computed type is a subset of the declared type, we use the full declared type to detect // a discriminant property. In cases where the computed type isn't a subset, e.g because of a preceding type // predicate narrowing, we use the actual computed type. if (declaredType.flags & TypeFlags.Union || computedType.flags & TypeFlags.Union) { - const access = getCandidateDiscriminantPropertyAccess(expr, reference); + const access = getCandidateDiscriminantPropertyAccess(expr); if (access) { const name = getAccessedPropertyName(access); if (name) { diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index feee1493eb16a..d513c5793dadf 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -3505,6 +3505,7 @@ export function convertJsonOption( convertJsonOption(opt.element, value, basePath, errors, propertyAssignment, valueExpression, sourceFile); } else if (!isString(opt.type)) { + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion return convertJsonOptionOfCustomType(opt as CommandLineOptionOfCustomType, value as string, errors, valueExpression, sourceFile); } const validatedValue = validateJsonOptionValue(opt, value, errors, valueExpression, sourceFile); diff --git a/tests/baselines/reference/discriminantNarrowingCouldBeCircular.js b/tests/baselines/reference/discriminantNarrowingCouldBeCircular.js new file mode 100644 index 0000000000000..2cc50e16b98cd --- /dev/null +++ b/tests/baselines/reference/discriminantNarrowingCouldBeCircular.js @@ -0,0 +1,69 @@ +//// [tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts] //// + +//// [discriminantNarrowingCouldBeCircular.ts] +// #57705, 57690 +declare function is(v: T): v is T; +const o: Record | undefined = {}; +if (o) { + for (const key in o) { + const value = o[key]; + if (is(value)) { + } + } +} + +type SomeRecord = { a: string }; +declare const kPresentationInheritanceParents: { [tagName: string]: string[] }; +declare function parentElementOrShadowHost(element: SomeRecord): SomeRecord | undefined; + +function getImplicitAriaRole(element: SomeRecord) { + let ancestor: SomeRecord | null = element; + while (ancestor) { + const parent = parentElementOrShadowHost(ancestor); + const parents = kPresentationInheritanceParents[ancestor.a]; + if (!parents || !parent || !parents.includes(parent.a)) + break; + ancestor = parent; + } +} + +declare function isPlainObject2( + data: unknown, + ): data is Record; + + declare const myObj2: unknown; + if (isPlainObject2(myObj2)) { + for (const key of ["a", "b", "c"]) { + const deeper = myObj2[key]; + const deeperKeys = isPlainObject2(deeper) ? Object.keys(deeper) : []; + } + } + + +//// [discriminantNarrowingCouldBeCircular.js] +"use strict"; +var o = {}; +if (o) { + for (var key in o) { + var value = o[key]; + if (is(value)) { + } + } +} +function getImplicitAriaRole(element) { + var ancestor = element; + while (ancestor) { + var parent = parentElementOrShadowHost(ancestor); + var parents = kPresentationInheritanceParents[ancestor.a]; + if (!parents || !parent || !parents.includes(parent.a)) + break; + ancestor = parent; + } +} +if (isPlainObject2(myObj2)) { + for (var _i = 0, _a = ["a", "b", "c"]; _i < _a.length; _i++) { + var key = _a[_i]; + var deeper = myObj2[key]; + var deeperKeys = isPlainObject2(deeper) ? Object.keys(deeper) : []; + } +} diff --git a/tests/baselines/reference/discriminantNarrowingCouldBeCircular.symbols b/tests/baselines/reference/discriminantNarrowingCouldBeCircular.symbols new file mode 100644 index 0000000000000..63c7e9dc7f5af --- /dev/null +++ b/tests/baselines/reference/discriminantNarrowingCouldBeCircular.symbols @@ -0,0 +1,129 @@ +//// [tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts] //// + +=== discriminantNarrowingCouldBeCircular.ts === +// #57705, 57690 +declare function is(v: T): v is T; +>is : Symbol(is, Decl(discriminantNarrowingCouldBeCircular.ts, 0, 0)) +>T : Symbol(T, Decl(discriminantNarrowingCouldBeCircular.ts, 1, 20)) +>v : Symbol(v, Decl(discriminantNarrowingCouldBeCircular.ts, 1, 23)) +>T : Symbol(T, Decl(discriminantNarrowingCouldBeCircular.ts, 1, 20)) +>v : Symbol(v, Decl(discriminantNarrowingCouldBeCircular.ts, 1, 23)) +>T : Symbol(T, Decl(discriminantNarrowingCouldBeCircular.ts, 1, 20)) + +const o: Record | undefined = {}; +>o : Symbol(o, Decl(discriminantNarrowingCouldBeCircular.ts, 2, 5)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +if (o) { +>o : Symbol(o, Decl(discriminantNarrowingCouldBeCircular.ts, 2, 5)) + + for (const key in o) { +>key : Symbol(key, Decl(discriminantNarrowingCouldBeCircular.ts, 4, 12)) +>o : Symbol(o, Decl(discriminantNarrowingCouldBeCircular.ts, 2, 5)) + + const value = o[key]; +>value : Symbol(value, Decl(discriminantNarrowingCouldBeCircular.ts, 5, 9)) +>o : Symbol(o, Decl(discriminantNarrowingCouldBeCircular.ts, 2, 5)) +>key : Symbol(key, Decl(discriminantNarrowingCouldBeCircular.ts, 4, 12)) + + if (is(value)) { +>is : Symbol(is, Decl(discriminantNarrowingCouldBeCircular.ts, 0, 0)) +>value : Symbol(value, Decl(discriminantNarrowingCouldBeCircular.ts, 5, 9)) + } + } +} + +type SomeRecord = { a: string }; +>SomeRecord : Symbol(SomeRecord, Decl(discriminantNarrowingCouldBeCircular.ts, 9, 1)) +>a : Symbol(a, Decl(discriminantNarrowingCouldBeCircular.ts, 11, 19)) + +declare const kPresentationInheritanceParents: { [tagName: string]: string[] }; +>kPresentationInheritanceParents : Symbol(kPresentationInheritanceParents, Decl(discriminantNarrowingCouldBeCircular.ts, 12, 13)) +>tagName : Symbol(tagName, Decl(discriminantNarrowingCouldBeCircular.ts, 12, 50)) + +declare function parentElementOrShadowHost(element: SomeRecord): SomeRecord | undefined; +>parentElementOrShadowHost : Symbol(parentElementOrShadowHost, Decl(discriminantNarrowingCouldBeCircular.ts, 12, 79)) +>element : Symbol(element, Decl(discriminantNarrowingCouldBeCircular.ts, 13, 43)) +>SomeRecord : Symbol(SomeRecord, Decl(discriminantNarrowingCouldBeCircular.ts, 9, 1)) +>SomeRecord : Symbol(SomeRecord, Decl(discriminantNarrowingCouldBeCircular.ts, 9, 1)) + +function getImplicitAriaRole(element: SomeRecord) { +>getImplicitAriaRole : Symbol(getImplicitAriaRole, Decl(discriminantNarrowingCouldBeCircular.ts, 13, 88)) +>element : Symbol(element, Decl(discriminantNarrowingCouldBeCircular.ts, 15, 29)) +>SomeRecord : Symbol(SomeRecord, Decl(discriminantNarrowingCouldBeCircular.ts, 9, 1)) + + let ancestor: SomeRecord | null = element; +>ancestor : Symbol(ancestor, Decl(discriminantNarrowingCouldBeCircular.ts, 16, 5)) +>SomeRecord : Symbol(SomeRecord, Decl(discriminantNarrowingCouldBeCircular.ts, 9, 1)) +>element : Symbol(element, Decl(discriminantNarrowingCouldBeCircular.ts, 15, 29)) + + while (ancestor) { +>ancestor : Symbol(ancestor, Decl(discriminantNarrowingCouldBeCircular.ts, 16, 5)) + + const parent = parentElementOrShadowHost(ancestor); +>parent : Symbol(parent, Decl(discriminantNarrowingCouldBeCircular.ts, 18, 9)) +>parentElementOrShadowHost : Symbol(parentElementOrShadowHost, Decl(discriminantNarrowingCouldBeCircular.ts, 12, 79)) +>ancestor : Symbol(ancestor, Decl(discriminantNarrowingCouldBeCircular.ts, 16, 5)) + + const parents = kPresentationInheritanceParents[ancestor.a]; +>parents : Symbol(parents, Decl(discriminantNarrowingCouldBeCircular.ts, 19, 9)) +>kPresentationInheritanceParents : Symbol(kPresentationInheritanceParents, Decl(discriminantNarrowingCouldBeCircular.ts, 12, 13)) +>ancestor.a : Symbol(a, Decl(discriminantNarrowingCouldBeCircular.ts, 11, 19)) +>ancestor : Symbol(ancestor, Decl(discriminantNarrowingCouldBeCircular.ts, 16, 5)) +>a : Symbol(a, Decl(discriminantNarrowingCouldBeCircular.ts, 11, 19)) + + if (!parents || !parent || !parents.includes(parent.a)) +>parents : Symbol(parents, Decl(discriminantNarrowingCouldBeCircular.ts, 19, 9)) +>parent : Symbol(parent, Decl(discriminantNarrowingCouldBeCircular.ts, 18, 9)) +>parents.includes : Symbol(Array.includes, Decl(lib.es2016.array.include.d.ts, --, --)) +>parents : Symbol(parents, Decl(discriminantNarrowingCouldBeCircular.ts, 19, 9)) +>includes : Symbol(Array.includes, Decl(lib.es2016.array.include.d.ts, --, --)) +>parent.a : Symbol(a, Decl(discriminantNarrowingCouldBeCircular.ts, 11, 19)) +>parent : Symbol(parent, Decl(discriminantNarrowingCouldBeCircular.ts, 18, 9)) +>a : Symbol(a, Decl(discriminantNarrowingCouldBeCircular.ts, 11, 19)) + + break; + ancestor = parent; +>ancestor : Symbol(ancestor, Decl(discriminantNarrowingCouldBeCircular.ts, 16, 5)) +>parent : Symbol(parent, Decl(discriminantNarrowingCouldBeCircular.ts, 18, 9)) + } +} + +declare function isPlainObject2( +>isPlainObject2 : Symbol(isPlainObject2, Decl(discriminantNarrowingCouldBeCircular.ts, 24, 1)) +>T : Symbol(T, Decl(discriminantNarrowingCouldBeCircular.ts, 26, 32)) + + data: unknown, +>data : Symbol(data, Decl(discriminantNarrowingCouldBeCircular.ts, 26, 35)) + + ): data is Record; +>data : Symbol(data, Decl(discriminantNarrowingCouldBeCircular.ts, 26, 35)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) + + declare const myObj2: unknown; +>myObj2 : Symbol(myObj2, Decl(discriminantNarrowingCouldBeCircular.ts, 30, 15)) + + if (isPlainObject2(myObj2)) { +>isPlainObject2 : Symbol(isPlainObject2, Decl(discriminantNarrowingCouldBeCircular.ts, 24, 1)) +>myObj2 : Symbol(myObj2, Decl(discriminantNarrowingCouldBeCircular.ts, 30, 15)) + + for (const key of ["a", "b", "c"]) { +>key : Symbol(key, Decl(discriminantNarrowingCouldBeCircular.ts, 32, 16)) + + const deeper = myObj2[key]; +>deeper : Symbol(deeper, Decl(discriminantNarrowingCouldBeCircular.ts, 33, 13)) +>myObj2 : Symbol(myObj2, Decl(discriminantNarrowingCouldBeCircular.ts, 30, 15)) +>key : Symbol(key, Decl(discriminantNarrowingCouldBeCircular.ts, 32, 16)) + + const deeperKeys = isPlainObject2(deeper) ? Object.keys(deeper) : []; +>deeperKeys : Symbol(deeperKeys, Decl(discriminantNarrowingCouldBeCircular.ts, 34, 13)) +>isPlainObject2 : Symbol(isPlainObject2, Decl(discriminantNarrowingCouldBeCircular.ts, 24, 1)) +>deeper : Symbol(deeper, Decl(discriminantNarrowingCouldBeCircular.ts, 33, 13)) +>Object.keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --)) +>keys : Symbol(ObjectConstructor.keys, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --)) +>deeper : Symbol(deeper, Decl(discriminantNarrowingCouldBeCircular.ts, 33, 13)) + } + } + diff --git a/tests/baselines/reference/discriminantNarrowingCouldBeCircular.types b/tests/baselines/reference/discriminantNarrowingCouldBeCircular.types new file mode 100644 index 0000000000000..63b27fb6c352a --- /dev/null +++ b/tests/baselines/reference/discriminantNarrowingCouldBeCircular.types @@ -0,0 +1,138 @@ +//// [tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts] //// + +=== discriminantNarrowingCouldBeCircular.ts === +// #57705, 57690 +declare function is(v: T): v is T; +>is : (v: T) => v is T +>v : T + +const o: Record | undefined = {}; +>o : Record | undefined +>{} : {} + +if (o) { +>o : Record + + for (const key in o) { +>key : string +>o : Record + + const value = o[key]; +>value : string +>o[key] : string +>o : Record +>key : string + + if (is(value)) { +>is(value) : boolean +>is : (v: T) => v is T +>value : string + } + } +} + +type SomeRecord = { a: string }; +>SomeRecord : { a: string; } +>a : string + +declare const kPresentationInheritanceParents: { [tagName: string]: string[] }; +>kPresentationInheritanceParents : { [tagName: string]: string[]; } +>tagName : string + +declare function parentElementOrShadowHost(element: SomeRecord): SomeRecord | undefined; +>parentElementOrShadowHost : (element: SomeRecord) => SomeRecord | undefined +>element : SomeRecord + +function getImplicitAriaRole(element: SomeRecord) { +>getImplicitAriaRole : (element: SomeRecord) => void +>element : SomeRecord + + let ancestor: SomeRecord | null = element; +>ancestor : SomeRecord | null +>element : SomeRecord + + while (ancestor) { +>ancestor : SomeRecord + + const parent = parentElementOrShadowHost(ancestor); +>parent : SomeRecord | undefined +>parentElementOrShadowHost(ancestor) : SomeRecord | undefined +>parentElementOrShadowHost : (element: SomeRecord) => SomeRecord | undefined +>ancestor : SomeRecord + + const parents = kPresentationInheritanceParents[ancestor.a]; +>parents : string[] +>kPresentationInheritanceParents[ancestor.a] : string[] +>kPresentationInheritanceParents : { [tagName: string]: string[]; } +>ancestor.a : string +>ancestor : SomeRecord +>a : string + + if (!parents || !parent || !parents.includes(parent.a)) +>!parents || !parent || !parents.includes(parent.a) : boolean +>!parents || !parent : boolean +>!parents : false +>parents : string[] +>!parent : boolean +>parent : SomeRecord | undefined +>!parents.includes(parent.a) : boolean +>parents.includes(parent.a) : boolean +>parents.includes : (searchElement: string, fromIndex?: number | undefined) => boolean +>parents : string[] +>includes : (searchElement: string, fromIndex?: number | undefined) => boolean +>parent.a : string +>parent : SomeRecord +>a : string + + break; + ancestor = parent; +>ancestor = parent : SomeRecord +>ancestor : SomeRecord | null +>parent : SomeRecord + } +} + +declare function isPlainObject2( +>isPlainObject2 : (data: unknown) => data is Record + + data: unknown, +>data : unknown + + ): data is Record; + + declare const myObj2: unknown; +>myObj2 : unknown + + if (isPlainObject2(myObj2)) { +>isPlainObject2(myObj2) : boolean +>isPlainObject2 : (data: unknown) => data is Record +>myObj2 : unknown + + for (const key of ["a", "b", "c"]) { +>key : string +>["a", "b", "c"] : string[] +>"a" : "a" +>"b" : "b" +>"c" : "c" + + const deeper = myObj2[key]; +>deeper : unknown +>myObj2[key] : unknown +>myObj2 : Record +>key : string + + const deeperKeys = isPlainObject2(deeper) ? Object.keys(deeper) : []; +>deeperKeys : string[] +>isPlainObject2(deeper) ? Object.keys(deeper) : [] : string[] +>isPlainObject2(deeper) : boolean +>isPlainObject2 : (data: unknown) => data is Record +>deeper : unknown +>Object.keys(deeper) : string[] +>Object.keys : { (o: object): string[]; (o: {}): string[]; } +>Object : ObjectConstructor +>keys : { (o: object): string[]; (o: {}): string[]; } +>deeper : Record +>[] : never[] + } + } + diff --git a/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.symbols b/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.symbols index e1bacc007b26a..6c33043410585 100644 --- a/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.symbols +++ b/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.symbols @@ -28,9 +28,9 @@ if (isOneOf(fruit.kind, ['apple', 'banana'] as const)) { >const : Symbol(const) fruit.kind ->fruit.kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 22), Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 41)) +>fruit.kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 22), Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 41), Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 62)) >fruit : Symbol(fruit, Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 13)) ->kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 22), Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 41)) +>kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 22), Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 41), Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 62)) fruit >fruit : Symbol(fruit, Decl(typePredicatesCanNarrowByDiscriminant.ts, 1, 13)) @@ -54,9 +54,9 @@ if (isOneOf(kind, ['apple', 'banana'] as const)) { >const : Symbol(const) fruit2.kind ->fruit2.kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 23), Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 42)) +>fruit2.kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 23), Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 42), Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 63)) >fruit2 : Symbol(fruit2, Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 13)) ->kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 23), Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 42)) +>kind : Symbol(kind, Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 23), Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 42), Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 63)) fruit2 >fruit2 : Symbol(fruit2, Decl(typePredicatesCanNarrowByDiscriminant.ts, 9, 13)) diff --git a/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.types b/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.types index 3dc7156b1fa08..bc14536bc8c5f 100644 --- a/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.types +++ b/tests/baselines/reference/typePredicatesCanNarrowByDiscriminant.types @@ -26,11 +26,11 @@ if (isOneOf(fruit.kind, ['apple', 'banana'] as const)) { fruit.kind >fruit.kind : "apple" | "banana" ->fruit : { kind: "apple"; } | { kind: "banana"; } +>fruit : { kind: "apple"; } | { kind: "banana"; } | { kind: "cherry"; } >kind : "apple" | "banana" fruit ->fruit : { kind: "apple"; } | { kind: "banana"; } +>fruit : { kind: "apple"; } | { kind: "banana"; } | { kind: "cherry"; } } declare const fruit2: { kind: 'apple'} | { kind: 'banana' } | { kind: 'cherry' } @@ -55,10 +55,10 @@ if (isOneOf(kind, ['apple', 'banana'] as const)) { >'banana' : "banana" fruit2.kind ->fruit2.kind : "apple" | "banana" ->fruit2 : { kind: "apple"; } | { kind: "banana"; } ->kind : "apple" | "banana" +>fruit2.kind : "apple" | "banana" | "cherry" +>fruit2 : { kind: "apple"; } | { kind: "banana"; } | { kind: "cherry"; } +>kind : "apple" | "banana" | "cherry" fruit2 ->fruit2 : { kind: "apple"; } | { kind: "banana"; } +>fruit2 : { kind: "apple"; } | { kind: "banana"; } | { kind: "cherry"; } } diff --git a/tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts b/tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts new file mode 100644 index 0000000000000..1c85d9e757307 --- /dev/null +++ b/tests/cases/compiler/discriminantNarrowingCouldBeCircular.ts @@ -0,0 +1,40 @@ +// @strict: true +// @lib: es2022 + +// #57705, 57690 +declare function is(v: T): v is T; +const o: Record | undefined = {}; +if (o) { + for (const key in o) { + const value = o[key]; + if (is(value)) { + } + } +} + +type SomeRecord = { a: string }; +declare const kPresentationInheritanceParents: { [tagName: string]: string[] }; +declare function parentElementOrShadowHost(element: SomeRecord): SomeRecord | undefined; + +function getImplicitAriaRole(element: SomeRecord) { + let ancestor: SomeRecord | null = element; + while (ancestor) { + const parent = parentElementOrShadowHost(ancestor); + const parents = kPresentationInheritanceParents[ancestor.a]; + if (!parents || !parent || !parents.includes(parent.a)) + break; + ancestor = parent; + } +} + +declare function isPlainObject2( + data: unknown, + ): data is Record; + + declare const myObj2: unknown; + if (isPlainObject2(myObj2)) { + for (const key of ["a", "b", "c"]) { + const deeper = myObj2[key]; + const deeperKeys = isPlainObject2(deeper) ? Object.keys(deeper) : []; + } + } From f42605fcef04f329e9bb5cb94677ca0101dcdd5c Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 15 Mar 2024 12:28:48 -0700 Subject: [PATCH 03/10] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#57746=20(Reve?= =?UTF-8?q?rt=20"Defer=20processing=20of=20nested=20...)=20into=20release-?= =?UTF-8?q?5.4=20(#57752)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> --- src/compiler/checker.ts | 10 +-- ...ericNestedCallReturningConstructor.symbols | 72 ------------------- ...enericNestedCallReturningConstructor.types | 63 ---------------- ...ceGenericNestedCallReturningConstructor.ts | 28 -------- 4 files changed, 3 insertions(+), 170 deletions(-) delete mode 100644 tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols delete mode 100644 tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types delete mode 100644 tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index cf16285cdb1a8..3981ebc1255ff 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -35136,7 +35136,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // use the resolvingSignature singleton to indicate that we deferred processing. This result will be // propagated out and eventually turned into silentNeverType (a type that is assignable to anything and // from which we never make inferences). - if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { + if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -35149,12 +35149,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunctionOrConstructor(signature: Signature) { - if (!signature.typeParameters) { - return false; - } - const returnType = getReturnTypeOfSignature(signature); - return isFunctionType(returnType) || isConstructorType(returnType); + function isGenericFunctionReturningFunction(signature: Signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } /** diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols deleted file mode 100644 index 03e0bcb9f168b..0000000000000 --- a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.symbols +++ /dev/null @@ -1,72 +0,0 @@ -//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// - -=== inferenceGenericNestedCallReturningConstructor.ts === -interface Action { ->Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) - - new (ctx: TContext): void; ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 1, 7)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 17)) -} - -declare class AssignAction { ->AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) - - constructor(ctx: TContext); ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 5, 14)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 4, 27)) -} - -declare function assign( ->assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) - - assigner: (ctx: TContext) => void ->assigner : Symbol(assigner, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 34)) ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 9, 13)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) - -): { - new (ctx: TContext): AssignAction; ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 11, 7)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) ->AssignAction : Symbol(AssignAction, Decl(inferenceGenericNestedCallReturningConstructor.ts, 2, 1)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 8, 24)) -} - -declare function createMachine(config: { ->createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) ->config : Symbol(config, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 41)) - - context: TContext; ->context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 50)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) - - entry: Action; ->entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 15, 20)) ->Action : Symbol(Action, Decl(inferenceGenericNestedCallReturningConstructor.ts, 0, 0)) ->TContext : Symbol(TContext, Decl(inferenceGenericNestedCallReturningConstructor.ts, 14, 31)) - -}): void; - -createMachine({ ->createMachine : Symbol(createMachine, Decl(inferenceGenericNestedCallReturningConstructor.ts, 12, 1)) - - context: { count: 0 }, ->context : Symbol(context, Decl(inferenceGenericNestedCallReturningConstructor.ts, 19, 15)) ->count : Symbol(count, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 12)) - - entry: assign((ctx) => { ->entry : Symbol(entry, Decl(inferenceGenericNestedCallReturningConstructor.ts, 20, 24)) ->assign : Symbol(assign, Decl(inferenceGenericNestedCallReturningConstructor.ts, 6, 1)) ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) - - ctx // { count: number } ->ctx : Symbol(ctx, Decl(inferenceGenericNestedCallReturningConstructor.ts, 21, 17)) - - }), -}); - diff --git a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types b/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types deleted file mode 100644 index ce6d09b4d3281..0000000000000 --- a/tests/baselines/reference/inferenceGenericNestedCallReturningConstructor.types +++ /dev/null @@ -1,63 +0,0 @@ -//// [tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts] //// - -=== inferenceGenericNestedCallReturningConstructor.ts === -interface Action { - new (ctx: TContext): void; ->ctx : TContext -} - -declare class AssignAction { ->AssignAction : AssignAction - - constructor(ctx: TContext); ->ctx : TContext -} - -declare function assign( ->assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction - - assigner: (ctx: TContext) => void ->assigner : (ctx: TContext) => void ->ctx : TContext - -): { - new (ctx: TContext): AssignAction; ->ctx : TContext -} - -declare function createMachine(config: { ->createMachine : (config: { context: TContext; entry: Action;}) => void ->config : { context: TContext; entry: Action; } - - context: TContext; ->context : TContext - - entry: Action; ->entry : Action - -}): void; - -createMachine({ ->createMachine({ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),}) : void ->createMachine : (config: { context: TContext; entry: Action; }) => void ->{ context: { count: 0 }, entry: assign((ctx) => { ctx // { count: number } }),} : { context: { count: number; }; entry: new (ctx: { count: number; }) => AssignAction<{ count: number; }>; } - - context: { count: 0 }, ->context : { count: number; } ->{ count: 0 } : { count: number; } ->count : number ->0 : 0 - - entry: assign((ctx) => { ->entry : new (ctx: { count: number; }) => AssignAction<{ count: number; }> ->assign((ctx) => { ctx // { count: number } }) : new (ctx: { count: number; }) => AssignAction<{ count: number; }> ->assign : (assigner: (ctx: TContext) => void) => new (ctx: TContext) => AssignAction ->(ctx) => { ctx // { count: number } } : (ctx: { count: number; }) => void ->ctx : { count: number; } - - ctx // { count: number } ->ctx : { count: number; } - - }), -}); - diff --git a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts b/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts deleted file mode 100644 index 8c1ea32096284..0000000000000 --- a/tests/cases/compiler/inferenceGenericNestedCallReturningConstructor.ts +++ /dev/null @@ -1,28 +0,0 @@ -// @strict: true -// @noEmit: true - -interface Action { - new (ctx: TContext): void; -} - -declare class AssignAction { - constructor(ctx: TContext); -} - -declare function assign( - assigner: (ctx: TContext) => void -): { - new (ctx: TContext): AssignAction; -} - -declare function createMachine(config: { - context: TContext; - entry: Action; -}): void; - -createMachine({ - context: { count: 0 }, - entry: assign((ctx) => { - ctx // { count: number } - }), -}); From 609560f36b84bf031fa14cc4b0d1b2aeb8cfc6f9 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Fri, 15 Mar 2024 19:40:24 +0000 Subject: [PATCH 04/10] Bump version to 5.4.3 and LKG --- lib/tsc.js | 83 +++++++++++++++++++------------------- lib/tsserver.js | 83 +++++++++++++++++++------------------- lib/typescript.js | 83 +++++++++++++++++++------------------- lib/typingsInstaller.js | 2 +- package-lock.json | 4 +- package.json | 2 +- src/compiler/corePublic.ts | 2 +- 7 files changed, 128 insertions(+), 131 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index b78d968065015..f3f3150c5d65b 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -18,7 +18,7 @@ and limitations under the License. // src/compiler/corePublic.ts var versionMajorMinor = "5.4"; -var version = "5.4.2"; +var version = "5.4.3"; // src/compiler/core.ts var emptyArray = []; @@ -57966,7 +57966,7 @@ function createTypeChecker(host) { const typeVarIndex = typeSet[0].flags & 8650752 /* TypeVariable */ ? 0 : 1; const typeVariable = typeSet[typeVarIndex]; const primitiveType = typeSet[1 - typeVarIndex]; - if (typeVariable.flags & 8650752 /* TypeVariable */ && (primitiveType.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */) || includes & 16777216 /* IncludesEmptyObject */)) { + if (typeVariable.flags & 8650752 /* TypeVariable */ && (primitiveType.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */) && !isGenericStringLikeType(primitiveType) || includes & 16777216 /* IncludesEmptyObject */)) { const constraint = getBaseConstraintOfType(typeVariable); if (constraint && everyType(constraint, (t) => !!(t.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */)) || isEmptyAnonymousObjectType(t))) { if (isTypeStrictSubtypeOf(constraint, primitiveType)) { @@ -58574,6 +58574,9 @@ function createTypeChecker(host) { function isPatternLiteralType(type) { return !!(type.flags & 134217728 /* TemplateLiteral */) && every(type.types, isPatternLiteralPlaceholderType) || !!(type.flags & 268435456 /* StringMapping */) && isPatternLiteralPlaceholderType(type.type); } + function isGenericStringLikeType(type) { + return !!(type.flags & (134217728 /* TemplateLiteral */ | 268435456 /* StringMapping */)) && !isPatternLiteralType(type); + } function isGenericType(type) { return !!getGenericObjectFlags(type); } @@ -58596,7 +58599,7 @@ function createTypeChecker(host) { } return type.objectFlags & 12582912 /* IsGenericType */; } - return (type.flags & 58982400 /* InstantiableNonPrimitive */ || isGenericMappedType(type) || isGenericTupleType(type) ? 4194304 /* IsGenericObjectType */ : 0) | (type.flags & (58982400 /* InstantiableNonPrimitive */ | 4194304 /* Index */ | 134217728 /* TemplateLiteral */ | 268435456 /* StringMapping */) && !isPatternLiteralType(type) ? 8388608 /* IsGenericIndexType */ : 0); + return (type.flags & 58982400 /* InstantiableNonPrimitive */ || isGenericMappedType(type) || isGenericTupleType(type) ? 4194304 /* IsGenericObjectType */ : 0) | (type.flags & (58982400 /* InstantiableNonPrimitive */ | 4194304 /* Index */) || isGenericStringLikeType(type) ? 8388608 /* IsGenericIndexType */ : 0); } function getSimplifiedType(type, writing) { return type.flags & 8388608 /* IndexedAccess */ ? getSimplifiedIndexedAccessType(type, writing) : type.flags & 16777216 /* Conditional */ ? getSimplifiedConditionalType(type, writing) : type; @@ -65644,7 +65647,7 @@ function createTypeChecker(host) { function hasMatchingArgument(expression, reference) { if (expression.arguments) { for (const argument of expression.arguments) { - if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference) || getCandidateDiscriminantPropertyAccess(argument, reference)) { + if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference)) { return true; } } @@ -65654,36 +65657,6 @@ function createTypeChecker(host) { } return false; } - function getCandidateDiscriminantPropertyAccess(expr, reference) { - if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { - if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - const declaration = symbol.valueDeclaration; - if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { - return declaration; - } - } - } else if (isAccessExpression(expr)) { - if (isMatchingReference(reference, expr.expression)) { - return expr; - } - } else if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - if (isConstantVariable(symbol)) { - const declaration = symbol.valueDeclaration; - if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { - return declaration.initializer; - } - if (isBindingElement(declaration) && !declaration.initializer) { - const parent = declaration.parent.parent; - if (isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && isMatchingReference(reference, parent.initializer)) { - return declaration; - } - } - } - } - return void 0; - } function getFlowNodeId(flow) { if (!flow.id || flow.id < 0) { flow.id = nextFlowId; @@ -66783,9 +66756,39 @@ function createTypeChecker(host) { } return result; } + function getCandidateDiscriminantPropertyAccess(expr) { + if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { + if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + const declaration = symbol.valueDeclaration; + if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { + return declaration; + } + } + } else if (isAccessExpression(expr)) { + if (isMatchingReference(reference, expr.expression)) { + return expr; + } + } else if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + if (isConstantVariable(symbol)) { + const declaration = symbol.valueDeclaration; + if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { + return declaration.initializer; + } + if (isBindingElement(declaration) && !declaration.initializer) { + const parent = declaration.parent.parent; + if (isVariableDeclaration(parent) && !parent.type && parent.initializer && (isIdentifier(parent.initializer) || isAccessExpression(parent.initializer)) && isMatchingReference(reference, parent.initializer)) { + return declaration; + } + } + } + } + return void 0; + } function getDiscriminantPropertyAccess(expr, computedType) { if (declaredType.flags & 1048576 /* Union */ || computedType.flags & 1048576 /* Union */) { - const access = getCandidateDiscriminantPropertyAccess(expr, reference); + const access = getCandidateDiscriminantPropertyAccess(expr); if (access) { const name = getAccessedPropertyName(access); if (name) { @@ -72506,7 +72509,7 @@ function createTypeChecker(host) { } return resolveErrorCall(node); } - if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -72516,12 +72519,8 @@ function createTypeChecker(host) { } return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunctionOrConstructor(signature) { - if (!signature.typeParameters) { - return false; - } - const returnType = getReturnTypeOfSignature(signature); - return isFunctionType(returnType) || isConstructorType(returnType); + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } function isUntypedFunctionCall(funcType, apparentFuncType, numCallSignatures, numConstructSignatures) { return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & 1048576 /* Union */) && !(getReducedType(apparentFuncType).flags & 131072 /* Never */) && isTypeAssignableTo(funcType, globalFunctionType); diff --git a/lib/tsserver.js b/lib/tsserver.js index dacf281c309e2..df1f3dd752ab6 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -2340,7 +2340,7 @@ module.exports = __toCommonJS(server_exports); // src/compiler/corePublic.ts var versionMajorMinor = "5.4"; -var version = "5.4.2"; +var version = "5.4.3"; var Comparison = /* @__PURE__ */ ((Comparison3) => { Comparison3[Comparison3["LessThan"] = -1] = "LessThan"; Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo"; @@ -62710,7 +62710,7 @@ function createTypeChecker(host) { const typeVarIndex = typeSet[0].flags & 8650752 /* TypeVariable */ ? 0 : 1; const typeVariable = typeSet[typeVarIndex]; const primitiveType = typeSet[1 - typeVarIndex]; - if (typeVariable.flags & 8650752 /* TypeVariable */ && (primitiveType.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */) || includes & 16777216 /* IncludesEmptyObject */)) { + if (typeVariable.flags & 8650752 /* TypeVariable */ && (primitiveType.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */) && !isGenericStringLikeType(primitiveType) || includes & 16777216 /* IncludesEmptyObject */)) { const constraint = getBaseConstraintOfType(typeVariable); if (constraint && everyType(constraint, (t) => !!(t.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */)) || isEmptyAnonymousObjectType(t))) { if (isTypeStrictSubtypeOf(constraint, primitiveType)) { @@ -63318,6 +63318,9 @@ function createTypeChecker(host) { function isPatternLiteralType(type) { return !!(type.flags & 134217728 /* TemplateLiteral */) && every(type.types, isPatternLiteralPlaceholderType) || !!(type.flags & 268435456 /* StringMapping */) && isPatternLiteralPlaceholderType(type.type); } + function isGenericStringLikeType(type) { + return !!(type.flags & (134217728 /* TemplateLiteral */ | 268435456 /* StringMapping */)) && !isPatternLiteralType(type); + } function isGenericType(type) { return !!getGenericObjectFlags(type); } @@ -63340,7 +63343,7 @@ function createTypeChecker(host) { } return type.objectFlags & 12582912 /* IsGenericType */; } - return (type.flags & 58982400 /* InstantiableNonPrimitive */ || isGenericMappedType(type) || isGenericTupleType(type) ? 4194304 /* IsGenericObjectType */ : 0) | (type.flags & (58982400 /* InstantiableNonPrimitive */ | 4194304 /* Index */ | 134217728 /* TemplateLiteral */ | 268435456 /* StringMapping */) && !isPatternLiteralType(type) ? 8388608 /* IsGenericIndexType */ : 0); + return (type.flags & 58982400 /* InstantiableNonPrimitive */ || isGenericMappedType(type) || isGenericTupleType(type) ? 4194304 /* IsGenericObjectType */ : 0) | (type.flags & (58982400 /* InstantiableNonPrimitive */ | 4194304 /* Index */) || isGenericStringLikeType(type) ? 8388608 /* IsGenericIndexType */ : 0); } function getSimplifiedType(type, writing) { return type.flags & 8388608 /* IndexedAccess */ ? getSimplifiedIndexedAccessType(type, writing) : type.flags & 16777216 /* Conditional */ ? getSimplifiedConditionalType(type, writing) : type; @@ -70388,7 +70391,7 @@ function createTypeChecker(host) { function hasMatchingArgument(expression, reference) { if (expression.arguments) { for (const argument of expression.arguments) { - if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference) || getCandidateDiscriminantPropertyAccess(argument, reference)) { + if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference)) { return true; } } @@ -70398,36 +70401,6 @@ function createTypeChecker(host) { } return false; } - function getCandidateDiscriminantPropertyAccess(expr, reference) { - if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { - if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - const declaration = symbol.valueDeclaration; - if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { - return declaration; - } - } - } else if (isAccessExpression(expr)) { - if (isMatchingReference(reference, expr.expression)) { - return expr; - } - } else if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - if (isConstantVariable(symbol)) { - const declaration = symbol.valueDeclaration; - if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { - return declaration.initializer; - } - if (isBindingElement(declaration) && !declaration.initializer) { - const parent2 = declaration.parent.parent; - if (isVariableDeclaration(parent2) && !parent2.type && parent2.initializer && (isIdentifier(parent2.initializer) || isAccessExpression(parent2.initializer)) && isMatchingReference(reference, parent2.initializer)) { - return declaration; - } - } - } - } - return void 0; - } function getFlowNodeId(flow) { if (!flow.id || flow.id < 0) { flow.id = nextFlowId; @@ -71527,9 +71500,39 @@ function createTypeChecker(host) { } return result; } + function getCandidateDiscriminantPropertyAccess(expr) { + if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { + if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + const declaration = symbol.valueDeclaration; + if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { + return declaration; + } + } + } else if (isAccessExpression(expr)) { + if (isMatchingReference(reference, expr.expression)) { + return expr; + } + } else if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + if (isConstantVariable(symbol)) { + const declaration = symbol.valueDeclaration; + if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { + return declaration.initializer; + } + if (isBindingElement(declaration) && !declaration.initializer) { + const parent2 = declaration.parent.parent; + if (isVariableDeclaration(parent2) && !parent2.type && parent2.initializer && (isIdentifier(parent2.initializer) || isAccessExpression(parent2.initializer)) && isMatchingReference(reference, parent2.initializer)) { + return declaration; + } + } + } + } + return void 0; + } function getDiscriminantPropertyAccess(expr, computedType) { if (declaredType.flags & 1048576 /* Union */ || computedType.flags & 1048576 /* Union */) { - const access = getCandidateDiscriminantPropertyAccess(expr, reference); + const access = getCandidateDiscriminantPropertyAccess(expr); if (access) { const name = getAccessedPropertyName(access); if (name) { @@ -77250,7 +77253,7 @@ function createTypeChecker(host) { } return resolveErrorCall(node); } - if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -77260,12 +77263,8 @@ function createTypeChecker(host) { } return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunctionOrConstructor(signature) { - if (!signature.typeParameters) { - return false; - } - const returnType = getReturnTypeOfSignature(signature); - return isFunctionType(returnType) || isConstructorType(returnType); + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } function isUntypedFunctionCall(funcType, apparentFuncType, numCallSignatures, numConstructSignatures) { return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & 1048576 /* Union */) && !(getReducedType(apparentFuncType).flags & 131072 /* Never */) && isTypeAssignableTo(funcType, globalFunctionType); diff --git a/lib/typescript.js b/lib/typescript.js index adde21acf1e4f..05672d241e67b 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -35,7 +35,7 @@ var ts = (() => { "src/compiler/corePublic.ts"() { "use strict"; versionMajorMinor = "5.4"; - version = "5.4.2"; + version = "5.4.3"; Comparison = /* @__PURE__ */ ((Comparison3) => { Comparison3[Comparison3["LessThan"] = -1] = "LessThan"; Comparison3[Comparison3["EqualTo"] = 0] = "EqualTo"; @@ -60465,7 +60465,7 @@ ${lanes.join("\n")} const typeVarIndex = typeSet[0].flags & 8650752 /* TypeVariable */ ? 0 : 1; const typeVariable = typeSet[typeVarIndex]; const primitiveType = typeSet[1 - typeVarIndex]; - if (typeVariable.flags & 8650752 /* TypeVariable */ && (primitiveType.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */) || includes & 16777216 /* IncludesEmptyObject */)) { + if (typeVariable.flags & 8650752 /* TypeVariable */ && (primitiveType.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */) && !isGenericStringLikeType(primitiveType) || includes & 16777216 /* IncludesEmptyObject */)) { const constraint = getBaseConstraintOfType(typeVariable); if (constraint && everyType(constraint, (t) => !!(t.flags & (402784252 /* Primitive */ | 67108864 /* NonPrimitive */)) || isEmptyAnonymousObjectType(t))) { if (isTypeStrictSubtypeOf(constraint, primitiveType)) { @@ -61073,6 +61073,9 @@ ${lanes.join("\n")} function isPatternLiteralType(type) { return !!(type.flags & 134217728 /* TemplateLiteral */) && every(type.types, isPatternLiteralPlaceholderType) || !!(type.flags & 268435456 /* StringMapping */) && isPatternLiteralPlaceholderType(type.type); } + function isGenericStringLikeType(type) { + return !!(type.flags & (134217728 /* TemplateLiteral */ | 268435456 /* StringMapping */)) && !isPatternLiteralType(type); + } function isGenericType(type) { return !!getGenericObjectFlags(type); } @@ -61095,7 +61098,7 @@ ${lanes.join("\n")} } return type.objectFlags & 12582912 /* IsGenericType */; } - return (type.flags & 58982400 /* InstantiableNonPrimitive */ || isGenericMappedType(type) || isGenericTupleType(type) ? 4194304 /* IsGenericObjectType */ : 0) | (type.flags & (58982400 /* InstantiableNonPrimitive */ | 4194304 /* Index */ | 134217728 /* TemplateLiteral */ | 268435456 /* StringMapping */) && !isPatternLiteralType(type) ? 8388608 /* IsGenericIndexType */ : 0); + return (type.flags & 58982400 /* InstantiableNonPrimitive */ || isGenericMappedType(type) || isGenericTupleType(type) ? 4194304 /* IsGenericObjectType */ : 0) | (type.flags & (58982400 /* InstantiableNonPrimitive */ | 4194304 /* Index */) || isGenericStringLikeType(type) ? 8388608 /* IsGenericIndexType */ : 0); } function getSimplifiedType(type, writing) { return type.flags & 8388608 /* IndexedAccess */ ? getSimplifiedIndexedAccessType(type, writing) : type.flags & 16777216 /* Conditional */ ? getSimplifiedConditionalType(type, writing) : type; @@ -68143,7 +68146,7 @@ ${lanes.join("\n")} function hasMatchingArgument(expression, reference) { if (expression.arguments) { for (const argument of expression.arguments) { - if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference) || getCandidateDiscriminantPropertyAccess(argument, reference)) { + if (isOrContainsMatchingReference(reference, argument) || optionalChainContainsReference(argument, reference)) { return true; } } @@ -68153,36 +68156,6 @@ ${lanes.join("\n")} } return false; } - function getCandidateDiscriminantPropertyAccess(expr, reference) { - if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { - if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - const declaration = symbol.valueDeclaration; - if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { - return declaration; - } - } - } else if (isAccessExpression(expr)) { - if (isMatchingReference(reference, expr.expression)) { - return expr; - } - } else if (isIdentifier(expr)) { - const symbol = getResolvedSymbol(expr); - if (isConstantVariable(symbol)) { - const declaration = symbol.valueDeclaration; - if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { - return declaration.initializer; - } - if (isBindingElement(declaration) && !declaration.initializer) { - const parent2 = declaration.parent.parent; - if (isVariableDeclaration(parent2) && !parent2.type && parent2.initializer && (isIdentifier(parent2.initializer) || isAccessExpression(parent2.initializer)) && isMatchingReference(reference, parent2.initializer)) { - return declaration; - } - } - } - } - return void 0; - } function getFlowNodeId(flow) { if (!flow.id || flow.id < 0) { flow.id = nextFlowId; @@ -69282,9 +69255,39 @@ ${lanes.join("\n")} } return result; } + function getCandidateDiscriminantPropertyAccess(expr) { + if (isBindingPattern(reference) || isFunctionExpressionOrArrowFunction(reference) || isObjectLiteralMethod(reference)) { + if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + const declaration = symbol.valueDeclaration; + if (declaration && (isBindingElement(declaration) || isParameter(declaration)) && reference === declaration.parent && !declaration.initializer && !declaration.dotDotDotToken) { + return declaration; + } + } + } else if (isAccessExpression(expr)) { + if (isMatchingReference(reference, expr.expression)) { + return expr; + } + } else if (isIdentifier(expr)) { + const symbol = getResolvedSymbol(expr); + if (isConstantVariable(symbol)) { + const declaration = symbol.valueDeclaration; + if (isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && isAccessExpression(declaration.initializer) && isMatchingReference(reference, declaration.initializer.expression)) { + return declaration.initializer; + } + if (isBindingElement(declaration) && !declaration.initializer) { + const parent2 = declaration.parent.parent; + if (isVariableDeclaration(parent2) && !parent2.type && parent2.initializer && (isIdentifier(parent2.initializer) || isAccessExpression(parent2.initializer)) && isMatchingReference(reference, parent2.initializer)) { + return declaration; + } + } + } + } + return void 0; + } function getDiscriminantPropertyAccess(expr, computedType) { if (declaredType.flags & 1048576 /* Union */ || computedType.flags & 1048576 /* Union */) { - const access = getCandidateDiscriminantPropertyAccess(expr, reference); + const access = getCandidateDiscriminantPropertyAccess(expr); if (access) { const name = getAccessedPropertyName(access); if (name) { @@ -75005,7 +75008,7 @@ ${lanes.join("\n")} } return resolveErrorCall(node); } - if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunctionOrConstructor)) { + if (checkMode & 8 /* SkipGenericFunctions */ && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) { skippedGenericFunction(node, checkMode); return resolvingSignature; } @@ -75015,12 +75018,8 @@ ${lanes.join("\n")} } return resolveCall(node, callSignatures, candidatesOutArray, checkMode, callChainFlags); } - function isGenericFunctionReturningFunctionOrConstructor(signature) { - if (!signature.typeParameters) { - return false; - } - const returnType = getReturnTypeOfSignature(signature); - return isFunctionType(returnType) || isConstructorType(returnType); + function isGenericFunctionReturningFunction(signature) { + return !!(signature.typeParameters && isFunctionType(getReturnTypeOfSignature(signature))); } function isUntypedFunctionCall(funcType, apparentFuncType, numCallSignatures, numConstructSignatures) { return isTypeAny(funcType) || isTypeAny(apparentFuncType) && !!(funcType.flags & 262144 /* TypeParameter */) || !numCallSignatures && !numConstructSignatures && !(apparentFuncType.flags & 1048576 /* Union */) && !(getReducedType(apparentFuncType).flags & 131072 /* Never */) && isTypeAssignableTo(funcType, globalFunctionType); diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 7790762703763..b629c7681e98a 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -54,7 +54,7 @@ var path = __toESM(require("path")); // src/compiler/corePublic.ts var versionMajorMinor = "5.4"; -var version = "5.4.2"; +var version = "5.4.3"; // src/compiler/core.ts var emptyArray = []; diff --git a/package-lock.json b/package-lock.json index 83d8d02918663..0f3b38bbadadb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typescript", - "version": "5.4.2", + "version": "5.4.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typescript", - "version": "5.4.2", + "version": "5.4.3", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", diff --git a/package.json b/package.json index 565e35da2e438..f6b9ceca6dc33 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "5.4.2", + "version": "5.4.3", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index a1f7376ba0ece..6684032a0969a 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -4,7 +4,7 @@ export const versionMajorMinor = "5.4"; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types -export const version = "5.4.2" as string; +export const version = "5.4.3" as string; /** * Type of objects whose values are all of the same type. From b45a41823ecaff6c1554a4c69161db10b2eba6ab Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 18 Mar 2024 11:56:40 -0700 Subject: [PATCH 05/10] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#57801=20(Dist?= =?UTF-8?q?ribute=20mapped=20types=20over=20array/...)=20into=20release-5.?= =?UTF-8?q?4=20(#57832)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Anders Hejlsberg --- src/compiler/checker.ts | 53 +++++++++------- .../mappedArrayTupleIntersections.symbols | 62 +++++++++++++++++++ .../mappedArrayTupleIntersections.types | 40 ++++++++++++ .../compiler/mappedArrayTupleIntersections.ts | 21 +++++++ 4 files changed, 152 insertions(+), 24 deletions(-) create mode 100644 tests/baselines/reference/mappedArrayTupleIntersections.symbols create mode 100644 tests/baselines/reference/mappedArrayTupleIntersections.types create mode 100644 tests/cases/compiler/mappedArrayTupleIntersections.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3981ebc1255ff..4abe2f0eec1b9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14557,7 +14557,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const constraint = getConstraintTypeFromMappedType(type); if (constraint.flags & TypeFlags.Index) { const baseConstraint = getBaseConstraintOfType((constraint as IndexType).type); - if (baseConstraint && everyType(baseConstraint, isArrayOrTupleType)) { + if (baseConstraint && everyType(baseConstraint, t => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } @@ -14565,6 +14565,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type; } + function isArrayOrTupleOrIntersection(type: Type) { + return !!(type.flags & TypeFlags.Intersection) && every((type as IntersectionType).types, isArrayOrTupleType); + } + function isMappedTypeGenericIndexedAccess(type: Type) { let objectType; return !!(type.flags & TypeFlags.IndexedAccess && getObjectFlags(objectType = (type as IndexedAccessType).objectType) & ObjectFlags.Mapped && @@ -19759,6 +19763,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // * If T is a union type we distribute the mapped type over the union. // * If T is an array we map to an array where the element type has been transformed. // * If T is a tuple we map to a tuple where the element types have been transformed. + // * If T is an intersection of array or tuple types we map to an intersection of transformed array or tuple types. // * Otherwise we map to an object type where the type of each property has been transformed. // For example, when T is instantiated to a union type A | B, we produce { [P in keyof A]: X } | // { [P in keyof B]: X }, and when when T is instantiated to a union type A | undefined, we produce @@ -19767,33 +19772,33 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (typeVariable) { const mappedTypeVariable = instantiateType(typeVariable, mapper); if (typeVariable !== mappedTypeVariable) { - return mapTypeWithAlias( - getReducedType(mappedTypeVariable), - t => { - if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { - if (!type.declaration.nameType) { - let constraint; - if ( - isArrayType(t) || t.flags & TypeFlags.Any && findResolutionCycleStartIndex(typeVariable, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 && - (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType) - ) { - return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); - } - if (isTupleType(t)) { - return instantiateMappedTupleType(t, type, typeVariable, mapper); - } - } - return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); - } - return t; - }, - aliasSymbol, - aliasTypeArguments, - ); + return mapTypeWithAlias(getReducedType(mappedTypeVariable), instantiateConstituent, aliasSymbol, aliasTypeArguments); } } // If the constraint type of the instantiation is the wildcard type, return the wildcard type. return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments); + + function instantiateConstituent(t: Type): Type { + if (t.flags & (TypeFlags.AnyOrUnknown | TypeFlags.InstantiableNonPrimitive | TypeFlags.Object | TypeFlags.Intersection) && t !== wildcardType && !isErrorType(t)) { + if (!type.declaration.nameType) { + let constraint; + if ( + isArrayType(t) || t.flags & TypeFlags.Any && findResolutionCycleStartIndex(typeVariable!, TypeSystemPropertyName.ImmediateBaseConstraint) < 0 && + (constraint = getConstraintOfTypeParameter(typeVariable!)) && everyType(constraint, isArrayOrTupleType) + ) { + return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable!, t, mapper)); + } + if (isTupleType(t)) { + return instantiateMappedTupleType(t, type, typeVariable!, mapper); + } + if (isArrayOrTupleOrIntersection(t)) { + return getIntersectionType(map((t as IntersectionType).types, instantiateConstituent)); + } + } + return instantiateAnonymousType(type, prependTypeMapping(typeVariable!, t, mapper)); + } + return t; + } } function getModifiedReadonlyState(state: boolean, modifiers: MappedTypeModifiers) { diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.symbols b/tests/baselines/reference/mappedArrayTupleIntersections.symbols new file mode 100644 index 0000000000000..354bdb031d901 --- /dev/null +++ b/tests/baselines/reference/mappedArrayTupleIntersections.symbols @@ -0,0 +1,62 @@ +//// [tests/cases/compiler/mappedArrayTupleIntersections.ts] //// + +=== mappedArrayTupleIntersections.ts === +type Box = { value: T }; +>Box : Symbol(Box, Decl(mappedArrayTupleIntersections.ts, 0, 0)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 0, 9)) +>value : Symbol(value, Decl(mappedArrayTupleIntersections.ts, 0, 15)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 0, 9)) + +type Boxify = { [K in keyof T]: Box }; +>Boxify : Symbol(Boxify, Decl(mappedArrayTupleIntersections.ts, 0, 27)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 1, 12)) +>K : Symbol(K, Decl(mappedArrayTupleIntersections.ts, 1, 20)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 1, 12)) +>Box : Symbol(Box, Decl(mappedArrayTupleIntersections.ts, 0, 0)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 1, 12)) +>K : Symbol(K, Decl(mappedArrayTupleIntersections.ts, 1, 20)) + +type T1 = Boxify; +>T1 : Symbol(T1, Decl(mappedArrayTupleIntersections.ts, 1, 47)) +>Boxify : Symbol(Boxify, Decl(mappedArrayTupleIntersections.ts, 0, 27)) + +type T2 = Boxify<[string, string]>; +>T2 : Symbol(T2, Decl(mappedArrayTupleIntersections.ts, 3, 27)) +>Boxify : Symbol(Boxify, Decl(mappedArrayTupleIntersections.ts, 0, 27)) + +type T3 = Boxify; +>T3 : Symbol(T3, Decl(mappedArrayTupleIntersections.ts, 4, 35)) +>Boxify : Symbol(Boxify, Decl(mappedArrayTupleIntersections.ts, 0, 27)) + +type T4 = Boxify; +>T4 : Symbol(T4, Decl(mappedArrayTupleIntersections.ts, 5, 39)) +>Boxify : Symbol(Boxify, Decl(mappedArrayTupleIntersections.ts, 0, 27)) + +type T5 = Boxify; +>T5 : Symbol(T5, Decl(mappedArrayTupleIntersections.ts, 6, 46)) +>Boxify : Symbol(Boxify, Decl(mappedArrayTupleIntersections.ts, 0, 27)) +>x : Symbol(x, Decl(mappedArrayTupleIntersections.ts, 7, 29)) + +// https://github.com/microsoft/TypeScript/issues/57744 + +type MustBeArray = T; +>MustBeArray : Symbol(MustBeArray, Decl(mappedArrayTupleIntersections.ts, 7, 43)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 11, 17)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 11, 17)) + +type Hmm = T extends number[] ? +>Hmm : Symbol(Hmm, Decl(mappedArrayTupleIntersections.ts, 11, 38)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 13, 9)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 13, 9)) + + MustBeArray<{ [I in keyof T]: 1 }> : +>MustBeArray : Symbol(MustBeArray, Decl(mappedArrayTupleIntersections.ts, 7, 43)) +>I : Symbol(I, Decl(mappedArrayTupleIntersections.ts, 14, 19)) +>T : Symbol(T, Decl(mappedArrayTupleIntersections.ts, 13, 9)) + + never; + +type X = Hmm<[3, 4, 5]>; +>X : Symbol(X, Decl(mappedArrayTupleIntersections.ts, 15, 10)) +>Hmm : Symbol(Hmm, Decl(mappedArrayTupleIntersections.ts, 11, 38)) + diff --git a/tests/baselines/reference/mappedArrayTupleIntersections.types b/tests/baselines/reference/mappedArrayTupleIntersections.types new file mode 100644 index 0000000000000..db4a465853fc9 --- /dev/null +++ b/tests/baselines/reference/mappedArrayTupleIntersections.types @@ -0,0 +1,40 @@ +//// [tests/cases/compiler/mappedArrayTupleIntersections.ts] //// + +=== mappedArrayTupleIntersections.ts === +type Box = { value: T }; +>Box : Box +>value : T + +type Boxify = { [K in keyof T]: Box }; +>Boxify : Boxify + +type T1 = Boxify; +>T1 : Box[] + +type T2 = Boxify<[string, string]>; +>T2 : [Box, Box] + +type T3 = Boxify; +>T3 : Box[] & Box[] + +type T4 = Boxify; +>T4 : Box[] & [Box, Box] + +type T5 = Boxify; +>T5 : Boxify +>x : string + +// https://github.com/microsoft/TypeScript/issues/57744 + +type MustBeArray = T; +>MustBeArray : T + +type Hmm = T extends number[] ? +>Hmm : Hmm + + MustBeArray<{ [I in keyof T]: 1 }> : + never; + +type X = Hmm<[3, 4, 5]>; +>X : [1, 1, 1] + diff --git a/tests/cases/compiler/mappedArrayTupleIntersections.ts b/tests/cases/compiler/mappedArrayTupleIntersections.ts new file mode 100644 index 0000000000000..4947e71a5d39c --- /dev/null +++ b/tests/cases/compiler/mappedArrayTupleIntersections.ts @@ -0,0 +1,21 @@ +// @strict: true +// @noEmit: true + +type Box = { value: T }; +type Boxify = { [K in keyof T]: Box }; + +type T1 = Boxify; +type T2 = Boxify<[string, string]>; +type T3 = Boxify; +type T4 = Boxify; +type T5 = Boxify; + +// https://github.com/microsoft/TypeScript/issues/57744 + +type MustBeArray = T; + +type Hmm = T extends number[] ? + MustBeArray<{ [I in keyof T]: 1 }> : + never; + +type X = Hmm<[3, 4, 5]>; From fc7006c125914a2d7146027744500ef8a308c5f6 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Mon, 18 Mar 2024 20:41:16 +0000 Subject: [PATCH 06/10] Update LKG --- lib/tsc.js | 44 +++++++++++++++++++++++--------------------- lib/tsserver.js | 44 +++++++++++++++++++++++--------------------- lib/typescript.js | 44 +++++++++++++++++++++++--------------------- 3 files changed, 69 insertions(+), 63 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index f3f3150c5d65b..3eb234d2d3789 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -55321,13 +55321,16 @@ function createTypeChecker(host) { const constraint = getConstraintTypeFromMappedType(type); if (constraint.flags & 4194304 /* Index */) { const baseConstraint = getBaseConstraintOfType(constraint.type); - if (baseConstraint && everyType(baseConstraint, isArrayOrTupleType)) { + if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } } return type; } + function isArrayOrTupleOrIntersection(type) { + return !!(type.flags & 2097152 /* Intersection */) && every(type.types, isArrayOrTupleType); + } function isMappedTypeGenericIndexedAccess(type) { let objectType; return !!(type.flags & 8388608 /* IndexedAccess */ && getObjectFlags(objectType = type.objectType) & 32 /* Mapped */ && !isGenericMappedType(objectType) && isGenericIndexType(type.indexType) && !(getMappedTypeModifiers(objectType) & 8 /* ExcludeOptional */) && !objectType.declaration.nameType); @@ -59698,29 +59701,28 @@ function createTypeChecker(host) { if (typeVariable) { const mappedTypeVariable = instantiateType(typeVariable, mapper); if (typeVariable !== mappedTypeVariable) { - return mapTypeWithAlias( - getReducedType(mappedTypeVariable), - (t) => { - if (t.flags & (3 /* AnyOrUnknown */ | 58982400 /* InstantiableNonPrimitive */ | 524288 /* Object */ | 2097152 /* Intersection */) && t !== wildcardType && !isErrorType(t)) { - if (!type.declaration.nameType) { - let constraint; - if (isArrayType(t) || t.flags & 1 /* Any */ && findResolutionCycleStartIndex(typeVariable, 4 /* ImmediateBaseConstraint */) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { - return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); - } - if (isTupleType(t)) { - return instantiateMappedTupleType(t, type, typeVariable, mapper); - } - } - return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); - } - return t; - }, - aliasSymbol, - aliasTypeArguments - ); + return mapTypeWithAlias(getReducedType(mappedTypeVariable), instantiateConstituent, aliasSymbol, aliasTypeArguments); } } return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments); + function instantiateConstituent(t) { + if (t.flags & (3 /* AnyOrUnknown */ | 58982400 /* InstantiableNonPrimitive */ | 524288 /* Object */ | 2097152 /* Intersection */) && t !== wildcardType && !isErrorType(t)) { + if (!type.declaration.nameType) { + let constraint; + if (isArrayType(t) || t.flags & 1 /* Any */ && findResolutionCycleStartIndex(typeVariable, 4 /* ImmediateBaseConstraint */) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { + return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); + } + if (isTupleType(t)) { + return instantiateMappedTupleType(t, type, typeVariable, mapper); + } + if (isArrayOrTupleOrIntersection(t)) { + return getIntersectionType(map(t.types, instantiateConstituent)); + } + } + return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); + } + return t; + } } function getModifiedReadonlyState(state, modifiers) { return modifiers & 1 /* IncludeReadonly */ ? true : modifiers & 2 /* ExcludeReadonly */ ? false : state; diff --git a/lib/tsserver.js b/lib/tsserver.js index df1f3dd752ab6..0ddc801d51c86 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -60065,13 +60065,16 @@ function createTypeChecker(host) { const constraint = getConstraintTypeFromMappedType(type); if (constraint.flags & 4194304 /* Index */) { const baseConstraint = getBaseConstraintOfType(constraint.type); - if (baseConstraint && everyType(baseConstraint, isArrayOrTupleType)) { + if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } } return type; } + function isArrayOrTupleOrIntersection(type) { + return !!(type.flags & 2097152 /* Intersection */) && every(type.types, isArrayOrTupleType); + } function isMappedTypeGenericIndexedAccess(type) { let objectType; return !!(type.flags & 8388608 /* IndexedAccess */ && getObjectFlags(objectType = type.objectType) & 32 /* Mapped */ && !isGenericMappedType(objectType) && isGenericIndexType(type.indexType) && !(getMappedTypeModifiers(objectType) & 8 /* ExcludeOptional */) && !objectType.declaration.nameType); @@ -64442,29 +64445,28 @@ function createTypeChecker(host) { if (typeVariable) { const mappedTypeVariable = instantiateType(typeVariable, mapper); if (typeVariable !== mappedTypeVariable) { - return mapTypeWithAlias( - getReducedType(mappedTypeVariable), - (t) => { - if (t.flags & (3 /* AnyOrUnknown */ | 58982400 /* InstantiableNonPrimitive */ | 524288 /* Object */ | 2097152 /* Intersection */) && t !== wildcardType && !isErrorType(t)) { - if (!type.declaration.nameType) { - let constraint; - if (isArrayType(t) || t.flags & 1 /* Any */ && findResolutionCycleStartIndex(typeVariable, 4 /* ImmediateBaseConstraint */) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { - return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); - } - if (isTupleType(t)) { - return instantiateMappedTupleType(t, type, typeVariable, mapper); - } - } - return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); - } - return t; - }, - aliasSymbol, - aliasTypeArguments - ); + return mapTypeWithAlias(getReducedType(mappedTypeVariable), instantiateConstituent, aliasSymbol, aliasTypeArguments); } } return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments); + function instantiateConstituent(t) { + if (t.flags & (3 /* AnyOrUnknown */ | 58982400 /* InstantiableNonPrimitive */ | 524288 /* Object */ | 2097152 /* Intersection */) && t !== wildcardType && !isErrorType(t)) { + if (!type.declaration.nameType) { + let constraint; + if (isArrayType(t) || t.flags & 1 /* Any */ && findResolutionCycleStartIndex(typeVariable, 4 /* ImmediateBaseConstraint */) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { + return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); + } + if (isTupleType(t)) { + return instantiateMappedTupleType(t, type, typeVariable, mapper); + } + if (isArrayOrTupleOrIntersection(t)) { + return getIntersectionType(map(t.types, instantiateConstituent)); + } + } + return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); + } + return t; + } } function getModifiedReadonlyState(state, modifiers) { return modifiers & 1 /* IncludeReadonly */ ? true : modifiers & 2 /* ExcludeReadonly */ ? false : state; diff --git a/lib/typescript.js b/lib/typescript.js index 05672d241e67b..8b56699181efc 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -57820,13 +57820,16 @@ ${lanes.join("\n")} const constraint = getConstraintTypeFromMappedType(type); if (constraint.flags & 4194304 /* Index */) { const baseConstraint = getBaseConstraintOfType(constraint.type); - if (baseConstraint && everyType(baseConstraint, isArrayOrTupleType)) { + if (baseConstraint && everyType(baseConstraint, (t) => isArrayOrTupleType(t) || isArrayOrTupleOrIntersection(t))) { return instantiateType(target, prependTypeMapping(typeVariable, baseConstraint, type.mapper)); } } } return type; } + function isArrayOrTupleOrIntersection(type) { + return !!(type.flags & 2097152 /* Intersection */) && every(type.types, isArrayOrTupleType); + } function isMappedTypeGenericIndexedAccess(type) { let objectType; return !!(type.flags & 8388608 /* IndexedAccess */ && getObjectFlags(objectType = type.objectType) & 32 /* Mapped */ && !isGenericMappedType(objectType) && isGenericIndexType(type.indexType) && !(getMappedTypeModifiers(objectType) & 8 /* ExcludeOptional */) && !objectType.declaration.nameType); @@ -62197,29 +62200,28 @@ ${lanes.join("\n")} if (typeVariable) { const mappedTypeVariable = instantiateType(typeVariable, mapper); if (typeVariable !== mappedTypeVariable) { - return mapTypeWithAlias( - getReducedType(mappedTypeVariable), - (t) => { - if (t.flags & (3 /* AnyOrUnknown */ | 58982400 /* InstantiableNonPrimitive */ | 524288 /* Object */ | 2097152 /* Intersection */) && t !== wildcardType && !isErrorType(t)) { - if (!type.declaration.nameType) { - let constraint; - if (isArrayType(t) || t.flags & 1 /* Any */ && findResolutionCycleStartIndex(typeVariable, 4 /* ImmediateBaseConstraint */) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { - return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); - } - if (isTupleType(t)) { - return instantiateMappedTupleType(t, type, typeVariable, mapper); - } - } - return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); - } - return t; - }, - aliasSymbol, - aliasTypeArguments - ); + return mapTypeWithAlias(getReducedType(mappedTypeVariable), instantiateConstituent, aliasSymbol, aliasTypeArguments); } } return instantiateType(getConstraintTypeFromMappedType(type), mapper) === wildcardType ? wildcardType : instantiateAnonymousType(type, mapper, aliasSymbol, aliasTypeArguments); + function instantiateConstituent(t) { + if (t.flags & (3 /* AnyOrUnknown */ | 58982400 /* InstantiableNonPrimitive */ | 524288 /* Object */ | 2097152 /* Intersection */) && t !== wildcardType && !isErrorType(t)) { + if (!type.declaration.nameType) { + let constraint; + if (isArrayType(t) || t.flags & 1 /* Any */ && findResolutionCycleStartIndex(typeVariable, 4 /* ImmediateBaseConstraint */) < 0 && (constraint = getConstraintOfTypeParameter(typeVariable)) && everyType(constraint, isArrayOrTupleType)) { + return instantiateMappedArrayType(t, type, prependTypeMapping(typeVariable, t, mapper)); + } + if (isTupleType(t)) { + return instantiateMappedTupleType(t, type, typeVariable, mapper); + } + if (isArrayOrTupleOrIntersection(t)) { + return getIntersectionType(map(t.types, instantiateConstituent)); + } + } + return instantiateAnonymousType(type, prependTypeMapping(typeVariable, t, mapper)); + } + return t; + } } function getModifiedReadonlyState(state, modifiers) { return modifiers & 1 /* IncludeReadonly */ ? true : modifiers & 2 /* ExcludeReadonly */ ? false : state; From 010b1885c089189425a0f7d34bd02305401f8928 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 19 Mar 2024 13:54:29 -0700 Subject: [PATCH 07/10] release-5.4: Revert PR 56087 (#57850) --- src/compiler/checker.ts | 6 ---- .../declarationEmitUsingTypeAlias1.errors.txt | 34 +++++++++++++++++++ .../declarationEmitUsingTypeAlias1.js | 6 ---- 3 files changed, 34 insertions(+), 12 deletions(-) create mode 100644 tests/baselines/reference/declarationEmitUsingTypeAlias1.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4abe2f0eec1b9..71dc5a4e83c67 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5735,12 +5735,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * Checks if two symbols, through aliasing and/or merging, refer to the same thing */ function getSymbolIfSameReference(s1: Symbol, s2: Symbol) { - if (s1.flags & SymbolFlags.TypeAlias && s2.declarations?.find(isTypeAlias)) { - s2 = getDeclaredTypeOfTypeAlias(s2).aliasSymbol || s2; - } - if (s2.flags & SymbolFlags.TypeAlias && s1.declarations?.find(isTypeAlias)) { - s1 = getDeclaredTypeOfTypeAlias(s1).aliasSymbol || s1; - } if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) { return s1; } diff --git a/tests/baselines/reference/declarationEmitUsingTypeAlias1.errors.txt b/tests/baselines/reference/declarationEmitUsingTypeAlias1.errors.txt new file mode 100644 index 0000000000000..c31e66a237a62 --- /dev/null +++ b/tests/baselines/reference/declarationEmitUsingTypeAlias1.errors.txt @@ -0,0 +1,34 @@ +src/index.ts(3,14): error TS2742: The inferred type of 'foo' cannot be named without a reference to '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. +src/index.ts(7,14): error TS2742: The inferred type of 'bar' cannot be named without a reference to '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. + + +==== node_modules/some-dep/dist/inner.d.ts (0 errors) ==== + export declare type Other = { other: string }; + export declare type SomeType = { arg: Other }; + +==== node_modules/some-dep/dist/index.d.ts (0 errors) ==== + export type OtherType = import('./inner').Other; + export type SomeType = import('./inner').SomeType; + +==== node_modules/some-dep/package.json (0 errors) ==== + { + "name": "some-dep", + "exports": { + ".": "./dist/index.js" + } + } + +==== src/index.ts (2 errors) ==== + import { SomeType } from "some-dep"; + + export const foo = (thing: SomeType) => { + ~~~ +!!! error TS2742: The inferred type of 'foo' cannot be named without a reference to '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. + return thing; + }; + + export const bar = (thing: SomeType) => { + ~~~ +!!! error TS2742: The inferred type of 'bar' cannot be named without a reference to '../node_modules/some-dep/dist/inner'. This is likely not portable. A type annotation is necessary. + return thing.arg; + }; \ No newline at end of file diff --git a/tests/baselines/reference/declarationEmitUsingTypeAlias1.js b/tests/baselines/reference/declarationEmitUsingTypeAlias1.js index 9bfe2999627b9..541c8c65140c9 100644 --- a/tests/baselines/reference/declarationEmitUsingTypeAlias1.js +++ b/tests/baselines/reference/declarationEmitUsingTypeAlias1.js @@ -39,9 +39,3 @@ var bar = function (thing) { return thing.arg; }; exports.bar = bar; - - -//// [index.d.ts] -import { SomeType } from "some-dep"; -export declare const foo: (thing: SomeType) => import("some-dep").SomeType; -export declare const bar: (thing: SomeType) => import("some-dep").OtherType; From ca8e720a36618eb1323f8dbc36a45a8fd5b35d78 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 19 Mar 2024 20:56:37 +0000 Subject: [PATCH 08/10] Update LKG --- lib/tsc.js | 7 ------- lib/tsserver.js | 7 ------- lib/typescript.js | 7 ------- 3 files changed, 21 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 3eb234d2d3789..f1b0030a23869 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -47517,13 +47517,6 @@ function createTypeChecker(host) { }); } function getSymbolIfSameReference(s1, s2) { - var _a, _b; - if (s1.flags & 524288 /* TypeAlias */ && ((_a = s2.declarations) == null ? void 0 : _a.find(isTypeAlias))) { - s2 = getDeclaredTypeOfTypeAlias(s2).aliasSymbol || s2; - } - if (s2.flags & 524288 /* TypeAlias */ && ((_b = s1.declarations) == null ? void 0 : _b.find(isTypeAlias))) { - s1 = getDeclaredTypeOfTypeAlias(s1).aliasSymbol || s1; - } if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) { return s1; } diff --git a/lib/tsserver.js b/lib/tsserver.js index 0ddc801d51c86..04602f13318f4 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -52261,13 +52261,6 @@ function createTypeChecker(host) { }); } function getSymbolIfSameReference(s1, s2) { - var _a, _b; - if (s1.flags & 524288 /* TypeAlias */ && ((_a = s2.declarations) == null ? void 0 : _a.find(isTypeAlias))) { - s2 = getDeclaredTypeOfTypeAlias(s2).aliasSymbol || s2; - } - if (s2.flags & 524288 /* TypeAlias */ && ((_b = s1.declarations) == null ? void 0 : _b.find(isTypeAlias))) { - s1 = getDeclaredTypeOfTypeAlias(s1).aliasSymbol || s1; - } if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) { return s1; } diff --git a/lib/typescript.js b/lib/typescript.js index 8b56699181efc..65799b4b0bac8 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -50016,13 +50016,6 @@ ${lanes.join("\n")} }); } function getSymbolIfSameReference(s1, s2) { - var _a, _b; - if (s1.flags & 524288 /* TypeAlias */ && ((_a = s2.declarations) == null ? void 0 : _a.find(isTypeAlias))) { - s2 = getDeclaredTypeOfTypeAlias(s2).aliasSymbol || s2; - } - if (s2.flags & 524288 /* TypeAlias */ && ((_b = s1.declarations) == null ? void 0 : _b.find(isTypeAlias))) { - s1 = getDeclaredTypeOfTypeAlias(s1).aliasSymbol || s1; - } if (getMergedSymbol(resolveSymbol(getMergedSymbol(s1))) === getMergedSymbol(resolveSymbol(getMergedSymbol(s2)))) { return s1; } From cd06f92c43eede05731cc0592bcb4ee7fe4d38cc Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 19 Mar 2024 15:07:36 -0700 Subject: [PATCH 09/10] =?UTF-8?q?=F0=9F=A4=96=20Pick=20PR=20#57853=20(Reve?= =?UTF-8?q?rt=20PR=2056161)=20into=20release-5.4=20(#57854)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com> --- src/compiler/checker.ts | 2 +- .../reference/enumWithInfinityProperty.errors.txt | 10 ---------- .../baselines/reference/enumWithNaNProperty.errors.txt | 10 ---------- .../enumWithNegativeInfinityProperty.errors.txt | 10 ---------- 4 files changed, 1 insertion(+), 31 deletions(-) delete mode 100644 tests/baselines/reference/enumWithInfinityProperty.errors.txt delete mode 100644 tests/baselines/reference/enumWithNaNProperty.errors.txt delete mode 100644 tests/baselines/reference/enumWithNegativeInfinityProperty.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 71dc5a4e83c67..3fef78b1df9fb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -45377,7 +45377,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { const text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } diff --git a/tests/baselines/reference/enumWithInfinityProperty.errors.txt b/tests/baselines/reference/enumWithInfinityProperty.errors.txt deleted file mode 100644 index 27de0a69b0383..0000000000000 --- a/tests/baselines/reference/enumWithInfinityProperty.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -enumWithInfinityProperty.ts(2,5): error TS2452: An enum member cannot have a numeric name. - - -==== enumWithInfinityProperty.ts (1 errors) ==== - enum A { - Infinity = 1 - ~~~~~~~~ -!!! error TS2452: An enum member cannot have a numeric name. - } - \ No newline at end of file diff --git a/tests/baselines/reference/enumWithNaNProperty.errors.txt b/tests/baselines/reference/enumWithNaNProperty.errors.txt deleted file mode 100644 index 941fa099eefe2..0000000000000 --- a/tests/baselines/reference/enumWithNaNProperty.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -enumWithNaNProperty.ts(2,5): error TS2452: An enum member cannot have a numeric name. - - -==== enumWithNaNProperty.ts (1 errors) ==== - enum A { - NaN = 1 - ~~~ -!!! error TS2452: An enum member cannot have a numeric name. - } - \ No newline at end of file diff --git a/tests/baselines/reference/enumWithNegativeInfinityProperty.errors.txt b/tests/baselines/reference/enumWithNegativeInfinityProperty.errors.txt deleted file mode 100644 index d9923989b8a3f..0000000000000 --- a/tests/baselines/reference/enumWithNegativeInfinityProperty.errors.txt +++ /dev/null @@ -1,10 +0,0 @@ -enumWithNegativeInfinityProperty.ts(2,5): error TS2452: An enum member cannot have a numeric name. - - -==== enumWithNegativeInfinityProperty.ts (1 errors) ==== - enum A { - "-Infinity" = 1 - ~~~~~~~~~~~ -!!! error TS2452: An enum member cannot have a numeric name. - } - \ No newline at end of file From 6ea273cdcca99db809074d2b2d38d0e5b59ee81b Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Tue, 19 Mar 2024 22:08:46 +0000 Subject: [PATCH 10/10] Update LKG --- lib/tsc.js | 2 +- lib/tsserver.js | 2 +- lib/typescript.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index f1b0030a23869..e6dcc303eb9c7 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -80672,7 +80672,7 @@ function createTypeChecker(host) { error(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); } else { const text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } diff --git a/lib/tsserver.js b/lib/tsserver.js index 04602f13318f4..bc0e83fb4070a 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -85416,7 +85416,7 @@ function createTypeChecker(host) { error2(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); } else { const text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error2(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } } diff --git a/lib/typescript.js b/lib/typescript.js index 65799b4b0bac8..7014c9a443241 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -83171,7 +83171,7 @@ ${lanes.join("\n")} error2(member.name, Diagnostics.Computed_property_names_are_not_allowed_in_enums); } else { const text = getTextOfPropertyName(member.name); - if (isNumericLiteralName(text)) { + if (isNumericLiteralName(text) && !isInfinityOrNaNString(text)) { error2(member.name, Diagnostics.An_enum_member_cannot_have_a_numeric_name); } }