Skip to content

Generic type union assignment via Pick throws TS2322 #28080

Open
@Niels-Be

Description

TypeScript Version: 3.1.3 and 3.2.0-dev.20181023
Works in Version 3.0.3

Search Terms: generic union assignment TS2322 setState

Code

interface A {
    a: string;
}

class Base<T> {
    prop: T;

    update<U extends keyof T>(props: Pick<T, U>) { /* like react setState */ }
}


class Test<T> extends Base<A & T> {
    test() {
        const str: string = "foo";
        this.prop.a = str; //ok
        this.update({
            a: str //err TS2322
        });
    }
}

// explicitly remove overloading properties
type SaveMerge<T, R> = T & Pick<R, Exclude<keyof R, keyof T>>;
class Test2<T> extends Base<SaveMerge<A, T>> {
    test() {
        const str: string = "foo";
        this.prop.a = str; //ok
        this.update({
            a: str //err TS2322
        });
    }
}

Expected behavior:
Compiles fine as in 3.0.3

Actual behavior:

test.ts:18:13 - error TS2322: Type 'string' is not assignable to type 'string & T["a"]'.
  Type 'string' is not assignable to type 'T["a"]'.

18             a: str //err
               ~

  test.ts:3:5
    3     a: string;
          ~
    The expected type comes from property 'a' which is declared here on type 'Pick<A & T, "a">'

test.ts:29:13 - error TS2322: Type 'string' is not assignable to type 'string & T["a"]'.
  Type 'string' is not assignable to type 'T["a"]'.

29             a: str //err
               ~

  test.ts:3:5
    3     a: string;
          ~
    The expected type comes from property 'a' which is declared here on type 'Pick<SaveMerge<A, T>, "a">'

Playground Link:
http://www.typescriptlang.org/play/#src=interface%20A%20%7B%0D%0A%20%20%20%20a%3A%20string%3B%0D%0A%7D%0D%0A%0D%0Aclass%20Base%3CT%3E%20%7B%0D%0A%20%20%20%20prop%3A%20T%3B%0D%0A%0D%0A%20%20%20%20update%3CU%20extends%20keyof%20T%3E(props%3A%20Pick%3CT%2C%20U%3E)%20%7B%20%7D%0D%0A%7D%0D%0A%0D%0A%0D%0Aclass%20Test%3CT%3E%20extends%20Base%3CA%20%26%20T%3E%20%7B%0D%0A%20%20%20%20test()%20%7B%0D%0A%20%20%20%20%20%20%20%20const%20str%3A%20string%20%3D%20%22foo%22%3B%0D%0A%20%20%20%20%20%20%20%20this.prop.a%20%3D%20str%3B%20%2F%2Fok%0D%0A%20%20%20%20%20%20%20%20this.update(%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20a%3A%20str%20%2F%2Ferr%20TS2322%0D%0A%20%20%20%20%20%20%20%20%7D)%3B%0D%0A%20%20%20%20%7D%0D%0A%7D%0D%0A%0D%0A%2F%2F%20explicitly%20remove%20overloading%20properties%0D%0Atype%20SaveMerge%3CT%2C%20R%3E%20%3D%20T%20%26%20Pick%3CR%2C%20Exclude%3Ckeyof%20R%2C%20keyof%20T%3E%3E%3B%0D%0Aclass%20Test2%3CT%3E%20extends%20Base%3CSaveMerge%3CA%2C%20T%3E%3E%20%7B%0D%0A%20%20%20%20test()%20%7B%0D%0A%20%20%20%20%20%20%20%20const%20str%3A%20string%20%3D%20%22foo%22%3B%0D%0A%20%20%20%20%20%20%20%20this.prop.a%20%3D%20str%3B%20%2F%2Fok%0D%0A%20%20%20%20%20%20%20%20this.update(%7B%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20a%3A%20str%20%2F%2Ferr%20TS2322%0D%0A%20%20%20%20%20%20%20%20%7D)%3B%0D%0A%20%20%20%20%7D%0D%0A%7D

Related Issues:
Maybe #26274

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: Conditional TypesThe issue relates to conditional types

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions