Skip to content

Typescript not understand Promise than catch logic #25022

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

Closed
vforv opened this issue Jun 16, 2018 · 6 comments
Closed

Typescript not understand Promise than catch logic #25022

vforv opened this issue Jun 16, 2018 · 6 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@vforv
Copy link

vforv commented Jun 16, 2018

    "typescript": "^2.7.2",
    "typescript-eslint-parser": "^14.0.0",

If I have promise like this:

export default function to<T>(promise: Promise<T>) {
    return promise
        .then((data: T) => {
            return { error: undefined, data };
        })
        .catch((error: Error) => {
            return { error, data: undefined };
        });
}

And after that I add async await with this logic:

public someMethod() {
const { error, data } = await to<SomeType>(SOME PROMISE HERE);

if(error) {
  return;
}

// HERE I WILL NOT BE ABLE TO GET SomeType because Typescript still recognise data as type:
// undefined | SomeType
data.
}

Maybe this is some bug with IDE I don't know. I am usigin Visual Code.

@DanielRosenwasser
Copy link
Member

TypeScript doesn't have a way to correlate the types of error and data once you've destructured them into independent variables.

Otherwise, being able to discriminate on undefined or null on a property of an object is an open issue: #24479

@DanielRosenwasser DanielRosenwasser added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jun 17, 2018
@vforv
Copy link
Author

vforv commented Jun 17, 2018

That is bad because I need to hack data variable like this: (data as Website[]) to make it work

@kitsonk
Copy link
Contributor

kitsonk commented Jun 17, 2018

I think @DanielRosenwasser might have looked at it a bit too quickly... What you have written int TypeScript could easily be improved to accomplish your intent:

export interface ToReturn<T> {
    error: Error | undefined;
    data: T | undefined;
}

export default function to<T>(promise: Promise<T>): Promise<ToReturn<T>> {
    return promise
        .then((data: T) => {
            return { error: undefined, data };
        })
        .catch((error: Error) => {
            return { error, data: undefined };
        });
}

async function someMethod() {
    const { error, data } = await to(Promise.resolve('foo'));

    if(error) {
        return;
    }

    data; // typeof string
}

These sort of basic questions are best asked on StackOverflow or Gitter though.

@kitsonk
Copy link
Contributor

kitsonk commented Jun 17, 2018

Actually, @DanielRosenwasser is right, though I am not entirely sure you wanted/needed what Daniel was suggesting. While it is mildly inconvenient, you can still access the type. Your original code was still flawed though in representing the return of the function. Here is a slightly better example which expresses what Daniel was talking about when run under --strictNullChecks:

export type ToReturn<T> = {
    error: Error;
    data: undefined;
} | {
    error: undefined;
    data: T
};

export default function to<T>(promise: Promise<T>): Promise<ToReturn<T>> {
    return promise
        .then((data: T) => {
            return { error: undefined, data };
        })
        .catch((error: Error) => {
            return { error, data: undefined };
        });
}

async function someMethod() {
    const { error, data } = await to(Promise.resolve('foo'));

    if (error) {
        return;
    }
    
    data; // typeof string | undefined

    if (data) {
        data; // string
    }
}

@vforv
Copy link
Author

vforv commented Jun 18, 2018

Yes, in this part

if (error) {
        return;
}
    
data; // typeof string | undefined

data should be just string but not string | undefined

@typescript-bot
Copy link
Collaborator

Automatically closing this issue for housekeeping purposes. The issue labels indicate that it is unactionable at the moment or has already been addressed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

4 participants