Skip to content

Commit 8d95ac5

Browse files
authored
Fix getEffectiveCheckNode (#60309)
1 parent 60dd512 commit 8d95ac5

12 files changed

+190
-8
lines changed

src/compiler/checker.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,6 @@ import {
726726
isRightSideOfQualifiedNameOrPropertyAccess,
727727
isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName,
728728
isSameEntityName,
729-
isSatisfiesExpression,
730729
isSetAccessor,
731730
isSetAccessorDeclaration,
732731
isShorthandAmbientModuleSymbol,
@@ -35356,8 +35355,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3535635355
}
3535735356

3535835357
function getEffectiveCheckNode(argument: Expression): Expression {
35359-
argument = skipParentheses(argument);
35360-
return isSatisfiesExpression(argument) ? skipParentheses(argument.expression) : argument;
35358+
const flags = isInJSFile(argument)
35359+
? OuterExpressionKinds.Parentheses | OuterExpressionKinds.Satisfies | OuterExpressionKinds.ExcludeJSDocTypeAssertion
35360+
: OuterExpressionKinds.Parentheses | OuterExpressionKinds.Satisfies;
35361+
return skipOuterExpressions(argument, flags);
3536135362
}
3536235363

3536335364
function getSignatureApplicabilityError(

src/compiler/factory/utilities.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -637,8 +637,9 @@ export function isOuterExpression(node: Node, kinds: OuterExpressionKinds = Oute
637637
return (kinds & OuterExpressionKinds.Parentheses) !== 0;
638638
case SyntaxKind.TypeAssertionExpression:
639639
case SyntaxKind.AsExpression:
640-
case SyntaxKind.SatisfiesExpression:
641640
return (kinds & OuterExpressionKinds.TypeAssertions) !== 0;
641+
case SyntaxKind.SatisfiesExpression:
642+
return (kinds & (OuterExpressionKinds.TypeAssertions | OuterExpressionKinds.Satisfies)) !== 0;
642643
case SyntaxKind.ExpressionWithTypeArguments:
643644
return (kinds & OuterExpressionKinds.ExpressionsWithTypeArguments) !== 0;
644645
case SyntaxKind.NonNullExpression:

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8557,8 +8557,9 @@ export const enum OuterExpressionKinds {
85578557
NonNullAssertions = 1 << 2,
85588558
PartiallyEmittedExpressions = 1 << 3,
85598559
ExpressionsWithTypeArguments = 1 << 4,
8560+
Satisfies = 1 << 5,
85608561

8561-
Assertions = TypeAssertions | NonNullAssertions,
8562+
Assertions = TypeAssertions | NonNullAssertions | Satisfies,
85628563
All = Parentheses | Assertions | PartiallyEmittedExpressions | ExpressionsWithTypeArguments,
85638564

85648565
ExcludeJSDocTypeAssertion = 1 << 31,

tests/baselines/reference/api/typescript.d.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7434,8 +7434,9 @@ declare namespace ts {
74347434
NonNullAssertions = 4,
74357435
PartiallyEmittedExpressions = 8,
74367436
ExpressionsWithTypeArguments = 16,
7437-
Assertions = 6,
7438-
All = 31,
7437+
Satisfies = 32,
7438+
Assertions = 38,
7439+
All = 63,
74397440
ExcludeJSDocTypeAssertion = -2147483648,
74407441
}
74417442
type ImmediatelyInvokedFunctionExpression = CallExpression & {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
mytest.js(6,44): error TS2322: Type 'string' is not assignable to type 'T'.
2+
'T' could be instantiated with an arbitrary type which could be unrelated to 'string'.
3+
mytest.js(13,44): error TS2322: Type 'string' is not assignable to type 'T'.
4+
'T' could be instantiated with an arbitrary type which could be unrelated to 'string'.
5+
6+
7+
==== mytest.js (2 errors) ====
8+
/**
9+
* @template T
10+
* @param {T|undefined} value value or not
11+
* @returns {T} result value
12+
*/
13+
const foo1 = value => /** @type {string} */({ ...value });
14+
~~~~~~~~~~~~~~
15+
!!! error TS2322: Type 'string' is not assignable to type 'T'.
16+
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'string'.
17+
18+
/**
19+
* @template T
20+
* @param {T|undefined} value value or not
21+
* @returns {T} result value
22+
*/
23+
const foo2 = value => /** @type {string} */(/** @type {T} */({ ...value }));
24+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25+
!!! error TS2322: Type 'string' is not assignable to type 'T'.
26+
!!! error TS2322: 'T' could be instantiated with an arbitrary type which could be unrelated to 'string'.
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/compiler/arrowExpressionBodyJSDoc.ts] ////
2+
3+
=== mytest.js ===
4+
/**
5+
* @template T
6+
* @param {T|undefined} value value or not
7+
* @returns {T} result value
8+
*/
9+
const foo1 = value => /** @type {string} */({ ...value });
10+
>foo1 : Symbol(foo1, Decl(mytest.js, 5, 5))
11+
>value : Symbol(value, Decl(mytest.js, 5, 12))
12+
>value : Symbol(value, Decl(mytest.js, 5, 12))
13+
14+
/**
15+
* @template T
16+
* @param {T|undefined} value value or not
17+
* @returns {T} result value
18+
*/
19+
const foo2 = value => /** @type {string} */(/** @type {T} */({ ...value }));
20+
>foo2 : Symbol(foo2, Decl(mytest.js, 12, 5))
21+
>value : Symbol(value, Decl(mytest.js, 12, 12))
22+
>value : Symbol(value, Decl(mytest.js, 12, 12))
23+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//// [tests/cases/compiler/arrowExpressionBodyJSDoc.ts] ////
2+
3+
=== mytest.js ===
4+
/**
5+
* @template T
6+
* @param {T|undefined} value value or not
7+
* @returns {T} result value
8+
*/
9+
const foo1 = value => /** @type {string} */({ ...value });
10+
>foo1 : <T>(value: T | undefined) => T
11+
> : ^ ^^ ^^ ^^^^^
12+
>value => /** @type {string} */({ ...value }) : <T>(value: T | undefined) => T
13+
> : ^ ^^ ^^ ^^^^^
14+
>value : T | undefined
15+
> : ^^^^^^^^^^^^^
16+
>({ ...value }) : string
17+
> : ^^^^^^
18+
>{ ...value } : {}
19+
> : ^^
20+
>value : T | undefined
21+
> : ^^^^^^^^^^^^^
22+
23+
/**
24+
* @template T
25+
* @param {T|undefined} value value or not
26+
* @returns {T} result value
27+
*/
28+
const foo2 = value => /** @type {string} */(/** @type {T} */({ ...value }));
29+
>foo2 : <T>(value: T | undefined) => T
30+
> : ^ ^^ ^^ ^^^^^
31+
>value => /** @type {string} */(/** @type {T} */({ ...value })) : <T>(value: T | undefined) => T
32+
> : ^ ^^ ^^ ^^^^^
33+
>value : T | undefined
34+
> : ^^^^^^^^^^^^^
35+
>(/** @type {T} */({ ...value })) : string
36+
> : ^^^^^^
37+
>({ ...value }) : T
38+
> : ^
39+
>{ ...value } : {}
40+
> : ^^
41+
>value : T | undefined
42+
> : ^^^^^^^^^^^^^
43+

tests/baselines/reference/typeSatisfaction_errorLocations1.errors.txt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,11 @@ typeSatisfaction_errorLocations1.ts(47,24): error TS2322: Type 'number' is not a
3131
typeSatisfaction_errorLocations1.ts(48,21): error TS2322: Type '{ a: number; }' is not assignable to type '{ a: true; }'.
3232
Types of property 'a' are incompatible.
3333
Type 'number' is not assignable to type 'true'.
34+
typeSatisfaction_errorLocations1.ts(50,23): error TS2741: Property 'a' is missing in type '{}' but required in type '{ a: true; }'.
35+
typeSatisfaction_errorLocations1.ts(51,24): error TS2741: Property 'a' is missing in type '{}' but required in type '{ a: true; }'.
3436

3537

36-
==== typeSatisfaction_errorLocations1.ts (22 errors) ====
38+
==== typeSatisfaction_errorLocations1.ts (24 errors) ====
3739
const obj1 = { a: 1 };
3840

3941
const fn1 = (s: { a: true }) => {};
@@ -143,4 +145,13 @@ typeSatisfaction_errorLocations1.ts(48,21): error TS2322: Type '{ a: number; }'
143145
!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a: true; }'.
144146
!!! error TS2322: Types of property 'a' are incompatible.
145147
!!! error TS2322: Type 'number' is not assignable to type 'true'.
148+
149+
((): { a: true } => (({}) satisfies unknown) satisfies unknown)();
150+
~~
151+
!!! error TS2741: Property 'a' is missing in type '{}' but required in type '{ a: true; }'.
152+
!!! related TS2728 typeSatisfaction_errorLocations1.ts:50:8: 'a' is declared here.
153+
((): { a: true } => ((({}) satisfies unknown)) satisfies unknown)();
154+
~~
155+
!!! error TS2741: Property 'a' is missing in type '{}' but required in type '{ a: true; }'.
156+
!!! related TS2728 typeSatisfaction_errorLocations1.ts:51:8: 'a' is declared here.
146157

tests/baselines/reference/typeSatisfaction_errorLocations1.symbols

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,9 @@ function fn6(): number {
129129
>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 47, 6))
130130
>obj1 : Symbol(obj1, Decl(typeSatisfaction_errorLocations1.ts, 0, 5))
131131

132+
((): { a: true } => (({}) satisfies unknown) satisfies unknown)();
133+
>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 49, 6))
134+
135+
((): { a: true } => ((({}) satisfies unknown)) satisfies unknown)();
136+
>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 50, 6))
137+

tests/baselines/reference/typeSatisfaction_errorLocations1.types

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,49 @@ function fn6(): number {
384384
>obj1 : { a: number; }
385385
> : ^^^^^^^^^^^^^^
386386

387+
((): { a: true } => (({}) satisfies unknown) satisfies unknown)();
388+
>((): { a: true } => (({}) satisfies unknown) satisfies unknown)() : { a: true; }
389+
> : ^^^^^ ^^^
390+
>((): { a: true } => (({}) satisfies unknown) satisfies unknown) : () => { a: true; }
391+
> : ^^^^^^
392+
>(): { a: true } => (({}) satisfies unknown) satisfies unknown : () => { a: true; }
393+
> : ^^^^^^
394+
>a : true
395+
> : ^^^^
396+
>true : true
397+
> : ^^^^
398+
>(({}) satisfies unknown) satisfies unknown : {}
399+
> : ^^
400+
>(({}) satisfies unknown) : {}
401+
> : ^^
402+
>({}) satisfies unknown : {}
403+
> : ^^
404+
>({}) : {}
405+
> : ^^
406+
>{} : {}
407+
> : ^^
408+
409+
((): { a: true } => ((({}) satisfies unknown)) satisfies unknown)();
410+
>((): { a: true } => ((({}) satisfies unknown)) satisfies unknown)() : { a: true; }
411+
> : ^^^^^ ^^^
412+
>((): { a: true } => ((({}) satisfies unknown)) satisfies unknown) : () => { a: true; }
413+
> : ^^^^^^
414+
>(): { a: true } => ((({}) satisfies unknown)) satisfies unknown : () => { a: true; }
415+
> : ^^^^^^
416+
>a : true
417+
> : ^^^^
418+
>true : true
419+
> : ^^^^
420+
>((({}) satisfies unknown)) satisfies unknown : {}
421+
> : ^^
422+
>((({}) satisfies unknown)) : {}
423+
> : ^^
424+
>(({}) satisfies unknown) : {}
425+
> : ^^
426+
>({}) satisfies unknown : {}
427+
> : ^^
428+
>({}) : {}
429+
> : ^^
430+
>{} : {}
431+
> : ^^
432+
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// @strict: true
2+
// @noEmit: true
3+
// @checkJs: true
4+
// @allowJs: true
5+
6+
// @filename: mytest.js
7+
8+
/**
9+
* @template T
10+
* @param {T|undefined} value value or not
11+
* @returns {T} result value
12+
*/
13+
const foo1 = value => /** @type {string} */({ ...value });
14+
15+
/**
16+
* @template T
17+
* @param {T|undefined} value value or not
18+
* @returns {T} result value
19+
*/
20+
const foo2 = value => /** @type {string} */(/** @type {T} */({ ...value }));

tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,6 @@ function fn6(): number {
4949
((): { a: true } => ({}) satisfies unknown)();
5050
((): { a: true } => ({ a: 1 }) satisfies unknown)();
5151
((): { a: true } => obj1 satisfies unknown)();
52+
53+
((): { a: true } => (({}) satisfies unknown) satisfies unknown)();
54+
((): { a: true } => ((({}) satisfies unknown)) satisfies unknown)();

0 commit comments

Comments
 (0)