-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
TypeScript v4.5 regression: cannot use Parameters type on narrowed methods / functions #46855
Comments
Also ran into this with |
Bisected to #41821 |
So, critically, this code never worked for the reasons it appears to work. This passes without error in 4.4: type Methods<T> = {
[K in keyof T]: T[K] extends string ? K : never;
// Changed Function to string ^
}[keyof T];
class Test {
foo = '';
bar(a: string, b: number): void {}
}
function doSomeProxying<T, Method extends Methods<T>, Args extends Parameters<T[Method]>>(
type: T,
method: Method,
...args: Args
): void {} Note that we're taking The type system does not actually recognize There are some things you can write that make this work as expected; they're hopefully at least someone self-explanatory so I'll post them all and you can pick based on what works best for you. Note that the type Methods<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
class Test {
foo = '';
bar(a: string, b: number): void {}
}
type LooseParameters<T> = T extends (...args: infer A) => unknown ? A : never;
function doSomeProxying<T, K extends Methods<T>>(
type: T,
method: K,
...args: LooseParameters<T[K]>
): void {} class Test {
foo = '';
bar(a: string, b: number): void {}
}
function doSomeProxying<T extends Record<K, (...args: any[]) => unknown>, K extends PropertyKey>(
type: T,
method: K,
...args: Parameters<T[K]>
): void {}
// @ts-expect-error
doSomeProxying(new Test(), 'foo');
// @ts-expect-error
doSomeProxying(new Test(), 'qua');
doSomeProxying(new Test(), 'bar', "hello", 42);
// @ts-expect-error
doSomeProxying(new Test(), 'bar', 42, 42); type Methods<T> = {
[K in keyof T]: T[K] extends Function ? K : never;
}[keyof T];
class Test {
foo = '';
bar(a: string, b: number): void {}
}
type Cast<T, U> = T extends U ? T : T & U;
function doSomeProxying<
T,
Method extends Methods<T>,
Args extends Parameters<Cast<T[Method], (...args: any[]) => void>>,
>(
type: T,
method: Method,
...args: Args
): void {}
// @ts-expect-error
doSomeProxying(new Test(), 'foo');
// @ts-expect-error
doSomeProxying(new Test(), 'qua');
doSomeProxying(new Test(), 'bar', "hello", 42);
// @ts-expect-error
doSomeProxying(new Test(), 'bar', 42, 42); Long-term there's still a sort of missing feature where you can refer to the keys of an object whose corresponding property types match some other type (which would come with associated assignability effects in generics etc), but in practice this is very rarely strictly needed, as shown by the alternatives above. |
Thanks for the rapid response and clear explanation! |
Bug Report
π Search Terms
function, method, generic, parameters, does not satisfy constraint, 4.5
π Version & Regression Information
β― Playground Link
Playground link with relevant code
βπΌ Switch the version to v4.4.4 and this compiles fine; v4.5.0-beta errors (as does v4.5.2, but the Playground doesn't offer this version)
π» Code
π Actual behavior
Compiler errors in v4.5.0, even though it was fine in v4.4.4.
π Expected behavior
Expect to be able to use the built-in
Parameters<>
type on properties I have narrowed down as functions.The text was updated successfully, but these errors were encountered: