Skip to content

Add UnionMember type#1368

Merged
sindresorhus merged 19 commits intosindresorhus:mainfrom
taiyakihitotsu:add/last-of-union-20260204
Mar 18, 2026
Merged

Add UnionMember type#1368
sindresorhus merged 19 commits intosindresorhus:mainfrom
taiyakihitotsu:add/last-of-union-20260204

Conversation

@taiyakihitotsu
Copy link
Contributor

@taiyakihitotsu taiyakihitotsu commented Feb 14, 2026

Add UnionMember

  • This is useful to recurse union-types, so I think this should be exported as a global for end-users.
  • We can evade a duplicated definition potentially.

And the current UnionMember, which locally defined in UnionToTuple, returns unknown.

expectType<never>({} as UnionMember<never>);
//=> unknown

This would cause an error if end-users use IsNever for termination check.

Ideally, UnionMember reduces a type, e.g., assuming $A$ and $B$ are type arguments of UnionMember<A | B>, $A \cup B$ -> $B$, so $\emptyset$ -> $\emptyset$ intuitively ($\bot$ -> $\bot$).
This PR's UnionMember handles this.


Note

taiyakihitotsu and others added 3 commits February 15, 2026 09:26
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
@taiyakihitotsu
Copy link
Contributor Author

@sindresorhus

Thanks for your reviews!

And I believe this suggestion implies that test-d/last-of-union.ts should have a test for recursion without directly importing UnionToTuple to clarify it. Right?

If so, UnionToTuple in test-d/last-of-union.ts fulfills the requirement. Would it be okay to integrate both in test-d/last-of-union.ts?


#1368 (comment)

type UnionToTupleWithExclude<T, L = LastOfUnion<T>> =
	IsNever<T> extends false
		? [...UnionToTupleWithExclude<Exclude<T, L>>, L]
		: [];

expectType<1 | 2 | 3>({} as UnionToTupleWithExclude<1 | 2 | 3>[number]);

@taiyakihitotsu taiyakihitotsu changed the title LastOfUnion: export internal type, useful to recurse union-types. UnionMember: export internal type, useful to recurse union-types. Feb 15, 2026

This comment was marked as resolved.

Repository owner deleted a comment from Copilot AI Feb 17, 2026
Copy link
Collaborator

@som-sm som-sm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR mostly LGTM, just few minor comments.

@taiyakihitotsu taiyakihitotsu force-pushed the add/last-of-union-20260204 branch from 4332fc5 to 1c642f4 Compare March 1, 2026 16:34
@taiyakihitotsu taiyakihitotsu requested a review from som-sm March 1, 2026 16:56
Co-authored-by: Som Shekhar Mukherjee <49264891+som-sm@users.noreply.github.com>
@taiyakihitotsu
Copy link
Contributor Author

@som-sm

Thank you!
Picked your comment: #1368 (comment)

I guess that's why you chose not to add an example.

Yes.
Now I think UnionLength defined in the doc is enough to describe how to write a recursion of union type.

@taiyakihitotsu taiyakihitotsu requested a review from som-sm March 3, 2026 02:26
@som-sm som-sm changed the title UnionMember: export internal type, useful to recurse union-types. Add UnionMember type Mar 3, 2026
@som-sm
Copy link
Collaborator

som-sm commented Mar 17, 2026

@sindresorhus If this LGTY, this can be merged. Also, #1349.

@sindresorhus sindresorhus merged commit 878b6df into sindresorhus:main Mar 18, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants