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

Property type is not narrowed for readonly object in some contexts #19469

Closed
OliverJAsh opened this issue Oct 25, 2017 · 8 comments
Closed

Property type is not narrowed for readonly object in some contexts #19469

OliverJAsh opened this issue Oct 25, 2017 · 8 comments
Labels
Needs More Info The issue still hasn't been fully clarified

Comments

@OliverJAsh
Copy link
Contributor

TypeScript Version: 2.4.1 and 2.6.0-rc

Code

{
    type User = { name: string };
    const logUser = (_user: User) => {};

    type State = {
        user: User | undefined;
    };

    const fn = function<Own extends {}>(p: Readonly<Own & State>) {
        const { user } = p;
        if (user !== undefined) {
            // Unexpected error: Type 'undefined' is not assignable to type 'User'
            // `user` should be narrowed to exclude `undefined` here.
            logUser(user);
        }
    };
}

//
// KNOWN WORKAROUNDS
//

{
    type User = { name: string };
    const logUser = (_user: User) => {};

    type State = {
        user: User | undefined;
    };

    const fn = function<Own extends {}>(p: Own & State) {
        const { user } = p;
        if (user !== undefined) {
            // No error when `Readonly` is dropped
            logUser(user);
        }
    };
}

{
    type User = { name: string };
    const logUser = (_user: User) => {};

    type State = {
        user: User | undefined;
    };

    const fn = function<Own extends {}>(p: Readonly<Own & State>) {
        const user: User | undefined = p.user;
        if (user !== undefined) {
            // No error when `user` is manually annotated
            logUser(user);
        }
    };
}

{
    type User = { name: string };
    const logUser = (_user: User) => {};

    type State = {
        user: User | undefined;
    };

    type Own = {};
    type P = Readonly<Own & State>
    const p = {} as any as P;

    const { user } = p;
    if (user !== undefined) {
        // No error if origin of `p` value and `Own` type is not from function
        logUser(user);
    }
}

Expected behavior:
(See comments in code.)

@mhegazy
Copy link
Contributor

mhegazy commented Oct 25, 2017

Seems to not produce errors in latest. can you give [email protected] a try.

@mhegazy mhegazy added the Needs More Info The issue still hasn't been fully clarified label Oct 25, 2017
@OliverJAsh
Copy link
Contributor Author

@mhegazy Yup, it is fixed for 2.6.1-insiders.20171019.

@OliverJAsh
Copy link
Contributor Author

I am still reproduce this on 2.6.1. Is it supposed to be fixed on that version?

@mhegazy
Copy link
Contributor

mhegazy commented Nov 2, 2017

I am not seeing any errors on [email protected]. can you share an updated repro?

@OliverJAsh
Copy link
Contributor Author

@mhegazy

declare class Maybe<A> {
    static of<A>(value: A | undefined): Maybe<A>;
    map<B>(f: (a: A) => B): Maybe<B>;
}

{
    type User = { name: string };
    const logUser = (_user: User) => {};

    type State = {
        user: User | undefined;
    };

    const fn = function<Own extends {}>(p: Readonly<Own & State>) {
        const { user } = p;

        Maybe.of(user).map(
            user =>
                // Unexpected error: Object is possibly 'undefined'.
                user.name,
        );
    };
}

@mhegazy
Copy link
Contributor

mhegazy commented Nov 6, 2017

in this example user is a generic variable. it's type is (Own & { user: User | undefined; })["user"]. this will not be narrowed with the use of Maybe.of which relies on inference picking the | undefined form the type. I think what you are looking for here is #14366

@OliverJAsh
Copy link
Contributor Author

I think what you are looking for here is #14366

Would this fix the above example so the correct types would be inferred, or would I still have to workaround this by annotating user?

@mhegazy
Copy link
Contributor

mhegazy commented Nov 29, 2017

depending on how it is implemented. but yes it would.

@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

No branches or pull requests

2 participants