Skip to content

in typescript 2.8, a common definition of Omit causes declarations that don't compile to be generated #25041

Open

Description

TypeScript Version:
Reproduces with 3.0.0-dev.201xxxxx, 2.9.2, 2.8.4

Search terms
omit, declaration, pick, undefined

Example

export type Omit<T, K extends keyof T> = Pick<T, 
    ({ [P in keyof T]: P } & { [P in K]: never } )[keyof T]>;

export interface IOmitTest {
	(): { notSupposedToHappen: Omit<IXProps, "unwantedProp"> }
}

export interface IXProps {
    optionalProp?: string
    unwantedProp: string
}

const Y: IOmitTest = null as any;
export const Z = Y();

export interface IMouseOver {
    wrong: Omit<IXProps, "unwantedProp">
}

generates

export declare type Omit<T, K extends keyof T> = Pick<T, ({
    [P in keyof T]: P;
} & {
    [P in K]: never;
})[keyof T]>;
export interface IOmitTest {
    (): {
        notSupposedToHappen: Omit<IXProps, "unwantedProp">;
    };
}
export interface IXProps {
    optionalProp?: string;
    unwantedProp: string;
}
export declare const Z: {
    notSupposedToHappen: Pick<IXProps, "optionalProp" | undefined>;
};
export interface IMouseOver {
    wrong: Omit<IXProps, "unwantedProp">;
}

The interface returning a function seems to be required to get typescript to collapse the Omit to a Pick statement (otherwise you just get Omit<IXProps, "unwatedProp"> in the declaration file).

I think this is a bug in typescript because it's produced a declaration file with syntax errors in it.

Expected behavior:
undefined should not be present in the Pick statement

Playground Link:
the playground does not provide the ability to generate declartions

Related Issues:
#12215

note that if the definition of Omit is replaced with the newer declaration possible in typescript 2.9

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

then

export declare const Z: {
    notSupposedToHappen: Pick<IXProps, "optionalProp">;
};

results as expected.

I actually encountered this issue using when using connect() in react-redux with a component with an optional property, where the definition of Omit is:

type Omit<T, K extends keyof T> = Pick<T, ({ [P in keyof T]: P } & { [P in K]: never } & { [x: string]: never, [x: number]: never })[keyof T]>;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions