Fixed error spans for SatisfiesExpression check nodes (#56918)

This commit is contained in:
Mateusz Burzyński 2024-01-19 23:11:12 +01:00 committed by GitHub
parent 1982349339
commit 10a63a9bb8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 572 additions and 6 deletions

View File

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

View File

@ -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<T extends { a: true }[]>(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<string, number>;
~
!!! 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'.

View File

@ -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<T extends { a: true }[]>(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<string, number>;
>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))

View File

@ -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<T extends { a: true }[]>(f: (...args: T) => void) {
>fn2 : <T extends { a: true; }[]>(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<string, number>;
>obj2 : { a: number; b: boolean; }
>{ a: 10, b: true } satisfies Record<string, number> : { 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; }

View File

@ -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<T extends { a: true }[]>(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<string, number>;
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)();