Don't treat an instantiation expression as an assertion in skipOuterExpressions (#59538)

This commit is contained in:
Jake Bailey 2024-08-06 15:01:46 -07:00 коммит произвёл GitHub
Родитель a745d1b205
Коммит 99878128f0
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
10 изменённых файлов: 166 добавлений и 6 удалений

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

@ -6553,6 +6553,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
return updateSatisfiesExpression(outerExpression, expression, outerExpression.type);
case SyntaxKind.NonNullExpression:
return updateNonNullExpression(outerExpression, expression);
case SyntaxKind.ExpressionWithTypeArguments:
return updateExpressionWithTypeArguments(outerExpression, expression, outerExpression.typeArguments);
case SyntaxKind.PartiallyEmittedExpression:
return updatePartiallyEmittedExpression(outerExpression, expression);
}

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

@ -630,9 +630,10 @@ export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All):
return (kinds & OuterExpressionKinds.Parentheses) !== 0;
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.ExpressionWithTypeArguments:
case SyntaxKind.SatisfiesExpression:
return (kinds & OuterExpressionKinds.TypeAssertions) !== 0;
case SyntaxKind.ExpressionWithTypeArguments:
return (kinds & OuterExpressionKinds.ExpressionsWithTypeArguments) !== 0;
case SyntaxKind.NonNullExpression:
return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0;
case SyntaxKind.PartiallyEmittedExpression:

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

@ -1689,7 +1689,7 @@ export function transformTypeScript(context: TransformationContext) {
}
function visitParenthesizedExpression(node: ParenthesizedExpression): Expression {
const innerExpression = skipOuterExpressions(node.expression, ~OuterExpressionKinds.Assertions);
const innerExpression = skipOuterExpressions(node.expression, ~(OuterExpressionKinds.Assertions | OuterExpressionKinds.ExpressionsWithTypeArguments));
if (isAssertionExpression(innerExpression) || isSatisfiesExpression(innerExpression)) {
// Make sure we consider all nested cast expressions, e.g.:
// (<any><number><any>-A).x;

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

@ -8476,11 +8476,12 @@ export const enum OuterExpressionKinds {
TypeAssertions = 1 << 1,
NonNullAssertions = 1 << 2,
PartiallyEmittedExpressions = 1 << 3,
ExpressionsWithTypeArguments = 1 << 4,
Assertions = TypeAssertions | NonNullAssertions,
All = Parentheses | Assertions | PartiallyEmittedExpressions,
All = Parentheses | Assertions | PartiallyEmittedExpressions | ExpressionsWithTypeArguments,
ExcludeJSDocTypeAssertion = 1 << 4,
ExcludeJSDocTypeAssertion = 1 << 31,
}
/** @internal */
@ -8490,6 +8491,7 @@ export type OuterExpression =
| SatisfiesExpression
| AsExpression
| NonNullExpression
| ExpressionWithTypeArguments
| PartiallyEmittedExpression;
/** @internal */

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

@ -7346,9 +7346,10 @@ declare namespace ts {
TypeAssertions = 2,
NonNullAssertions = 4,
PartiallyEmittedExpressions = 8,
ExpressionsWithTypeArguments = 16,
Assertions = 6,
All = 15,
ExcludeJSDocTypeAssertion = 16,
All = 31,
ExcludeJSDocTypeAssertion = -2147483648,
}
type ImmediatelyInvokedFunctionExpression = CallExpression & {
readonly expression: FunctionExpression;

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

@ -0,0 +1,26 @@
assignmentToInstantiationExpression.ts(2,1): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
assignmentToInstantiationExpression.ts(6,1): error TS2454: Variable 'getValue' is used before being assigned.
assignmentToInstantiationExpression.ts(6,1): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
assignmentToInstantiationExpression.ts(10,1): error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
==== assignmentToInstantiationExpression.ts (4 errors) ====
let obj: { fn?: <T>() => T } = {};
obj.fn<number> = () => 1234;
~~~~~~~~~~~~~~
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
let getValue: <T>() => T;
getValue<number> = () => 1234;
~~~~~~~~
!!! error TS2454: Variable 'getValue' is used before being assigned.
~~~~~~~~~~~~~~~~
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.
let getValue2!: <T>() => T;
getValue2<number> = () => 1234;
~~~~~~~~~~~~~~~~~
!!! error TS2364: The left-hand side of an assignment expression must be a variable or a property access.

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

@ -0,0 +1,23 @@
//// [tests/cases/compiler/assignmentToInstantiationExpression.ts] ////
//// [assignmentToInstantiationExpression.ts]
let obj: { fn?: <T>() => T } = {};
obj.fn<number> = () => 1234;
let getValue: <T>() => T;
getValue<number> = () => 1234;
let getValue2!: <T>() => T;
getValue2<number> = () => 1234;
//// [assignmentToInstantiationExpression.js]
"use strict";
var obj = {};
(obj.fn) = function () { return 1234; };
var getValue;
(getValue) = function () { return 1234; };
var getValue2;
(getValue2) = function () { return 1234; };

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

@ -0,0 +1,32 @@
//// [tests/cases/compiler/assignmentToInstantiationExpression.ts] ////
=== assignmentToInstantiationExpression.ts ===
let obj: { fn?: <T>() => T } = {};
>obj : Symbol(obj, Decl(assignmentToInstantiationExpression.ts, 0, 3))
>fn : Symbol(fn, Decl(assignmentToInstantiationExpression.ts, 0, 10))
>T : Symbol(T, Decl(assignmentToInstantiationExpression.ts, 0, 17))
>T : Symbol(T, Decl(assignmentToInstantiationExpression.ts, 0, 17))
obj.fn<number> = () => 1234;
>obj.fn : Symbol(fn, Decl(assignmentToInstantiationExpression.ts, 0, 10))
>obj : Symbol(obj, Decl(assignmentToInstantiationExpression.ts, 0, 3))
>fn : Symbol(fn, Decl(assignmentToInstantiationExpression.ts, 0, 10))
let getValue: <T>() => T;
>getValue : Symbol(getValue, Decl(assignmentToInstantiationExpression.ts, 4, 3))
>T : Symbol(T, Decl(assignmentToInstantiationExpression.ts, 4, 15))
>T : Symbol(T, Decl(assignmentToInstantiationExpression.ts, 4, 15))
getValue<number> = () => 1234;
>getValue : Symbol(getValue, Decl(assignmentToInstantiationExpression.ts, 4, 3))
let getValue2!: <T>() => T;
>getValue2 : Symbol(getValue2, Decl(assignmentToInstantiationExpression.ts, 8, 3))
>T : Symbol(T, Decl(assignmentToInstantiationExpression.ts, 8, 17))
>T : Symbol(T, Decl(assignmentToInstantiationExpression.ts, 8, 17))
getValue2<number> = () => 1234;
>getValue2 : Symbol(getValue2, Decl(assignmentToInstantiationExpression.ts, 8, 3))

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

@ -0,0 +1,61 @@
//// [tests/cases/compiler/assignmentToInstantiationExpression.ts] ////
=== assignmentToInstantiationExpression.ts ===
let obj: { fn?: <T>() => T } = {};
>obj : { fn?: <T>() => T; }
> : ^^^^^^^ ^^^
>fn : (<T>() => T) | undefined
> : ^^ ^^^^^^^ ^^^^^^^^^^^^^
>{} : {}
> : ^^
obj.fn<number> = () => 1234;
>obj.fn<number> = () => 1234 : () => number
> : ^^^^^^^^^^^^
>obj.fn<number> : (() => number) | undefined
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^
>obj.fn : (<T>() => T) | undefined
> : ^^ ^^^^^^^ ^^^^^^^^^^^^^
>obj : { fn?: <T>() => T; }
> : ^^^^^^^ ^^^
>fn : (<T>() => T) | undefined
> : ^^ ^^^^^^^ ^^^^^^^^^^^^^
>() => 1234 : () => number
> : ^^^^^^^^^^^^
>1234 : 1234
> : ^^^^
let getValue: <T>() => T;
>getValue : <T>() => T
> : ^ ^^^^^^^
getValue<number> = () => 1234;
>getValue<number> = () => 1234 : () => number
> : ^^^^^^^^^^^^
>getValue<number> : () => number
> : ^^^^^^^^^^^^
>getValue : <T>() => T
> : ^ ^^^^^^^
>() => 1234 : () => number
> : ^^^^^^^^^^^^
>1234 : 1234
> : ^^^^
let getValue2!: <T>() => T;
>getValue2 : <T>() => T
> : ^ ^^^^^^^
getValue2<number> = () => 1234;
>getValue2<number> = () => 1234 : () => number
> : ^^^^^^^^^^^^
>getValue2<number> : () => number
> : ^^^^^^^^^^^^
>getValue2 : <T>() => T
> : ^ ^^^^^^^
>() => 1234 : () => number
> : ^^^^^^^^^^^^
>1234 : 1234
> : ^^^^

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

@ -0,0 +1,12 @@
// @strict: true
let obj: { fn?: <T>() => T } = {};
obj.fn<number> = () => 1234;
let getValue: <T>() => T;
getValue<number> = () => 1234;
let getValue2!: <T>() => T;
getValue2<number> = () => 1234;