Skip to content

Typescript not understand Promise than catch logic #25022

Closed
@vforv

Description

@vforv
    "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.

Activity

DanielRosenwasser

DanielRosenwasser commented on Jun 17, 2018

@DanielRosenwasser
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

vforv

vforv commented on Jun 17, 2018

@vforv
Author

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

kitsonk

kitsonk commented on Jun 17, 2018

@kitsonk
Contributor

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

kitsonk commented on Jun 17, 2018

@kitsonk
Contributor

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

vforv commented on Jun 18, 2018

@vforv
Author

Yes, in this part

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

data should be just string but not string | undefined

typescript-bot

typescript-bot commented on Jul 2, 2018

@typescript-bot
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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @DanielRosenwasser@kitsonk@vforv@typescript-bot

        Issue actions

          Typescript not understand Promise than catch logic · Issue #25022 · microsoft/TypeScript