Skip to content

Partial and Readonly are not commutative when using generics #17682

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

Closed
sccolbert opened this issue Aug 8, 2017 · 1 comment
Closed

Partial and Readonly are not commutative when using generics #17682

sccolbert opened this issue Aug 8, 2017 · 1 comment
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@sccolbert
Copy link

TypeScript Version: 2.4.2

Code

type State = {
    [key: string]: string | boolean | number | null;
};


type Args1<T extends State> = {
    readonly previous: Readonly<Partial<T>>;
    readonly current: Readonly<Partial<T>>;
};


type Args2<T extends State> = {
    readonly previous: Partial<Readonly<T>>;
    readonly current: Partial<Readonly<T>>;
};


function doit<T extends State>() {
    let previous: Partial<T> = Object.create(null);
    let current: Partial<T> = Object.create(null);
    let args1: Args1<T> = { previous, current };  // not okay
    let args2: Args2<T> = { previous, current };  // okay
}


type State2 = { foo: number, bar: string };


type Args3 = {
    readonly previous: Readonly<Partial<State2>>;
    readonly current: Readonly<Partial<State2>>;
};


type Args4 = {
    readonly previous: Partial<Readonly<State2>>;
    readonly current: Partial<Readonly<State2>>;
};


function doit2() {
    let previous: Partial<State2> = Object.create(null);
    let current: Partial<State2> = Object.create(null);
    let args1: Args3 = { previous, current };  // okay
    let args2: Args4 = { previous, current };  // okay
}

Expected behavior:

All examples compile.

Actual behavior:

The generic args only compile if Partial and Readonly are applied in a specific order.

@mhegazy mhegazy added the Needs Investigation This issue needs a team member to investigate its status. label Aug 29, 2017
@mhegazy
Copy link
Contributor

mhegazy commented Oct 31, 2017

@ahejlsberg our current comparison logic makes it so that mapped types are not commutative. also the special handling we have for Partial<T> to be assignable from {} will not work if Partial is wrapped in any other mapped type. should be have some special handling for Readonly as well, and treat it like an identity mapper, i.e. U is assignable to Readonly<T> iff U is assignable to T.

@ahejlsberg ahejlsberg added Bug A bug in TypeScript and removed Needs Investigation This issue needs a team member to investigate its status. labels Nov 4, 2017
@ahejlsberg ahejlsberg added this to the TypeScript 2.7 milestone Nov 4, 2017
@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Nov 4, 2017
@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
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

No branches or pull requests

3 participants