Skip to content
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

Conditionnal return type not recognized inside the function #59618

Closed
Tristan-WorkGH opened this issue Aug 13, 2024 · 4 comments
Closed

Conditionnal return type not recognized inside the function #59618

Tristan-WorkGH opened this issue Aug 13, 2024 · 4 comments
Labels
Duplicate An existing issue was already created

Comments

@Tristan-WorkGH
Copy link

πŸ”Ž Search Terms

"not assignable",
"parametized argument",
"conditional return"

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about 5.1.6

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.1.6#code/JYOwLgpgTgZghgYwgAgJIBMLmDYcBGANigN7LDoBcyAzmFKAOYDcyIcAthAPzV0MgWyAL4BYAFASYAVxAIwwAPYhkHAJ4y5AHgAqGMMggAPSCHQ00mbLgLFkAHzbTChAHwAKUDEU1qe9GAAlH76hiZY5pZYCjZEKNy09EzI1CDOhMgkEsg55DDIniDeFgC8JU4ugZnZubVQEGDSUCppLsw1tTkA9F0AolBQfmoADigA5K2EY+QWIIoGcDQ0wIzscchgihsj4-4GxqaRGNE4eOsJ-Mmp6WMAdO4ATADMDw+BHSKGhDSkH3UNTRUXh8two7XEnVyPX6g2QOh2yDGl0E02As3myEWy1WthQm22o0RezChwsx2sZzsFySghSFSm92er3eENyYnE7IkxAMYA4w2Q5XUmgQ7kmgXBPRKrmQ3I2fOuLi5DTlwweAtUGlkIpI7C41DGYwANOQqIixsJxRJJdLZbzVXwaYwJEA

πŸ’» Code

interface Identifiable { id: string; name?: string; }

function myfunc<TIdt extends Identifiable | null>(infos: TIdt): TIdt extends Identifiable ? string : null {
    if (infos == null) {
        return null;
        //Err: Type 'null' is not assignable to type 'TIdt extends Identifiable ? string : null'.(2322)
    } else {
        return infos.id;
        //Err: Type 'string' is not assignable to type 'TIdt extends Identifiable ? string : null'.(2322)
    }
}

let tmp = myfunc(null);
//=> let tmp: null
let tmp2 = myfunc({name: '', id: ''});
//=> let tmp2: string

πŸ™ Actual behavior

tsc doesn't seem to match the if statement with the conditional return.

On the other hand it understand what I want to say when calling the method.

πŸ™‚ Expected behavior

What I expect is for typescript to understand in the if that if the argument is null then I can only return null, and alse only return a string, like defined in the function signature.

Additional information about the issue

I have the impression that the signature is correct as typescript infer correctly when calling the function, so the problem is inside the function with the if?

@MartinJohns
Copy link
Contributor

Duplicate of #33912.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Aug 13, 2024
@muradkhan995
Copy link

Solution

You can resolve this by using type assertions or by separating the logic into distinct functions. Here's a solution using type assertions:

typescript

interface Identifiable { id: string; name?: string; }

function myfunc<TIdt extends Identifiable | null>(infos: TIdt): TIdt extends Identifiable ? string : null {
    if (infos == null) {
        return null as any;
    } else {
        return infos.id as any;
    }
}

In the code above:

return null as any; tells TypeScript to treat null as the correct return type (TIdt extends Identifiable ? string : null).
return infos.id as any; similarly tells TypeScript to treat infos.id as the correct return type.

Explanation

as any works as a workaround to convince TypeScript to accept the return value. However, this can be less safe, as it bypasses some of TypeScript's type checks.

Alternatively, you can split the logic into two functions, which can be more type-safe:

typescript

function myfuncIdentifiable(infos: Identifiable): string {
    return infos.id;
}

function myfunc<TIdt extends Identifiable | null>(infos: TIdt): TIdt extends Identifiable ? string : null {
    if (infos == null) {
        return null as any;
    } else {
        return myfuncIdentifiable(infos as Identifiable) as any;
    }
}

This way, the type logic is handled separately, and TypeScript is less likely to encounter problems with narrowing.
Summary

The root cause of this issue is TypeScript's inability to correctly narrow the conditional type within the function body.
The workaround involves using type assertions to force TypeScript to accept the return type.
Alternatively, splitting the function can make the type logic clearer and safer.

@MartinJohns
Copy link
Contributor

Looks like a garbage ChatGPT response.

@Tristan-WorkGH
Copy link
Author

Effectively a duplicate of #33912, will watch this one.

Will use function overloading in the meantime.

@Tristan-WorkGH Tristan-WorkGH closed this as not planned Won't fix, can't repro, duplicate, stale Aug 14, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants