Skip to content

Pick<T, Exclude<keyof T, K>> & Pick<T, Extract<keyof T, K>> should be assignable to T #28884

Open
@djrodgerspryor

Description

@djrodgerspryor

TypeScript Version: 3.2.1

Search Terms:
3.2.1
extends
intersection generic

Code

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

type Func<T> = (arg: T) => null

type Context = 'Context';

export function withRouteContextPropConsumer<
    T extends { routeContext: Context }
>(
    funcToWrap: Func<T>,
): Func<Omit<T, "routeContext">> {
    return (args: Omit<T, "routeContext">) => {
        const routeContext: Context = 'Context';
        return funcToWrap({ ...args, routeContext });
    };
}

Expected behavior:
Code compiles without errors

Actual behavior:

Argument of type '{ routeContext: "Context"; }' is not assignable to parameter of type 'T'.

Playground Link: http://www.typescriptlang.org/play/#src=type%20Omit%3CT%2C%20K%20extends%20keyof%20T%3E%20%3D%20Pick%3CT%2C%20Exclude%3Ckeyof%20T%2C%20K%3E%3E%3B%0A%0Atype%20Func%3CT%3E%20%3D%20(arg%3A%20T)%20%3D%3E%20null%0A%0Atype%20Context%20%3D%20'Context'%3B%0A%0Aexport%20function%20withRouteContextPropConsumer%3C%0A%20%20%20%20T%20extends%20%7B%20routeContext%3A%20Context%20%7D%0A%3E(%0A%20%20%20%20funcToWrap%3A%20Func%3CT%3E%2C%0A)%3A%20Func%3COmit%3CT%2C%20%22routeContext%22%3E%3E%20%7B%0A%20%20%20%20return%20(args%3A%20Omit%3CT%2C%20%22routeContext%22%3E)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20const%20routeContext%3A%20Context%20%3D%20'Context'%3B%0A%20%20%20%20%20%20%20%20return%20funcToWrap(%7B%20...args%2C%20routeContext%20%7D)%3B%0A%20%20%20%20%7D%3B%0A%7D
Related Issues: Nothing obvious

After upgrading from 3.0.3 to 3.2.1, it seems that tsc has (at least partially) lost the ability to reason about constrained generics.

In the example above (one of our React context helper functions, modified to remove the React dependency), the function is parameterised over a constrained generic:

T extends { routeContext: Context }

But a few lines later, the compiler complains that the generic T may not have a routeContext attribute. T must have a routeContext attribute however, because of the constraint. Perhaps the Omit helper is confusing things?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions