Skip to content
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

Object.assign does not conclude correct type from second argumet in ternary operator #39002

Closed
aghArdeshir opened this issue Jun 10, 2020 · 4 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@aghArdeshir
Copy link
Contributor

TypeScript Version: 4.0.0-dev

Search Terms: Object assign, spread

Code

// A *self-contained* demonstration of the problem follows...
// Test this by running `tsc` on the command-line, rather than through another build tool such as Gulp, Webpack, etc.
const production: boolean = true;

interface Icon {
    x: number;
    y: number;
    name: 'we' | 'you' | 'hello' | undefined;
}

const myBeautifulIcon: Icon = Object.assign(
    { x: 2, y: 2 },
    production ? { name: 'we' } : { name: 'you' }
)

console.log(myBeautifulIcon);

(code tested in nightly ts playground)

Expected behavior:
The code to be valid and myBeautifulIcon object have correct type. The correct type should be concluded from Object assign.

Actual behavior:
Error arised, saying that theconcluded type for name was string;

Playground Link:
https://www.typescriptlang.org/play/?ts=4.0.0-dev.20200609&ssl=1&ssc=1&pln=14&pc=30#code/MYewdgzgLgBADgJxAEwK7CgS3ALhgIxBABsBTAQzBgF4YoFVSBuAKBczClIQDNzhSMAJKgqAbxYwpMAB54wqALb5uraTACe8pSoRrpYcotJ4A5AHdSpmAB8YpjSFTW7pgBalixEC5iowyKQ8HKTIrAC+bKLQMIoaAEIUqFg8qMQiuMKiNDAA8vgAVqQYAHTkEBCYAOZgABSS0mKyeABMADSarTDhbQ1SiCjoWOAwAPwwTYbGZpbW4TB4k0Ym9o7O3SwAlFHgECSkJd5VtXGJ5MmYqemim0xAA

Related Issues:
#35621
#26792
#16163

More practical use case:
image

@j-oliveras
Copy link
Contributor

You can also use as const since version 3.4:

    production ? { name: 'we' } as const : { name: 'you' } as const
    // or
    production ? { name: 'we' as const } : { name: 'you' as const }

@RyanCavanaugh RyanCavanaugh added the Design Limitation Constraints of the existing architecture prevent this from being fixed label Jun 10, 2020
@RyanCavanaugh
Copy link
Member

Object.assign is "just a function" so the normal widening rules apply - basically TS's assumption is that Object.assign will leave the basic type alone, but might modify the primitive within its family (e.g. maybe Object.assign({ x: -5, y: "hello"}) is { x: 5, y:" HELLO" }). as const is the correct thing to write to indicate that you don't believe that will happen.

@aghArdeshir
Copy link
Contributor Author

Oo! That's a bummer.
Cause lots of times, typescript does things that "feels like" smart!
And that feeling in me made that expecttion that I wished typescript to conclude result type.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

3 participants