-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Can't infer return type of generic function #55435
Comments
TS doesn't have true call types of the sort you'd need for this to work. Looks like a duplicate of #52035 (or at least this comment) and refers back to #6606. |
I think this is something that has to be looked into because it has great potential and it almost works. type FilterObject<T, P extends (v: any, k: any, t: any) => boolean> = { [k in keyof T as P extends (v: T[k], k: k, t: T) => true ? k : never]: T[k] };
type Test = { ab: 1, ac: 2, cb: 3, ad: 1, g: "g" };
type a = FilterObject<Test, (v: 1) => true>;
// ^? type a = { ab: 1, ad: 1 }
type b = FilterObject<Test, <K>(_: any, k: K) => K extends `a${string}` ? false : true>;
// ^? type b = { cb: 3, g: "g" }
type c = FilterObject<Test, <V, K>(v: V, k: K) => K extends V ? true : false>;
// ^? type c = { g: "g" } It understands what the return type is, so why can't it infer it |
It seems like you want specifically #40179 |
Yeah #40179 was the one I was searching for but "call types" wasn't mentioned there |
I'm also blocked from making one of my more complicated types generic because of this. The type WrapConfig = { wrap?: boolean };
type ReturnValue<TWrapConfig extends WrapConfig | void, T> =
TWrapConfig extends object
? TWrapConfig['wrap'] extends true ? T[]
: T
: T;
function doThing<TWrapConfig extends WrapConfig | void = void>(
config?: TWrapConfig
): ReturnValue<TWrapConfig, string> {
return (config?.wrap ? ['hi'] : 'hi') as ReturnValue<TWrapConfig, string>;
}
// Test that the function return type is parametric on the shape of the arguments
doThing({ wrap: true }) satisfies string[];
doThing({ wrap: false }) satisfies string;
doThing({}) satisfies string;
doThing() satisfies string;
// Test that the function, without type parameter, spans the union of return types
doThing satisfies ((...args: any[]) => string[] | string);
// Try to infer the return type without supplying the type parameter
type DoThingReturn = typeof doThing extends (...args: any[]) => infer R ? R : unknown;
(null as unknown as DoThingReturn) satisfies string[] | string; // ERROR Output"use strict";
function doThing(config) {
return ((config === null || config === void 0 ? void 0 : config.wrap) ? ['hi'] : 'hi');
}
// Test that the function return type is parametric on the shape of the arguments
doThing({ wrap: true });
doThing({ wrap: false });
doThing({});
doThing();
// Test that the function, without type parameter, spans the union of return types
doThing;
null; // ERROR Compiler Options{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictFunctionTypes": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"noImplicitThis": true,
"noImplicitReturns": true,
"alwaysStrict": true,
"esModuleInterop": true,
"declaration": true,
"target": "ES2017",
"jsx": "react",
"module": "ESNext",
"moduleResolution": "node"
}
} Playground Link: Provided |
# Summary This _so_ close to works. You can see the types in action here: ``` const address = 'abc' as Base58EncodedAddress; /** No encoding */ const noEncodingWithContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { withContext: true, }); const noEncodingFalseContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { withContext: false, }); const noEncodingNoContextConfig = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address); /** Base58 */ const base58EncodingWithContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base58', withContext: true, }); const base58EncodingFalseContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base58', withContext: false, }); const base58EncodingNoContextConfig = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base58', }); /** Base64 */ const base64EncodingWithContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base64', withContext: true, }); const base64EncodingFalseContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base64', withContext: false, }); const base64EncodingNoContextConfig = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base64', }); /** Base64-zstd */ const base64ZStdEncodingWithContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base64+zstd', withContext: true, }); const base64ZStdEncodingFalseContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base64+zstd', withContext: false, }); const base64ZStdEncodingNoContextConfig = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'base64+zstd', }); /** JSON parsed */ const jsonParsedEncodingWithContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'jsonParsed', withContext: true, }); const jsonParsedEncodingFalseContext = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'jsonParsed', withContext: false, }); const jsonParsedEncodingNoContextConfig = (null as unknown as GetProgramAccountsApi).getProgramAccounts(address, { encoding: 'jsonParsed', }); ``` There's _one_ TypeScript bug, though, that makes `rpc.getProgramAccounts()` ultimately lose all of its type information. It's because of this: microsoft/TypeScript#55435 (comment)
This issue has been marked as "Duplicate" and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
🔎 Search Terms
infer generic function return type
🕗 Version & Regression Information
3.5.1
the syntax wasn't supported4.8.4
there was an additional bug for which the type ofa
(In the example) was[ true, true ]
5.2.0-beta
doesn't fix the issue⏯ Playground Link
https://www.typescriptlang.org/play?ts=5.1.6#code/FAehAIHUHsCcGsDO5C8G4WR3gG9jl+ALgJ4AOApuAMIAWpAxvADwAqANOAArikAe+pAdgBNkACm4AucAEN+hAJTgAvAD5wAI2jQANqRmrFHLrwHDwYyUwUqCsAK7kA-DfvhJAMylbEpANzAceGBQcEjgAO4AlvhU4LTQALbEOtxGxLCkiIgR0PyIAbhEZOAAkogActD4AIzM+pQ09MxsDACqyubgLVaqLUZ8QshV4E4eXuSS+Hakyn54BCTkUkrgANol5ZU1AEzKbKUV1QxVqgC6s4EQuAB6Dv5zQTAIyOn4trD8EfwA5gQ04J-EWz4fLzIqlJhTWrLah0RiscC1DqWJSqJgzEGFchqZZrcGQyb2XbrCH2Bijbync64ILXW4AX38QQAItAMvwAOT4cIhMwAIVsP2IUlg+DkWBBzNZiA5XPg-GgYX++GQAKBGIWlE8WgYADE+iZkDrbPxaPhsvw2ABBWBfZA8fqmdJSQQ5LSEcDGuUK-grE51PX2g1mAB0oeFtsk1tt3X+-DcpFgnWGSck-FIADcE1TQeRaNCtQxERJwMjrPC1kM-RLLuAbncLuADlxM-xwDlpG20wBaIWwKTxUh8RNZRJaCJuCKkQTgTOwLI5dVFChamoB4wDcBGk1mnJsNHLNcO0TF0uqT7xxO9Jy9VMZrOL8jTgzLrRaGpFiwx+HHat4Ou-lk2U5bkEHCKIYjiUceFSdJMnNPI5kxLh81fd80SRGM1nhLZwBONgf3uGt-0I4InnCGhW2iBNFnSGVwC+AQEwiWgELwJDShqfdnwLDoqhjAlSDYLDcPRRCNTcHF1hqASiQ4o5KV-WlgDpIA
💻 Code
🙁 Actual behavior
Types
c
,d
ande[0]
areunknown
🙂 Expected behavior
Types
c
,d
ande[0]
should have all been1
.I tried to infer the return type of some generics functions when they got supplied with certain types, I can check wether the return type is something else (
true
insideCheck
in this example) but I cannot actually get itAdditional information about the issue
No response
The text was updated successfully, but these errors were encountered: