-
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 Autocompletion Not Working For Function Overloads #26892
Comments
I'm also having an issue with autocomplete on overloaded code: public select<P extends NonReferenceNonFunctionPropNames<T>>(f: P): string;
public select<P extends NonReferenceNonFunctionPropNames<T>>(f: FunctionField<T>): string;
public select<P extends NonReferenceNonFunctionPropNames<T>>(f: P[]): string[];
public select<P extends NonReferenceNonFunctionPropNames<T>>(f: P | P[] | FunctionField<T>): string | string[] {
let relations = this._traversed.map(r => r.apiName);
if (Array.isArray(f)) {
let fieldArr: string[];
fieldArr = f.map(field => {
return this._obj.FIELDS[field as string].apiName
});
return fieldArr.map(field => {
return [...relations, ...[field]].join('.');
});
} else if (typeof f === 'object') {
let apiName = this._obj.FIELDS[f.field as string].apiName
return renderComplexTypeText([...relations, ...[apiName]].join('.'), f.func, f.alias)
} else {
return [...relations, ...[this._obj.FIELDS[f as string].apiName]].join('.');
}
} The auto-compete does work on the instances with |
What is the expected behavior? |
The signature help is wrong either if the first argument is |
I recently encountered the same problem where I wanted the compiler to restrict arguments based on previous arguments for an overloaded function type. Also, I came up with a solution that works quite well, in my opinion. First of all, your types need a little fix: // intersection types do not make much sense, you actually want union types
type Country = Germany | Austria;
type State = GermanState | AustrianState; With this fix in mind, you can change the function signature in such a manner that you will basically be able to have partial application of your function: // I removed the class "wrapper" to keep the example small - this should work for methods, as well.
function b(input: Germany): (second: GermanState) => string;
function b(input: Austria): (second: AustrianState) => string;
function b(input: Country): (second: State) => string {
return second => "test";
} Now, you are forced to apply the function b twice. For the second application, VSCode will suggest more fitting values because the inference of the compiler is "locked" into the return type of the first application: In this playground you will find both approaches. Just try the autocompletion for the calls of both |
any updates on this? I have a function with 100+ overloads. needs this feature very much! |
Good luck.... |
@Kingwl |
Is there any update on this? |
@RyanCavanaugh I'd like to help with this, as fixing it would enable a library API design that isn't really viable right now, while autocomplete is suggesting invalid candidates. However, I've never contributed to the language server before and don't know how it's set up. Do you have any sense of how hard this would be? And, if not too bad, any pointers on how to get started? |
Here is another simple example of this behaviour: type UserTypes = {
userType: "admin" | "user" | "unauthorized";
}
type SessionData = {
sessionId: string;
userData?: {
username: string;
}
}
type AuthedSessionData = Required<SessionData>;
function getUserData(userType: {userType: "unauthorized"}) : SessionData
function getUserData(userType: {userType: "admin" | "user" }) : AuthedSessionData
function getUserData(userType: {userType: "unauthorized"} | {userType: "admin" | "user"}) : SessionData | AuthedSessionData {
if(userType.userType === "unauthorized"){
return {
sessionId: "123"
}
}
return {
sessionId: "123",
userData: {
username: "foo"
}
}
}
const result1 = getUserData({"userType": "unauthorized"})
const result2 = getUserData({"userType": "admin"}); // <-- Valid, but no autocomplete We can get the autocomplete behaviour back by converting to a generic: type UserTypes<T extends "admin" | "user" | "unauthorized"> = {
userType: T ;
}
type SessionData = {
sessionId: string;
userData?: {
username: string;
}
}
type AuthedSessionData = Required<SessionData>;
function getUserData<T extends "admin" | "user" | "unauthorized"> (userType: UserTypes<T>) : T extends "unauthorized" ? SessionData : AuthedSessionData {
if(userType.userType === "unauthorized"){
return {
sessionId: "123"
} as T extends "unauthorized" ? SessionData : AuthedSessionData
}
return {
sessionId: "123",
userData: {
username: "foo"
}
}
}
const result1 = getUserData({"userType": "unauthorized"})
const result2 = getUserData({"userType": "admin"}); But as a rule of thumb, I prefer to use function overloads over generics - tends to be simpler. |
From @MartinLoeper on August 29, 2018 13:27
Steps to Reproduce:
I provided a small example of the issue (see screenshot below).
However, the auto-completion suggest the literals for both overloads.
I expect the auto-completion to show "BW" and "BY" only!
Does this issue occur when all extensions are disabled?: Yes
The code:
Copied from original issue: microsoft/vscode#57509
The text was updated successfully, but these errors were encountered: