Skip to content

Lose generic when spreading T | undefined where T is a generic object type #58645

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
yfzhe opened this issue May 24, 2024 · 3 comments
Closed
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@yfzhe
Copy link

yfzhe commented May 24, 2024

πŸ”Ž Search Terms

spread, union

πŸ•— Version & Regression Information

There are 2 problems. The first was changed between versions 4.0.5 and 4.1.5, and the second exists in every version of TS I tried in the Playground.

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/GYVwdgxgLglg9mABMOcA8AVRBTAHlbMAEwGdE4AjAK22gD4AKKALkSwB9FwjtgYxsRAJSIA3gChEiAE7YoIaUlGIAdGqgAaZKlYAWAEyIAvgG5xR8eNCRYCRBQCG0zDnyFS5arSiMWbRJzcvPyCIhJSsvKKYqrqxmZGQA

πŸ’» Code

// spread and add a property
function foo<T extends object>(t: T | undefined) {
  return { ...t, foo: 42 };
}

// just spread
function bar<T extends object>(t: T | undefined) {
  return { ...t };
}

πŸ™ Actual behavior

  1. The result type of foo is { foo: number }.
  2. The result type of bar is {}.

πŸ™‚ Expected behavior

  1. The result type of foo is(T & { foo: number }) | { foo: number }.
  2. The result type of bar is T.

Additional information about the issue

I'm not sure if this is same with #58617. But as there are some previous versions of TS work as I expected, I tend to treat it as a different issue and a bug.

@ahejlsberg
Copy link
Member

I don't think there is a bug here. Spreading an undefined value creates no properties, so { ...t } produces {} when t is undefined. Thus, the result is T | {}, which reduces to just {} by subtype reduction.

@ahejlsberg ahejlsberg added the Working as Intended The behavior described is the intended behavior; this is not a bug label May 24, 2024
@yfzhe
Copy link
Author

yfzhe commented May 24, 2024

I'm confused a little on the situation of foo. I think it is also because of subtype reduction which the type of { ...t, foo: number } is { foo: number }. But as we see it was (T & { foo: number }) | { foo: number } in some old versions of TS, did there happen some "breaking changes" on subtype reduction?

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale May 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

3 participants