From 10a63a9bb8647c07fa44bb840d9ddf4fb03a901c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 19 Jan 2024 23:11:12 +0100 Subject: [PATCH] Fixed error spans for `SatisfiesExpression` check nodes (#56918) --- src/compiler/checker.ts | 21 +- ...ypeSatisfaction_errorLocations1.errors.txt | 146 +++++++++++ .../typeSatisfaction_errorLocations1.symbols | 131 ++++++++++ .../typeSatisfaction_errorLocations1.types | 229 ++++++++++++++++++ .../typeSatisfaction_errorLocations1.ts | 51 ++++ 5 files changed, 572 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/typeSatisfaction_errorLocations1.errors.txt create mode 100644 tests/baselines/reference/typeSatisfaction_errorLocations1.symbols create mode 100644 tests/baselines/reference/typeSatisfaction_errorLocations1.types create mode 100644 tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8e6d48fceaa..6d56ae15fcb 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -700,6 +700,7 @@ import { isRightSideOfQualifiedNameOrPropertyAccess, isRightSideOfQualifiedNameOrPropertyAccessOrJSDocMemberName, isSameEntityName, + isSatisfiesExpression, isSetAccessor, isSetAccessorDeclaration, isShorthandAmbientModuleSymbol, @@ -20654,7 +20655,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const elem = node.elements[i]; if (isOmittedExpression(elem)) continue; const nameType = getNumberLiteralType(i); - yield { errorNode: elem, innerExpression: elem, nameType }; + const checkNode = getEffectiveCheckNode(elem); + yield { errorNode: checkNode, innerExpression: checkNode, nameType }; } } @@ -34190,6 +34192,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } + function getEffectiveCheckNode(argument: Expression): Expression { + argument = skipParentheses(argument); + return isSatisfiesExpression(argument) ? skipParentheses(argument.expression) : argument; + } + function getSignatureApplicabilityError( node: CallLikeExpression, args: readonly Expression[], @@ -34233,7 +34240,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // we obtain the regular type of any object literal arguments because we may not have inferred complete // parameter types yet and therefore excess property checks may yield false positives (see #17041). const checkArgType = checkMode & CheckMode.SkipContextSensitive ? getRegularTypeOfObjectLiteral(argType) : argType; - if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? arg : undefined, arg, headMessage, containingMessageChain, errorOutputContainer)) { + const effectiveCheckArgumentNode = getEffectiveCheckNode(arg); + if (!checkTypeRelatedToAndOptionallyElaborate(checkArgType, paramType, relation, reportErrors ? effectiveCheckArgumentNode : undefined, effectiveCheckArgumentNode, headMessage, containingMessageChain, errorOutputContainer)) { Debug.assert(!reportErrors || !!errorOutputContainer.errors, "parameter should have errors when reporting errors"); maybeAddMissingAwaitInfo(arg, checkArgType, paramType); return errorOutputContainer.errors || emptyArray; @@ -34245,7 +34253,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const restArgCount = args.length - argCount; const errorNode = !reportErrors ? undefined : restArgCount === 0 ? node : - restArgCount === 1 ? args[argCount] : + restArgCount === 1 ? getEffectiveCheckNode(args[argCount]) : setTextRangePosEnd(createSyntheticExpression(node, spreadType), args[argCount].pos, args[args.length - 1].end); if (!checkTypeRelatedTo(spreadType, restType, relation, errorNode, headMessage, /*containingMessageChain*/ undefined, errorOutputContainer)) { Debug.assert(!reportErrors || !!errorOutputContainer.errors, "rest parameter should have errors when reporting errors"); @@ -37536,12 +37544,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const exprType = checkExpression(node.body); const returnOrPromisedType = returnType && unwrapReturnType(returnType, functionFlags); if (returnOrPromisedType) { + const effectiveCheckNode = getEffectiveCheckNode(node.body); if ((functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async) { // Async function - const awaitedType = checkAwaitedType(exprType, /*withAlias*/ false, node.body, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); - checkTypeAssignableToAndOptionallyElaborate(awaitedType, returnOrPromisedType, node.body, node.body); + const awaitedType = checkAwaitedType(exprType, /*withAlias*/ false, effectiveCheckNode, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member); + checkTypeAssignableToAndOptionallyElaborate(awaitedType, returnOrPromisedType, effectiveCheckNode, effectiveCheckNode); } else { // Normal function - checkTypeAssignableToAndOptionallyElaborate(exprType, returnOrPromisedType, node.body, node.body); + checkTypeAssignableToAndOptionallyElaborate(exprType, returnOrPromisedType, effectiveCheckNode, effectiveCheckNode); } } } diff --git a/tests/baselines/reference/typeSatisfaction_errorLocations1.errors.txt b/tests/baselines/reference/typeSatisfaction_errorLocations1.errors.txt new file mode 100644 index 00000000000..0d31158d642 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_errorLocations1.errors.txt @@ -0,0 +1,146 @@ +typeSatisfaction_errorLocations1.ts(4,5): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ a: true; }'. + Property 'a' is missing in type '{}' but required in type '{ a: true; }'. +typeSatisfaction_errorLocations1.ts(5,7): error TS2322: Type 'number' is not assignable to type 'true'. +typeSatisfaction_errorLocations1.ts(6,5): error TS2345: Argument of type '{ a: number; }' is not assignable to parameter of type '{ a: true; }'. + Types of property 'a' are incompatible. + Type 'number' is not assignable to type 'true'. +typeSatisfaction_errorLocations1.ts(11,10): error TS2345: Argument of type '{}' is not assignable to parameter of type '{ a: true; }'. + Property 'a' is missing in type '{}' but required in type '{ a: true; }'. +typeSatisfaction_errorLocations1.ts(12,12): error TS2322: Type 'number' is not assignable to type 'true'. +typeSatisfaction_errorLocations1.ts(13,10): error TS2345: Argument of type '{ a: number; }' is not assignable to parameter of type '{ a: true; }'. + Types of property 'a' are incompatible. + Type 'number' is not assignable to type 'true'. +typeSatisfaction_errorLocations1.ts(16,5): error TS2345: Argument of type '[{ a: boolean; }]' is not assignable to parameter of type 'T'. + 'T' could be instantiated with an arbitrary type which could be unrelated to '[{ a: boolean; }]'. +typeSatisfaction_errorLocations1.ts(18,5): error TS2345: Argument of type '[{ a: true; }]' is not assignable to parameter of type 'T'. + '[{ a: true; }]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{ a: true; }[]'. +typeSatisfaction_errorLocations1.ts(21,43): error TS2322: Type 'number' is not assignable to type 'boolean'. +typeSatisfaction_errorLocations1.ts(23,23): error TS2322: Type 'boolean' is not assignable to type 'number'. +typeSatisfaction_errorLocations1.ts(25,20): error TS1360: Type 'number' does not satisfy the expected type 'boolean'. +typeSatisfaction_errorLocations1.ts(26,7): error TS2322: Type '1' is not assignable to type 'true'. +typeSatisfaction_errorLocations1.ts(29,18): error TS2322: Type 'string' is not assignable to type 'number'. +typeSatisfaction_errorLocations1.ts(31,20): error TS1360: Type 'readonly [10, "20"]' does not satisfy the expected type 'number[]'. + The type 'readonly [10, "20"]' is 'readonly' and cannot be assigned to the mutable type 'number[]'. +typeSatisfaction_errorLocations1.ts(34,9): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +typeSatisfaction_errorLocations1.ts(36,9): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. +typeSatisfaction_errorLocations1.ts(39,3): error TS2322: Type 'string' is not assignable to type 'number'. +typeSatisfaction_errorLocations1.ts(43,3): error TS2322: Type 'string' is not assignable to type 'number'. +typeSatisfaction_errorLocations1.ts(43,16): error TS1360: Type 'string' does not satisfy the expected type 'number'. +typeSatisfaction_errorLocations1.ts(46,22): error TS2741: Property 'a' is missing in type '{}' but required in type '{ a: true; }'. +typeSatisfaction_errorLocations1.ts(47,24): error TS2322: Type 'number' is not assignable to type 'true'. +typeSatisfaction_errorLocations1.ts(48,21): error TS2322: Type '{ a: number; }' is not assignable to type '{ a: true; }'. + Types of property 'a' are incompatible. + Type 'number' is not assignable to type 'true'. + + +==== typeSatisfaction_errorLocations1.ts (22 errors) ==== + const obj1 = { a: 1 }; + + const fn1 = (s: { a: true }) => {}; + fn1({} satisfies unknown); + ~~ +!!! error TS2345: Argument of type '{}' is not assignable to parameter of type '{ a: true; }'. +!!! error TS2345: Property 'a' is missing in type '{}' but required in type '{ a: true; }'. +!!! related TS2728 typeSatisfaction_errorLocations1.ts:3:19: 'a' is declared here. + fn1({ a: 1 } satisfies unknown); + ~ +!!! error TS2322: Type 'number' is not assignable to type 'true'. +!!! related TS6500 typeSatisfaction_errorLocations1.ts:3:19: The expected type comes from property 'a' which is declared here on type '{ a: true; }' + fn1(obj1 satisfies unknown); + ~~~~ +!!! error TS2345: Argument of type '{ a: number; }' is not assignable to parameter of type '{ a: true; }'. +!!! error TS2345: Types of property 'a' are incompatible. +!!! error TS2345: Type 'number' is not assignable to type 'true'. + + class Cls1 { + constructor(p: { a: true }) {} + } + new Cls1({} satisfies unknown); + ~~ +!!! error TS2345: Argument of type '{}' is not assignable to parameter of type '{ a: true; }'. +!!! error TS2345: Property 'a' is missing in type '{}' but required in type '{ a: true; }'. +!!! related TS2728 typeSatisfaction_errorLocations1.ts:9:20: 'a' is declared here. + new Cls1({ a: 1 } satisfies unknown); + ~ +!!! error TS2322: Type 'number' is not assignable to type 'true'. +!!! related TS6500 typeSatisfaction_errorLocations1.ts:9:20: The expected type comes from property 'a' which is declared here on type '{ a: true; }' + new Cls1(obj1 satisfies unknown); + ~~~~ +!!! error TS2345: Argument of type '{ a: number; }' is not assignable to parameter of type '{ a: true; }'. +!!! error TS2345: Types of property 'a' are incompatible. +!!! error TS2345: Type 'number' is not assignable to type 'true'. + + function fn2(f: (...args: T) => void) { + f({ a: true } satisfies unknown); + ~~~~~~~~~~~ +!!! error TS2345: Argument of type '[{ a: boolean; }]' is not assignable to parameter of type 'T'. +!!! error TS2345: 'T' could be instantiated with an arbitrary type which could be unrelated to '[{ a: boolean; }]'. + const o = { a: true as const }; + f(o satisfies unknown); + ~ +!!! error TS2345: Argument of type '[{ a: true; }]' is not assignable to parameter of type 'T'. +!!! error TS2345: '[{ a: true; }]' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint '{ a: true; }[]'. + } + + const tuple1: [boolean, boolean] = [true, 100 satisfies unknown]; + ~~~ +!!! error TS2322: Type 'number' is not assignable to type 'boolean'. + + const obj2 = { a: 10, b: true } satisfies Record; + ~ +!!! error TS2322: Type 'boolean' is not assignable to type 'number'. + + const literal1 = 1 satisfies boolean; + ~~~~~~~~~ +!!! error TS1360: Type 'number' does not satisfy the expected type 'boolean'. + const literal2: true = 1 satisfies number; + ~~~~~~~~ +!!! error TS2322: Type '1' is not assignable to type 'true'. + + declare function fn3(...args: unknown[]): void; + fn3(10, ...([10, "20"] satisfies number[])); + ~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. + const tuple2 = [10, "20"] as const; + fn3(10, ...(tuple2 satisfies number[])); + ~~~~~~~~~ +!!! error TS1360: Type 'readonly [10, "20"]' does not satisfy the expected type 'number[]'. +!!! error TS1360: The type 'readonly [10, "20"]' is 'readonly' and cannot be assigned to the mutable type 'number[]'. + + declare function fn4(...args: number[]): void; + fn4(10, ...(["10", "20"] satisfies readonly string[])); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + const tuple3 = ["10", "20"] as const; + fn4(10, ...(tuple3 satisfies readonly string[])); + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + + function fn5(): number { + return "foo" satisfies unknown; + ~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. + } + + function fn6(): number { + return "foo" satisfies number; + ~~~~~~ +!!! error TS2322: Type 'string' is not assignable to type 'number'. + ~~~~~~~~~ +!!! error TS1360: Type 'string' does not satisfy the expected type 'number'. + } + + ((): { a: true } => ({}) satisfies unknown)(); + ~~ +!!! error TS2741: Property 'a' is missing in type '{}' but required in type '{ a: true; }'. +!!! related TS2728 typeSatisfaction_errorLocations1.ts:46:8: 'a' is declared here. + ((): { a: true } => ({ a: 1 }) satisfies unknown)(); + ~ +!!! error TS2322: Type 'number' is not assignable to type 'true'. +!!! related TS6500 typeSatisfaction_errorLocations1.ts:47:8: The expected type comes from property 'a' which is declared here on type '{ a: true; }' + ((): { a: true } => obj1 satisfies unknown)(); + ~~~~ +!!! error TS2322: Type '{ a: number; }' is not assignable to type '{ a: true; }'. +!!! error TS2322: Types of property 'a' are incompatible. +!!! error TS2322: Type 'number' is not assignable to type 'true'. + \ No newline at end of file diff --git a/tests/baselines/reference/typeSatisfaction_errorLocations1.symbols b/tests/baselines/reference/typeSatisfaction_errorLocations1.symbols new file mode 100644 index 00000000000..f44c4deaa52 --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_errorLocations1.symbols @@ -0,0 +1,131 @@ +//// [tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts] //// + +=== typeSatisfaction_errorLocations1.ts === +const obj1 = { a: 1 }; +>obj1 : Symbol(obj1, Decl(typeSatisfaction_errorLocations1.ts, 0, 5)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 0, 14)) + +const fn1 = (s: { a: true }) => {}; +>fn1 : Symbol(fn1, Decl(typeSatisfaction_errorLocations1.ts, 2, 5)) +>s : Symbol(s, Decl(typeSatisfaction_errorLocations1.ts, 2, 13)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 2, 17)) + +fn1({} satisfies unknown); +>fn1 : Symbol(fn1, Decl(typeSatisfaction_errorLocations1.ts, 2, 5)) + +fn1({ a: 1 } satisfies unknown); +>fn1 : Symbol(fn1, Decl(typeSatisfaction_errorLocations1.ts, 2, 5)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 4, 5)) + +fn1(obj1 satisfies unknown); +>fn1 : Symbol(fn1, Decl(typeSatisfaction_errorLocations1.ts, 2, 5)) +>obj1 : Symbol(obj1, Decl(typeSatisfaction_errorLocations1.ts, 0, 5)) + +class Cls1 { +>Cls1 : Symbol(Cls1, Decl(typeSatisfaction_errorLocations1.ts, 5, 28)) + + constructor(p: { a: true }) {} +>p : Symbol(p, Decl(typeSatisfaction_errorLocations1.ts, 8, 14)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 8, 18)) +} +new Cls1({} satisfies unknown); +>Cls1 : Symbol(Cls1, Decl(typeSatisfaction_errorLocations1.ts, 5, 28)) + +new Cls1({ a: 1 } satisfies unknown); +>Cls1 : Symbol(Cls1, Decl(typeSatisfaction_errorLocations1.ts, 5, 28)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 11, 10)) + +new Cls1(obj1 satisfies unknown); +>Cls1 : Symbol(Cls1, Decl(typeSatisfaction_errorLocations1.ts, 5, 28)) +>obj1 : Symbol(obj1, Decl(typeSatisfaction_errorLocations1.ts, 0, 5)) + +function fn2(f: (...args: T) => void) { +>fn2 : Symbol(fn2, Decl(typeSatisfaction_errorLocations1.ts, 12, 33)) +>T : Symbol(T, Decl(typeSatisfaction_errorLocations1.ts, 14, 13)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 14, 24)) +>f : Symbol(f, Decl(typeSatisfaction_errorLocations1.ts, 14, 38)) +>args : Symbol(args, Decl(typeSatisfaction_errorLocations1.ts, 14, 42)) +>T : Symbol(T, Decl(typeSatisfaction_errorLocations1.ts, 14, 13)) + + f({ a: true } satisfies unknown); +>f : Symbol(f, Decl(typeSatisfaction_errorLocations1.ts, 14, 38)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 15, 5)) + + const o = { a: true as const }; +>o : Symbol(o, Decl(typeSatisfaction_errorLocations1.ts, 16, 7)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 16, 13)) +>const : Symbol(const) + + f(o satisfies unknown); +>f : Symbol(f, Decl(typeSatisfaction_errorLocations1.ts, 14, 38)) +>o : Symbol(o, Decl(typeSatisfaction_errorLocations1.ts, 16, 7)) +} + +const tuple1: [boolean, boolean] = [true, 100 satisfies unknown]; +>tuple1 : Symbol(tuple1, Decl(typeSatisfaction_errorLocations1.ts, 20, 5)) + +const obj2 = { a: 10, b: true } satisfies Record; +>obj2 : Symbol(obj2, Decl(typeSatisfaction_errorLocations1.ts, 22, 5)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 22, 14)) +>b : Symbol(b, Decl(typeSatisfaction_errorLocations1.ts, 22, 21)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) + +const literal1 = 1 satisfies boolean; +>literal1 : Symbol(literal1, Decl(typeSatisfaction_errorLocations1.ts, 24, 5)) + +const literal2: true = 1 satisfies number; +>literal2 : Symbol(literal2, Decl(typeSatisfaction_errorLocations1.ts, 25, 5)) + +declare function fn3(...args: unknown[]): void; +>fn3 : Symbol(fn3, Decl(typeSatisfaction_errorLocations1.ts, 25, 42)) +>args : Symbol(args, Decl(typeSatisfaction_errorLocations1.ts, 27, 21)) + +fn3(10, ...([10, "20"] satisfies number[])); +>fn3 : Symbol(fn3, Decl(typeSatisfaction_errorLocations1.ts, 25, 42)) + +const tuple2 = [10, "20"] as const; +>tuple2 : Symbol(tuple2, Decl(typeSatisfaction_errorLocations1.ts, 29, 5)) +>const : Symbol(const) + +fn3(10, ...(tuple2 satisfies number[])); +>fn3 : Symbol(fn3, Decl(typeSatisfaction_errorLocations1.ts, 25, 42)) +>tuple2 : Symbol(tuple2, Decl(typeSatisfaction_errorLocations1.ts, 29, 5)) + +declare function fn4(...args: number[]): void; +>fn4 : Symbol(fn4, Decl(typeSatisfaction_errorLocations1.ts, 30, 40)) +>args : Symbol(args, Decl(typeSatisfaction_errorLocations1.ts, 32, 21)) + +fn4(10, ...(["10", "20"] satisfies readonly string[])); +>fn4 : Symbol(fn4, Decl(typeSatisfaction_errorLocations1.ts, 30, 40)) + +const tuple3 = ["10", "20"] as const; +>tuple3 : Symbol(tuple3, Decl(typeSatisfaction_errorLocations1.ts, 34, 5)) +>const : Symbol(const) + +fn4(10, ...(tuple3 satisfies readonly string[])); +>fn4 : Symbol(fn4, Decl(typeSatisfaction_errorLocations1.ts, 30, 40)) +>tuple3 : Symbol(tuple3, Decl(typeSatisfaction_errorLocations1.ts, 34, 5)) + +function fn5(): number { +>fn5 : Symbol(fn5, Decl(typeSatisfaction_errorLocations1.ts, 35, 49)) + + return "foo" satisfies unknown; +} + +function fn6(): number { +>fn6 : Symbol(fn6, Decl(typeSatisfaction_errorLocations1.ts, 39, 1)) + + return "foo" satisfies number; +} + +((): { a: true } => ({}) satisfies unknown)(); +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 45, 6)) + +((): { a: true } => ({ a: 1 }) satisfies unknown)(); +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 46, 6)) +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 46, 22)) + +((): { a: true } => obj1 satisfies unknown)(); +>a : Symbol(a, Decl(typeSatisfaction_errorLocations1.ts, 47, 6)) +>obj1 : Symbol(obj1, Decl(typeSatisfaction_errorLocations1.ts, 0, 5)) + diff --git a/tests/baselines/reference/typeSatisfaction_errorLocations1.types b/tests/baselines/reference/typeSatisfaction_errorLocations1.types new file mode 100644 index 00000000000..e8e6de7184b --- /dev/null +++ b/tests/baselines/reference/typeSatisfaction_errorLocations1.types @@ -0,0 +1,229 @@ +//// [tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts] //// + +=== typeSatisfaction_errorLocations1.ts === +const obj1 = { a: 1 }; +>obj1 : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +const fn1 = (s: { a: true }) => {}; +>fn1 : (s: { a: true;}) => void +>(s: { a: true }) => {} : (s: { a: true;}) => void +>s : { a: true; } +>a : true +>true : true + +fn1({} satisfies unknown); +>fn1({} satisfies unknown) : void +>fn1 : (s: { a: true; }) => void +>{} satisfies unknown : {} +>{} : {} + +fn1({ a: 1 } satisfies unknown); +>fn1({ a: 1 } satisfies unknown) : void +>fn1 : (s: { a: true; }) => void +>{ a: 1 } satisfies unknown : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +fn1(obj1 satisfies unknown); +>fn1(obj1 satisfies unknown) : void +>fn1 : (s: { a: true; }) => void +>obj1 satisfies unknown : { a: number; } +>obj1 : { a: number; } + +class Cls1 { +>Cls1 : Cls1 + + constructor(p: { a: true }) {} +>p : { a: true; } +>a : true +>true : true +} +new Cls1({} satisfies unknown); +>new Cls1({} satisfies unknown) : Cls1 +>Cls1 : typeof Cls1 +>{} satisfies unknown : {} +>{} : {} + +new Cls1({ a: 1 } satisfies unknown); +>new Cls1({ a: 1 } satisfies unknown) : Cls1 +>Cls1 : typeof Cls1 +>{ a: 1 } satisfies unknown : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +new Cls1(obj1 satisfies unknown); +>new Cls1(obj1 satisfies unknown) : Cls1 +>Cls1 : typeof Cls1 +>obj1 satisfies unknown : { a: number; } +>obj1 : { a: number; } + +function fn2(f: (...args: T) => void) { +>fn2 : (f: (...args: T) => void) => void +>a : true +>true : true +>f : (...args: T) => void +>args : T + + f({ a: true } satisfies unknown); +>f({ a: true } satisfies unknown) : void +>f : (...args: T) => void +>{ a: true } satisfies unknown : { a: boolean; } +>{ a: true } : { a: boolean; } +>a : boolean +>true : true + + const o = { a: true as const }; +>o : { a: true; } +>{ a: true as const } : { a: true; } +>a : true +>true as const : true +>true : true + + f(o satisfies unknown); +>f(o satisfies unknown) : void +>f : (...args: T) => void +>o satisfies unknown : { a: true; } +>o : { a: true; } +} + +const tuple1: [boolean, boolean] = [true, 100 satisfies unknown]; +>tuple1 : [boolean, boolean] +>[true, 100 satisfies unknown] : [true, number] +>true : true +>100 satisfies unknown : 100 +>100 : 100 + +const obj2 = { a: 10, b: true } satisfies Record; +>obj2 : { a: number; b: boolean; } +>{ a: 10, b: true } satisfies Record : { a: number; b: boolean; } +>{ a: 10, b: true } : { a: number; b: boolean; } +>a : number +>10 : 10 +>b : boolean +>true : true + +const literal1 = 1 satisfies boolean; +>literal1 : 1 +>1 satisfies boolean : 1 +>1 : 1 + +const literal2: true = 1 satisfies number; +>literal2 : true +>true : true +>1 satisfies number : 1 +>1 : 1 + +declare function fn3(...args: unknown[]): void; +>fn3 : (...args: unknown[]) => void +>args : unknown[] + +fn3(10, ...([10, "20"] satisfies number[])); +>fn3(10, ...([10, "20"] satisfies number[])) : void +>fn3 : (...args: unknown[]) => void +>10 : 10 +>...([10, "20"] satisfies number[]) : string | number +>([10, "20"] satisfies number[]) : (string | number)[] +>[10, "20"] satisfies number[] : (string | number)[] +>[10, "20"] : (string | number)[] +>10 : 10 +>"20" : "20" + +const tuple2 = [10, "20"] as const; +>tuple2 : readonly [10, "20"] +>[10, "20"] as const : readonly [10, "20"] +>[10, "20"] : readonly [10, "20"] +>10 : 10 +>"20" : "20" + +fn3(10, ...(tuple2 satisfies number[])); +>fn3(10, ...(tuple2 satisfies number[])) : void +>fn3 : (...args: unknown[]) => void +>10 : 10 +>...(tuple2 satisfies number[]) : 10 | "20" +>(tuple2 satisfies number[]) : readonly [10, "20"] +>tuple2 satisfies number[] : readonly [10, "20"] +>tuple2 : readonly [10, "20"] + +declare function fn4(...args: number[]): void; +>fn4 : (...args: number[]) => void +>args : number[] + +fn4(10, ...(["10", "20"] satisfies readonly string[])); +>fn4(10, ...(["10", "20"] satisfies readonly string[])) : void +>fn4 : (...args: number[]) => void +>10 : 10 +>...(["10", "20"] satisfies readonly string[]) : string +>(["10", "20"] satisfies readonly string[]) : string[] +>["10", "20"] satisfies readonly string[] : string[] +>["10", "20"] : string[] +>"10" : "10" +>"20" : "20" + +const tuple3 = ["10", "20"] as const; +>tuple3 : readonly ["10", "20"] +>["10", "20"] as const : readonly ["10", "20"] +>["10", "20"] : readonly ["10", "20"] +>"10" : "10" +>"20" : "20" + +fn4(10, ...(tuple3 satisfies readonly string[])); +>fn4(10, ...(tuple3 satisfies readonly string[])) : void +>fn4 : (...args: number[]) => void +>10 : 10 +>...(tuple3 satisfies readonly string[]) : "20" | "10" +>(tuple3 satisfies readonly string[]) : readonly ["10", "20"] +>tuple3 satisfies readonly string[] : readonly ["10", "20"] +>tuple3 : readonly ["10", "20"] + +function fn5(): number { +>fn5 : () => number + + return "foo" satisfies unknown; +>"foo" satisfies unknown : "foo" +>"foo" : "foo" +} + +function fn6(): number { +>fn6 : () => number + + return "foo" satisfies number; +>"foo" satisfies number : "foo" +>"foo" : "foo" +} + +((): { a: true } => ({}) satisfies unknown)(); +>((): { a: true } => ({}) satisfies unknown)() : { a: true; } +>((): { a: true } => ({}) satisfies unknown) : () => { a: true;} +>(): { a: true } => ({}) satisfies unknown : () => { a: true;} +>a : true +>true : true +>({}) satisfies unknown : {} +>({}) : {} +>{} : {} + +((): { a: true } => ({ a: 1 }) satisfies unknown)(); +>((): { a: true } => ({ a: 1 }) satisfies unknown)() : { a: true; } +>((): { a: true } => ({ a: 1 }) satisfies unknown) : () => { a: true;} +>(): { a: true } => ({ a: 1 }) satisfies unknown : () => { a: true;} +>a : true +>true : true +>({ a: 1 }) satisfies unknown : { a: number; } +>({ a: 1 }) : { a: number; } +>{ a: 1 } : { a: number; } +>a : number +>1 : 1 + +((): { a: true } => obj1 satisfies unknown)(); +>((): { a: true } => obj1 satisfies unknown)() : { a: true; } +>((): { a: true } => obj1 satisfies unknown) : () => { a: true;} +>(): { a: true } => obj1 satisfies unknown : () => { a: true;} +>a : true +>true : true +>obj1 satisfies unknown : { a: number; } +>obj1 : { a: number; } + diff --git a/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts new file mode 100644 index 00000000000..11276d5ca26 --- /dev/null +++ b/tests/cases/conformance/expressions/typeSatisfaction/typeSatisfaction_errorLocations1.ts @@ -0,0 +1,51 @@ +// @strict: true +// @noEmit: true + +const obj1 = { a: 1 }; + +const fn1 = (s: { a: true }) => {}; +fn1({} satisfies unknown); +fn1({ a: 1 } satisfies unknown); +fn1(obj1 satisfies unknown); + +class Cls1 { + constructor(p: { a: true }) {} +} +new Cls1({} satisfies unknown); +new Cls1({ a: 1 } satisfies unknown); +new Cls1(obj1 satisfies unknown); + +function fn2(f: (...args: T) => void) { + f({ a: true } satisfies unknown); + const o = { a: true as const }; + f(o satisfies unknown); +} + +const tuple1: [boolean, boolean] = [true, 100 satisfies unknown]; + +const obj2 = { a: 10, b: true } satisfies Record; + +const literal1 = 1 satisfies boolean; +const literal2: true = 1 satisfies number; + +declare function fn3(...args: unknown[]): void; +fn3(10, ...([10, "20"] satisfies number[])); +const tuple2 = [10, "20"] as const; +fn3(10, ...(tuple2 satisfies number[])); + +declare function fn4(...args: number[]): void; +fn4(10, ...(["10", "20"] satisfies readonly string[])); +const tuple3 = ["10", "20"] as const; +fn4(10, ...(tuple3 satisfies readonly string[])); + +function fn5(): number { + return "foo" satisfies unknown; +} + +function fn6(): number { + return "foo" satisfies number; +} + +((): { a: true } => ({}) satisfies unknown)(); +((): { a: true } => ({ a: 1 }) satisfies unknown)(); +((): { a: true } => obj1 satisfies unknown)();