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

Type guard fails for a part of an object #31755

Closed
tomfun opened this issue Jun 4, 2019 · 2 comments
Closed

Type guard fails for a part of an object #31755

tomfun opened this issue Jun 4, 2019 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@tomfun
Copy link

tomfun commented Jun 4, 2019

TypeScript Version: 3.4.5

Search Terms: type guard object destructuring, type guard object key

Code

export type GROUP_TYPE = 'group_1' | 'group_2';

export function isGroup(g: any): g is GROUP_TYPE {
    const allowedGroups: GROUP_TYPE[] = ['group_1', 'group_2'];
    return allowedGroups.indexOf(g) !== -1;
}

function getPermissions(query: { group: GROUP_TYPE }) {/* do something */ }

function goodFunction(query: { group: string }) {
    if (!isGroup(query.group))
        return;

    const { group } = query;

    return getPermissions({ ...query, group });
}

function sameFunction(query: { group: string }) {
    if (!isGroup(query.group))
        return;

    return getPermissions(query); // Error here
    //   _________________^^^^^
/*
Argument of type '{ group: string; }' is not assignable to parameter of type '{ group: GROUP_TYPE; }'.
 ...
*/
}

Expected behavior:
Both functions (goodFunction, sameFunction) should be valid typescript code

Actual behavior:
We see TS error

Argument of type '{ group: string; }' is not assignable to parameter of type '{ group: GROUP_TYPE; }'.
  Types of property 'group' are incompatible.
    Type 'string' is not assignable to type 'GROUP_TYPE'.

it thinks that query.group is steel a string when passing as arguments, but knows it is a GROUP_TYPE when gets it from object.

Playground Link:
link to playground

@jack-williams
Copy link
Collaborator

Type guards do not propagate type narrowings to parent objects. The narrowing is only applied upon access of the narrowed property which is why the destructing function works, but the reference function does not. Narrowing the parent would involve synthesizing new types which would be expensive. More detail in this comment.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jun 4, 2019
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

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