Skip to content

Cannot type a function that copies a property in an object #31725

Closed
@arielshaqed

Description

@arielshaqed

TypeScript Version: Version 3.6.0-dev.20190602

Search Terms: "generic return type" (returns too many results, sorry)

Code

function copy<K extends string, J extends string, T extends Record<K, number>>(
    o: T, s: K, t: J
): T & Record<J, number> {
    return { ...o, [t]: o[s] };
}

const { b } = copy({ a: 2 }, 'a', 'b');

Expected behavior:

Code compiles with 3.4.x. It is unsound when explicitly specifying type params, but with implicit type params it lets me express the type of copy.

Actual behavior:

With 3.5.1 compilation fails:

../../../../../../tmp/x.ts:4:5 - error TS2322: Type 'T & { [x: string]: T[K]; }' is not assignable to type 'T & Record<J, number>'.
  Type 'T & { [x: string]: T[K]; }' is not assignable to type 'Record<J, number>'.

4     return { ...o, [t]: o[s] };
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 1 error.

Here's the thing: the new compiler is correct, the claimed type is unsound. I can specialize the call to copy to make it unsound, e.g.

const { c }: Record<'c', number> = copy<'a', 'b' | 'c', Record<'a', number>>({ a: 2 }, 'a', 'b');

actually compiles with 3.4.5, and now c is undefined and 3.4.5 thinks it has type number. 3.5.1 prevents that (yay!).

I would like a way to type copy; I used to have an unsound type for it (but safe unless used with explicit type params), now I have no way to type it.

Playground Link: https://www.typescriptlang.org/play/#src=function%20copy%3CK%20extends%20string%2C%20J%20extends%20string%2C%20T%20extends%20Record%3CK%2C%20number%3E%3E(%0A%20%20%20%20o%3A%20T%2C%20s%3A%20K%2C%20t%3A%20J%0A)%3A%20T%20%26%20Record%3CJ%2C%20number%3E%20%7B%0A%20%20%20%20return%20%7B%20...o%2C%20%5Bt%5D%3A%20o%5Bs%5D%20%7D%3B%0A%7D%0A%0Aconst%20%7B%20c%20%7D%3A%20Record%3C'c'%2C%20number%3E%20%3D%20copy%3C'a'%2C%20'b'%20%7C%20'c'%2C%20Record%3C'a'%2C%20number%3E%3E(%7B%20a%3A%202%20%7D%2C%20'a'%2C%20'b')%3B%0A

Related Issues:
Even found a suspect PR!

Probably introduced in #30769, which I found via #31672.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs More InfoThe issue still hasn't been fully clarified

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions