Account for type parameters in missing function codefix (#49727)

* Account for type parameters in missing function codefix

* Apply suggestions from code review

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>

* WIP

* Synthesize new type parameters instead of deep unions and intersections

* Pass along type parameter constraints

* E.T. phone home

* Clean up comments just a bit

* Only widen the instance type sometimes

Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
This commit is contained in:
Josh Goldberg
2022-07-26 18:22:19 -04:00
committed by GitHub
parent 78e2bfd712
commit ebd42abf95
15 changed files with 444 additions and 10 deletions

View File

@@ -63,7 +63,7 @@ verify.codeFix({
// 8 type args
this.foo3<1,2,3,4,5,6,7,8>();
}
foo3<T0, T1, T2, T3, T4, T5, T6, T7>() {
foo3<T, U, V, W, X, Y, Z, T7>() {
throw new Error("Method not implemented.");
}
foo2<T, U, V, W, X, Y, Z>() {

View File

@@ -0,0 +1,22 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T>(value: T) {
//// const keyofTypeof = Object.keys(value)[0] as keyof T;
//// added/*1*/(keyofTypeof);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T>(value: T) {
const keyofTypeof = Object.keys(value)[0] as keyof T;
added(keyofTypeof);
}
function added(keyofTypeof: string | number | symbol) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T>(value: T) {
//// added/*1*/(value);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T>(value: T) {
added(value);
}
function added<T>(value: T) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T>(value: T) {
//// added/*1*/<T, string>(value, "");
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T>(value: T) {
added<T, string>(value, "");
}
function added<T, U>(value: T, arg1: string) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T>(value: T) {
//// added/*1*/<T>(value, value);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T>(value: T) {
added<T>(value, value);
}
function added<T>(value: T, value1: T) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T extends string>(value: T) {
//// added/*1*/(value);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T extends string>(value: T) {
added(value);
}
function added<T extends string>(value: T) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,24 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T>(value: T) {
//// if (typeof value === "number") {
//// added/*1*/(value);
//// }
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T>(value: T) {
if (typeof value === "number") {
added(value);
}
}
function added<T>(value: T) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,43 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function e<T extends "phone" | "home">() {
//// let et: T = 'phone'
//// added1/*1*/(et)
//// et = 'home'
//// added2/*2*/(et)
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added1'",
index: 0,
newFileContent: `function e<T extends "phone" | "home">() {
let et: T = 'phone'
added1(et)
et = 'home'
added2(et)
}
function added1(et: string) {
throw new Error("Function not implemented.")
}
`,
});
goTo.marker("2");
verify.codeFix({
description: "Add missing function declaration 'added1'",
index: 0,
newFileContent: `function e<T extends "phone" | "home">() {
let et: T = 'phone'
added1(et)
et = 'home'
added2(et)
}
function added1(et: string) {
throw new Error("Function not implemented.")
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T1, T, T2>(t1: T1, t: T, t2a: T2, t2b: T2, t2c: T2) {
//// added/*1*/(t2a, t2b, t2c, t1, t, t2a, t2c, t2b);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T1, T, T2>(t1: T1, t: T, t2a: T2, t2b: T2, t2c: T2) {
added(t2a, t2b, t2c, t1, t, t2a, t2c, t2b);
}
function added<T2, T1, T>(t2a: T2, t2b: T2, t2c: T2, t1: T1, t: T, t2a1: T2, t2c1: T2, t2b1: T2) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T extends string, U extends T>(value: T, other: U) {
//// added/*1*/(value, other);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T extends string, U extends T>(value: T, other: U) {
added(value, other);
}
function added<T extends string, U extends T>(value: T, other: U) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,24 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function outer<O>(o: O) {
//// return function inner<I>(i: I) {
//// added/*1*/(o, i);
//// }
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function outer<O>(o: O) {
return function inner<I>(i: I) {
added(o, i);
}
}
function added<O, I>(o: O, i: I) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,28 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function outer<O>(o: O) {
//// return function middle<M>(m: M) {
//// return function inner<I>(i: I) {
//// added/*1*/(o, m, i);
//// }
//// }
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function outer<O>(o: O) {
return function middle<M>(m: M) {
return function inner<I>(i: I) {
added(o, m, i);
}
}
}
function added<O, M, I>(o: O, m: M, i: I) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T, U>(value: T | U & string) {
//// added/*1*/(value);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T, U>(value: T | U & string) {
added(value);
}
function added<T>(value: T) {
throw new Error("Function not implemented.");
}
`,
});

View File

@@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
// @noImplicitAny: true
////function existing<T, U>(value1: T | U & string, value2: U & T, value3: U | T, value4: U) {
//// added/*1*/(value1, value2, value3, value4);
////}
goTo.marker("1");
verify.codeFix({
description: "Add missing function declaration 'added'",
index: 0,
newFileContent: `function existing<T, U>(value1: T | U & string, value2: U & T, value3: U | T, value4: U) {
added(value1, value2, value3, value4);
}
function added<T, U, V>(value1: T, value2: U, value3: V, value4: U) {
throw new Error("Function not implemented.");
}
`,
});