diff --git a/internal/checker/checker.go b/internal/checker/checker.go
index b639d488e44..c55b43a24a2 100644
--- a/internal/checker/checker.go
+++ b/internal/checker/checker.go
@@ -16441,7 +16441,12 @@ func (c *Checker) getNonMissingTypeOfSymbol(symbol *ast.Symbol) *Type {
func (c *Checker) getTypeOfInstantiatedSymbol(symbol *ast.Symbol) *Type {
links := c.valueSymbolLinks.Get(symbol)
if links.resolvedType == nil {
- links.resolvedType = c.instantiateType(c.getTypeOfSymbol(links.target), links.mapper)
+ declaration := links.target.ValueDeclaration
+ t := c.instantiateType(c.getTypeOfSymbol(links.target), links.mapper)
+ if declaration != nil && ast.IsParameterDeclaration(declaration) && hasDotDotDotToken(declaration) {
+ t = c.normalizeNoInferSpread(t)
+ }
+ links.resolvedType = t
}
return links.resolvedType
}
@@ -16518,9 +16523,14 @@ func (c *Checker) getTypeOfVariableOrParameterOrPropertyWorker(symbol *ast.Symbo
}
var result *Type
switch declaration.Kind {
- case ast.KindParameter, ast.KindPropertyDeclaration, ast.KindPropertySignature, ast.KindVariableDeclaration,
+ case ast.KindPropertyDeclaration, ast.KindPropertySignature, ast.KindVariableDeclaration,
ast.KindBindingElement:
result = c.getWidenedTypeForVariableLikeDeclaration(declaration, true /*reportErrors*/)
+ case ast.KindParameter:
+ result = c.getWidenedTypeForVariableLikeDeclaration(declaration, true /*reportErrors*/)
+ if hasDotDotDotToken(declaration) {
+ result = c.normalizeNoInferSpread(result)
+ }
case ast.KindPropertyAssignment:
result = c.checkPropertyAssignment(declaration, CheckModeNormal)
case ast.KindShorthandPropertyAssignment:
@@ -23215,6 +23225,12 @@ func (c *Checker) createNormalizedTupleTypeEx(target *Type, elementTypes []*Type
return c.createTypeReferenceEx(target, elementTypes, objectFlags)
}
if d.combinedFlags&ElementFlagsVariadic != 0 {
+ elementTypes = core.SameMapIndex(elementTypes, func(t *Type, i int) *Type {
+ if i < len(d.elementInfos) && d.elementInfos[i].flags&ElementFlagsVariadic != 0 {
+ return c.normalizeNoInferSpread(t)
+ }
+ return t
+ })
for i, e := range elementTypes {
if i < len(d.elementInfos) && d.elementInfos[i].flags&ElementFlagsVariadic != 0 && e.flags&(TypeFlagsNever|TypeFlagsUnion) != 0 {
// Transform [A, ...(X | Y | Z)] into [A, ...X] | [A, ...Y] | [A, ...Z]
@@ -23256,6 +23272,19 @@ func (c *Checker) createNormalizedTupleTypeEx(target *Type, elementTypes []*Type
return tupleTarget
}
+func (c *Checker) normalizeNoInferSpread(t *Type) *Type {
+ if !c.isNoInferType(t) {
+ return t
+ }
+ return c.mapType(t.AsSubstitutionType().baseType, func(element *Type) *Type {
+ if !isTupleType(element) {
+ return c.getNoInferType(t)
+ }
+ target := element.TargetTupleType()
+ return c.createTupleTypeEx(core.Map(c.getElementTypes(element), c.getNoInferType), target.elementInfos, target.readonly)
+ })
+}
+
func (c *Checker) createNormalizedTupleType(target *Type, elementTypes []*Type) *Type {
return c.createNormalizedTupleTypeEx(target, elementTypes, ObjectFlagsNone)
}
diff --git a/testdata/baselines/reference/conformance/noInferRestSpread1.errors.txt b/testdata/baselines/reference/conformance/noInferRestSpread1.errors.txt
new file mode 100644
index 00000000000..21f67ac0e0a
--- /dev/null
+++ b/testdata/baselines/reference/conformance/noInferRestSpread1.errors.txt
@@ -0,0 +1,41 @@
+noInferRestSpread1.ts(7,22): error TS2345: Argument of type '(a: number, b: number) => void' is not assignable to parameter of type '(args_0: number) => void'.
+ Target signature provides too few arguments. Expected 2 or more, but got 1.
+
+
+==== noInferRestSpread1.ts (1 errors) ====
+ declare function call(
+ arg: (...args: NoInfer) => void,
+ ...args: A
+ ): A;
+
+ const result1 = call((a: number) => {}, 1, 2);
+ const result2 = call((a: number, b: number) => {}, 1); // error
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+!!! error TS2345: Argument of type '(a: number, b: number) => void' is not assignable to parameter of type '(args_0: number) => void'.
+!!! error TS2345: Target signature provides too few arguments. Expected 2 or more, but got 1.
+ const result3 = call((a) => {}, 1, ''); // test contextual parameters
+ const result4 = call((a, b) => {}, 1, ''); // test contextual parameters
+ const result5 = call((...args) => {}, 1, ''); // test contextual parameters
+ const result6 = call((a, ...rest) => {}, 1, ''); // test contextual parameters
+
+ declare function fn1(
+ cb: (a: [number, ...NoInfer]) => void,
+ args: A,
+ ): A;
+
+ declare const singleStr: [string];
+
+ const result7 = fn1((arg) => {
+ arg.length;
+ }, singleStr);
+
+ declare const tupleUnion: [string] | [number, boolean];
+
+ const result8 = fn1((arg) => {
+ arg.length;
+ }, tupleUnion);
+
+ declare function fn2(arg: (...args: NoInfer<[string, number]>) => void): void;
+
+ fn2((a, ...rest) => {});
+
\ No newline at end of file
diff --git a/testdata/baselines/reference/conformance/noInferRestSpread1.symbols b/testdata/baselines/reference/conformance/noInferRestSpread1.symbols
new file mode 100644
index 00000000000..18dc968f1ab
--- /dev/null
+++ b/testdata/baselines/reference/conformance/noInferRestSpread1.symbols
@@ -0,0 +1,113 @@
+//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread1.ts] ////
+
+=== noInferRestSpread1.ts ===
+declare function call(
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 0, 22))
+
+ arg: (...args: NoInfer) => void,
+>arg : Symbol(arg, Decl(noInferRestSpread1.ts, 0, 52))
+>args : Symbol(args, Decl(noInferRestSpread1.ts, 1, 8))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 0, 22))
+
+ ...args: A
+>args : Symbol(args, Decl(noInferRestSpread1.ts, 1, 37))
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 0, 22))
+
+): A;
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 0, 22))
+
+const result1 = call((a: number) => {}, 1, 2);
+>result1 : Symbol(result1, Decl(noInferRestSpread1.ts, 5, 5))
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 5, 22))
+
+const result2 = call((a: number, b: number) => {}, 1); // error
+>result2 : Symbol(result2, Decl(noInferRestSpread1.ts, 6, 5))
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 6, 22))
+>b : Symbol(b, Decl(noInferRestSpread1.ts, 6, 32))
+
+const result3 = call((a) => {}, 1, ''); // test contextual parameters
+>result3 : Symbol(result3, Decl(noInferRestSpread1.ts, 7, 5))
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 7, 22))
+
+const result4 = call((a, b) => {}, 1, ''); // test contextual parameters
+>result4 : Symbol(result4, Decl(noInferRestSpread1.ts, 8, 5))
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 8, 22))
+>b : Symbol(b, Decl(noInferRestSpread1.ts, 8, 24))
+
+const result5 = call((...args) => {}, 1, ''); // test contextual parameters
+>result5 : Symbol(result5, Decl(noInferRestSpread1.ts, 9, 5))
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>args : Symbol(args, Decl(noInferRestSpread1.ts, 9, 22))
+
+const result6 = call((a, ...rest) => {}, 1, ''); // test contextual parameters
+>result6 : Symbol(result6, Decl(noInferRestSpread1.ts, 10, 5))
+>call : Symbol(call, Decl(noInferRestSpread1.ts, 0, 0))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 10, 22))
+>rest : Symbol(rest, Decl(noInferRestSpread1.ts, 10, 24))
+
+declare function fn1(
+>fn1 : Symbol(fn1, Decl(noInferRestSpread1.ts, 10, 48))
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 12, 21))
+
+ cb: (a: [number, ...NoInfer]) => void,
+>cb : Symbol(cb, Decl(noInferRestSpread1.ts, 12, 42))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 13, 7))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 12, 21))
+
+ args: A,
+>args : Symbol(args, Decl(noInferRestSpread1.ts, 13, 43))
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 12, 21))
+
+): A;
+>A : Symbol(A, Decl(noInferRestSpread1.ts, 12, 21))
+
+declare const singleStr: [string];
+>singleStr : Symbol(singleStr, Decl(noInferRestSpread1.ts, 17, 13))
+
+const result7 = fn1((arg) => {
+>result7 : Symbol(result7, Decl(noInferRestSpread1.ts, 19, 5))
+>fn1 : Symbol(fn1, Decl(noInferRestSpread1.ts, 10, 48))
+>arg : Symbol(arg, Decl(noInferRestSpread1.ts, 19, 21))
+
+ arg.length;
+>arg.length : Symbol(length)
+>arg : Symbol(arg, Decl(noInferRestSpread1.ts, 19, 21))
+>length : Symbol(length)
+
+}, singleStr);
+>singleStr : Symbol(singleStr, Decl(noInferRestSpread1.ts, 17, 13))
+
+declare const tupleUnion: [string] | [number, boolean];
+>tupleUnion : Symbol(tupleUnion, Decl(noInferRestSpread1.ts, 23, 13))
+
+const result8 = fn1((arg) => {
+>result8 : Symbol(result8, Decl(noInferRestSpread1.ts, 25, 5))
+>fn1 : Symbol(fn1, Decl(noInferRestSpread1.ts, 10, 48))
+>arg : Symbol(arg, Decl(noInferRestSpread1.ts, 25, 21))
+
+ arg.length;
+>arg.length : Symbol(length)
+>arg : Symbol(arg, Decl(noInferRestSpread1.ts, 25, 21))
+>length : Symbol(length)
+
+}, tupleUnion);
+>tupleUnion : Symbol(tupleUnion, Decl(noInferRestSpread1.ts, 23, 13))
+
+declare function fn2(arg: (...args: NoInfer<[string, number]>) => void): void;
+>fn2 : Symbol(fn2, Decl(noInferRestSpread1.ts, 27, 15))
+>arg : Symbol(arg, Decl(noInferRestSpread1.ts, 29, 21))
+>args : Symbol(args, Decl(noInferRestSpread1.ts, 29, 27))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+
+fn2((a, ...rest) => {});
+>fn2 : Symbol(fn2, Decl(noInferRestSpread1.ts, 27, 15))
+>a : Symbol(a, Decl(noInferRestSpread1.ts, 31, 5))
+>rest : Symbol(rest, Decl(noInferRestSpread1.ts, 31, 7))
+
diff --git a/testdata/baselines/reference/conformance/noInferRestSpread1.types b/testdata/baselines/reference/conformance/noInferRestSpread1.types
new file mode 100644
index 00000000000..732799eb52a
--- /dev/null
+++ b/testdata/baselines/reference/conformance/noInferRestSpread1.types
@@ -0,0 +1,131 @@
+//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread1.ts] ////
+
+=== noInferRestSpread1.ts ===
+declare function call(
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+
+ arg: (...args: NoInfer) => void,
+>arg : (...args: NoInfer) => void
+>args : NoInfer
+
+ ...args: A
+>args : A
+
+): A;
+
+const result1 = call((a: number) => {}, 1, 2);
+>result1 : [number, number]
+>call((a: number) => {}, 1, 2) : [number, number]
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+>(a: number) => {} : (a: number) => void
+>a : number
+>1 : 1
+>2 : 2
+
+const result2 = call((a: number, b: number) => {}, 1); // error
+>result2 : [number]
+>call((a: number, b: number) => {}, 1) : [number]
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+>(a: number, b: number) => {} : (a: number, b: number) => void
+>a : number
+>b : number
+>1 : 1
+
+const result3 = call((a) => {}, 1, ''); // test contextual parameters
+>result3 : [number, string]
+>call((a) => {}, 1, '') : [number, string]
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+>(a) => {} : (a: number) => void
+>a : number
+>1 : 1
+>'' : ""
+
+const result4 = call((a, b) => {}, 1, ''); // test contextual parameters
+>result4 : [number, string]
+>call((a, b) => {}, 1, '') : [number, string]
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+>(a, b) => {} : (a: number, b: string) => void
+>a : number
+>b : string
+>1 : 1
+>'' : ""
+
+const result5 = call((...args) => {}, 1, ''); // test contextual parameters
+>result5 : [number, string]
+>call((...args) => {}, 1, '') : [number, string]
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+>(...args) => {} : (args_0: number, args_1: string) => void
+>args : [number, string]
+>1 : 1
+>'' : ""
+
+const result6 = call((a, ...rest) => {}, 1, ''); // test contextual parameters
+>result6 : [number, string]
+>call((a, ...rest) => {}, 1, '') : [number, string]
+>call : (arg: (...args: NoInfer) => void, ...args: A) => A
+>(a, ...rest) => {} : (a: number, rest_0: string) => void
+>a : number
+>rest : [string]
+>1 : 1
+>'' : ""
+
+declare function fn1(
+>fn1 : (cb: (a: [number, ...NoInfer]) => void, args: A) => A
+
+ cb: (a: [number, ...NoInfer]) => void,
+>cb : (a: [number, ...NoInfer]) => void
+>a : [number, ...NoInfer]
+
+ args: A,
+>args : A
+
+): A;
+
+declare const singleStr: [string];
+>singleStr : [string]
+
+const result7 = fn1((arg) => {
+>result7 : [string]
+>fn1((arg) => { arg.length;}, singleStr) : [string]
+>fn1 : (cb: (a: [number, ...NoInfer]) => void, args: A) => A
+>(arg) => { arg.length;} : (arg: [number, string]) => void
+>arg : [number, string]
+
+ arg.length;
+>arg.length : 2
+>arg : [number, string]
+>length : 2
+
+}, singleStr);
+>singleStr : [string]
+
+declare const tupleUnion: [string] | [number, boolean];
+>tupleUnion : [string] | [number, boolean]
+
+const result8 = fn1((arg) => {
+>result8 : [string] | [number, boolean]
+>fn1((arg) => { arg.length;}, tupleUnion) : [string] | [number, boolean]
+>fn1 : (cb: (a: [number, ...NoInfer]) => void, args: A) => A
+>(arg) => { arg.length;} : (arg: [number, string] | [number, number, boolean]) => void
+>arg : [number, string] | [number, number, boolean]
+
+ arg.length;
+>arg.length : 2 | 3
+>arg : [number, string] | [number, number, boolean]
+>length : 2 | 3
+
+}, tupleUnion);
+>tupleUnion : [string] | [number, boolean]
+
+declare function fn2(arg: (...args: NoInfer<[string, number]>) => void): void;
+>fn2 : (arg: (...args: NoInfer<[string, number]>) => void) => void
+>arg : (args_0: string, args_1: number) => void
+>args : [string, number]
+
+fn2((a, ...rest) => {});
+>fn2((a, ...rest) => {}) : void
+>fn2 : (arg: (...args: NoInfer<[string, number]>) => void) => void
+>(a, ...rest) => {} : (a: string, rest_0: number) => void
+>a : string
+>rest : [number]
+
diff --git a/testdata/baselines/reference/conformance/noInferRestSpread2.symbols b/testdata/baselines/reference/conformance/noInferRestSpread2.symbols
new file mode 100644
index 00000000000..67eeffa1d18
--- /dev/null
+++ b/testdata/baselines/reference/conformance/noInferRestSpread2.symbols
@@ -0,0 +1,106 @@
+//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread2.ts] ////
+
+=== noInferRestSpread2.ts ===
+// https://github.com/microsoft/TypeScript/issues/63627
+
+function arr1(a: [number, ...NoInfer<[]>]) {}
+>arr1 : Symbol(arr1, Decl(noInferRestSpread2.ts, 0, 0))
+>a : Symbol(a, Decl(noInferRestSpread2.ts, 2, 14))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+
+arr1([1]);
+>arr1 : Symbol(arr1, Decl(noInferRestSpread2.ts, 0, 0))
+
+function arr2(a: [number, ...[]]) {}
+>arr2 : Symbol(arr2, Decl(noInferRestSpread2.ts, 3, 10))
+>a : Symbol(a, Decl(noInferRestSpread2.ts, 5, 14))
+
+arr2([1]);
+>arr2 : Symbol(arr2, Decl(noInferRestSpread2.ts, 3, 10))
+
+function fun1(a: (x: number, ...o: NoInfer<[]>) => void) {}
+>fun1 : Symbol(fun1, Decl(noInferRestSpread2.ts, 6, 10))
+>a : Symbol(a, Decl(noInferRestSpread2.ts, 8, 14))
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 8, 18))
+>o : Symbol(o, Decl(noInferRestSpread2.ts, 8, 28))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+
+fun1(x => {});
+>fun1 : Symbol(fun1, Decl(noInferRestSpread2.ts, 6, 10))
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 9, 5))
+
+function fun2(a: (x: number, ...o: []) => void) {}
+>fun2 : Symbol(fun2, Decl(noInferRestSpread2.ts, 9, 14))
+>a : Symbol(a, Decl(noInferRestSpread2.ts, 11, 14))
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 11, 18))
+>o : Symbol(o, Decl(noInferRestSpread2.ts, 11, 28))
+
+fun2(x => {});
+>fun2 : Symbol(fun2, Decl(noInferRestSpread2.ts, 9, 14))
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 12, 5))
+
+function func1(
+>func1 : Symbol(func1, Decl(noInferRestSpread2.ts, 12, 14))
+>A : Symbol(A, Decl(noInferRestSpread2.ts, 14, 15))
+
+ args: A,
+>args : Symbol(args, Decl(noInferRestSpread2.ts, 14, 36))
+>A : Symbol(A, Decl(noInferRestSpread2.ts, 14, 15))
+
+ fn: (x: number, ...args: NoInfer) => void,
+>fn : Symbol(fn, Decl(noInferRestSpread2.ts, 15, 10))
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 16, 7))
+>args : Symbol(args, Decl(noInferRestSpread2.ts, 16, 17))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+>A : Symbol(A, Decl(noInferRestSpread2.ts, 14, 15))
+
+) {}
+
+func1([] as const, x => {});
+>func1 : Symbol(func1, Decl(noInferRestSpread2.ts, 12, 14))
+>const : Symbol(const)
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 19, 18))
+
+function func2(
+>func2 : Symbol(func2, Decl(noInferRestSpread2.ts, 19, 28))
+>A : Symbol(A, Decl(noInferRestSpread2.ts, 21, 15))
+
+ args: A,
+>args : Symbol(args, Decl(noInferRestSpread2.ts, 21, 36))
+>A : Symbol(A, Decl(noInferRestSpread2.ts, 21, 15))
+
+ fn: (...args: NoInfer) => void,
+>fn : Symbol(fn, Decl(noInferRestSpread2.ts, 22, 10))
+>args : Symbol(args, Decl(noInferRestSpread2.ts, 23, 7))
+>NoInfer : Symbol(NoInfer, Decl(lib.es5.d.ts, --, --))
+>A : Symbol(A, Decl(noInferRestSpread2.ts, 21, 15))
+
+) {}
+
+function foo(u: number, v: number) {
+>foo : Symbol(foo, Decl(noInferRestSpread2.ts, 24, 4))
+>u : Symbol(u, Decl(noInferRestSpread2.ts, 26, 13))
+>v : Symbol(v, Decl(noInferRestSpread2.ts, 26, 23))
+
+ func2([u, v] as const, () => {});
+>func2 : Symbol(func2, Decl(noInferRestSpread2.ts, 19, 28))
+>u : Symbol(u, Decl(noInferRestSpread2.ts, 26, 13))
+>v : Symbol(v, Decl(noInferRestSpread2.ts, 26, 23))
+>const : Symbol(const)
+
+ func2([u, v] as const, (x: number) => {});
+>func2 : Symbol(func2, Decl(noInferRestSpread2.ts, 19, 28))
+>u : Symbol(u, Decl(noInferRestSpread2.ts, 26, 13))
+>v : Symbol(v, Decl(noInferRestSpread2.ts, 26, 23))
+>const : Symbol(const)
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 28, 26))
+
+ func2([u, v] as const, (x: number, y: number) => {});
+>func2 : Symbol(func2, Decl(noInferRestSpread2.ts, 19, 28))
+>u : Symbol(u, Decl(noInferRestSpread2.ts, 26, 13))
+>v : Symbol(v, Decl(noInferRestSpread2.ts, 26, 23))
+>const : Symbol(const)
+>x : Symbol(x, Decl(noInferRestSpread2.ts, 29, 26))
+>y : Symbol(y, Decl(noInferRestSpread2.ts, 29, 36))
+}
+
diff --git a/testdata/baselines/reference/conformance/noInferRestSpread2.types b/testdata/baselines/reference/conformance/noInferRestSpread2.types
new file mode 100644
index 00000000000..cbba8a94908
--- /dev/null
+++ b/testdata/baselines/reference/conformance/noInferRestSpread2.types
@@ -0,0 +1,118 @@
+//// [tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread2.ts] ////
+
+=== noInferRestSpread2.ts ===
+// https://github.com/microsoft/TypeScript/issues/63627
+
+function arr1(a: [number, ...NoInfer<[]>]) {}
+>arr1 : (a: [number, ...NoInfer<[]>]) => void
+>a : [number]
+
+arr1([1]);
+>arr1([1]) : void
+>arr1 : (a: [number, ...NoInfer<[]>]) => void
+>[1] : [number]
+>1 : 1
+
+function arr2(a: [number, ...[]]) {}
+>arr2 : (a: [number, ...[]]) => void
+>a : [number]
+
+arr2([1]);
+>arr2([1]) : void
+>arr2 : (a: [number, ...[]]) => void
+>[1] : [number]
+>1 : 1
+
+function fun1(a: (x: number, ...o: NoInfer<[]>) => void) {}
+>fun1 : (a: (x: number, ...o: NoInfer<[]>) => void) => void
+>a : (x: number) => void
+>x : number
+>o : []
+
+fun1(x => {});
+>fun1(x => {}) : void
+>fun1 : (a: (x: number, ...o: NoInfer<[]>) => void) => void
+>x => {} : (x: number) => void
+>x : number
+
+function fun2(a: (x: number, ...o: []) => void) {}
+>fun2 : (a: (x: number, ...o: []) => void) => void
+>a : (x: number) => void
+>x : number
+>o : []
+
+fun2(x => {});
+>fun2(x => {}) : void
+>fun2 : (a: (x: number, ...o: []) => void) => void
+>x => {} : (x: number) => void
+>x : number
+
+function func1(
+>func1 : (args: A, fn: (x: number, ...args: NoInfer) => void) => void
+
+ args: A,
+>args : A
+
+ fn: (x: number, ...args: NoInfer) => void,
+>fn : (x: number, ...args: NoInfer) => void
+>x : number
+>args : NoInfer
+
+) {}
+
+func1([] as const, x => {});
+>func1([] as const, x => {}) : void
+>func1 : (args: A, fn: (x: number, ...args: NoInfer) => void) => void
+>[] as const : []
+>[] : []
+>x => {} : (x: number) => void
+>x : number
+
+function func2(
+>func2 : (args: A, fn: (...args: NoInfer) => void) => void
+
+ args: A,
+>args : A
+
+ fn: (...args: NoInfer) => void,
+>fn : (...args: NoInfer) => void
+>args : NoInfer
+
+) {}
+
+function foo(u: number, v: number) {
+>foo : (u: number, v: number) => void
+>u : number
+>v : number
+
+ func2([u, v] as const, () => {});
+>func2([u, v] as const, () => {}) : void
+>func2 : (args: A, fn: (...args: NoInfer) => void) => void
+>[u, v] as const : [number, number]
+>[u, v] : [number, number]
+>u : number
+>v : number
+>() => {} : () => void
+
+ func2([u, v] as const, (x: number) => {});
+>func2([u, v] as const, (x: number) => {}) : void
+>func2 : (args: A, fn: (...args: NoInfer) => void) => void
+>[u, v] as const : [number, number]
+>[u, v] : [number, number]
+>u : number
+>v : number
+>(x: number) => {} : (x: number) => void
+>x : number
+
+ func2([u, v] as const, (x: number, y: number) => {});
+>func2([u, v] as const, (x: number, y: number) => {}) : void
+>func2 : (args: A, fn: (...args: NoInfer) => void) => void
+>[u, v] as const : [number, number]
+>[u, v] : [number, number]
+>u : number
+>v : number
+>(x: number, y: number) => {} : (x: number, y: number) => void
+>x : number
+>y : number
+}
+
diff --git a/testdata/tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread1.ts b/testdata/tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread1.ts
new file mode 100644
index 00000000000..c86f2ec235a
--- /dev/null
+++ b/testdata/tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread1.ts
@@ -0,0 +1,35 @@
+// @strict: true
+// @noEmit: true
+
+declare function call(
+ arg: (...args: NoInfer) => void,
+ ...args: A
+): A;
+
+const result1 = call((a: number) => {}, 1, 2);
+const result2 = call((a: number, b: number) => {}, 1); // error
+const result3 = call((a) => {}, 1, ''); // test contextual parameters
+const result4 = call((a, b) => {}, 1, ''); // test contextual parameters
+const result5 = call((...args) => {}, 1, ''); // test contextual parameters
+const result6 = call((a, ...rest) => {}, 1, ''); // test contextual parameters
+
+declare function fn1(
+ cb: (a: [number, ...NoInfer]) => void,
+ args: A,
+): A;
+
+declare const singleStr: [string];
+
+const result7 = fn1((arg) => {
+ arg.length;
+}, singleStr);
+
+declare const tupleUnion: [string] | [number, boolean];
+
+const result8 = fn1((arg) => {
+ arg.length;
+}, tupleUnion);
+
+declare function fn2(arg: (...args: NoInfer<[string, number]>) => void): void;
+
+fn2((a, ...rest) => {});
diff --git a/testdata/tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread2.ts b/testdata/tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread2.ts
new file mode 100644
index 00000000000..948777ec0cb
--- /dev/null
+++ b/testdata/tests/cases/conformance/types/typeRelationships/typeInference/noInferRestSpread2.ts
@@ -0,0 +1,34 @@
+// @strict: true
+// @noEmit: true
+
+// https://github.com/microsoft/TypeScript/issues/63627
+
+function arr1(a: [number, ...NoInfer<[]>]) {}
+arr1([1]);
+
+function arr2(a: [number, ...[]]) {}
+arr2([1]);
+
+function fun1(a: (x: number, ...o: NoInfer<[]>) => void) {}
+fun1(x => {});
+
+function fun2(a: (x: number, ...o: []) => void) {}
+fun2(x => {});
+
+function func1(
+ args: A,
+ fn: (x: number, ...args: NoInfer) => void,
+) {}
+
+func1([] as const, x => {});
+
+function func2(
+ args: A,
+ fn: (...args: NoInfer) => void,
+) {}
+
+function foo(u: number, v: number) {
+ func2([u, v] as const, () => {});
+ func2([u, v] as const, (x: number) => {});
+ func2([u, v] as const, (x: number, y: number) => {});
+}