microsoft / microsoft/TypeScript

Common fields of union not resolved for generic conditional with `any` branch

Open
#62,466 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Bug Domain: Conditional Types Help Wanted
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
2d 4h
Merged PRs (30d)
132

Description

🔎 Search Terms

"conditional generics with any branch in union", "union with generic conditional branch"

🕗 Version & Regression Information

This is the behavior in every version I tried, and I reviewed the FAQ for entries about conditional generics used in unions but didn't find anything that seemed relevant.

⏯ Playground Link

https://www.typescriptlang.org/play/?ts=5.9.2#code/C4TwDgpgBAkgdgYQPYFsVLlAvFA3gY1XTgC4oBnYAJwEs4BzAXwG4AoV0SKZOAExuA0MAQwA2AHgDSUCAA9gEPuQrU69KAB8ocAK4oARhCoA+bFGlyFS7XsNUoAfjwYIZXQaOMoZAEoRCVLzilLQMADRQOnAA1nBIAO5wxmyc0ACqcEJwAOoCABZ+9DqiwlQ8-IIiEhbyirzKIWqaNh4mZvDIaBjNABTlAlliUqYAZLCIRBgAlGwAZlH4lZhywihgohAZWbnABRBFJVRSMrXWjQzN7nbGPdEQIGSSU3isUG9QhHCUkZkYO3sHUr9JZiMy4LzCZRbP75QrFIEYCqDarJV7vAD06KguxoyniSCo0WUkJOkEWEF4aLeUW2sP28LKiIGVQAdIQunA2Ix2KluEyQaJ-gBBOAgY6WOoNVQXLRXIymHA1Kz1Fp2RxQYSi7xQPwBILnegRKKxBJJFLgdK-HL5EUgYHI8WnFUGy62eXtCYc3r2qrC0XDKBjDqTOAzVjzOCLLInVbrTZWv1ipWSlShdSyt0mW73R7PXBUj4Yb40mG7W0+uCgnDgjVQhM20UVoaSVHvKCY7F5XFQPIk4TYi0yKhUAlQWajgAG7OIE+0SGAJ1xggu3QnTcFDaTo3GnRnBZL1rLjf5yLZIbYbYLHf0OgXu0Une7ACpeEgIOQn1B8YSC59vmARzARN1zBCFlD6E9fU3AMg09YgwzbACkCAzd1zPDkuVYIA

💻 Code
type InCommon = {common: string};

type Conditional<K extends string | number> = K extends number ? {one: number} : Record<string, unknown>;
type UnionWithRegularConditional<K extends string | number> = InCommon | (Conditional<K> & InCommon);
function exampleUnionWithRegular<K extends string | number>(key: K) {
    const unionWithRegularConditional = {} as UnionWithRegularConditional<K>;
    // this works as expected
    unionWithRegularConditional.common;
}

type ConditionalWithAny<K extends string | number> = K extends number ? any : Record<string, unknown>;
type UnionWithAnyConditional<K extends string | number> = InCommon | (ConditionalWithAny<K> & InCommon);
function exampleUnionWithAny<K extends string | number>(key: K) {
    const unionWithAnyConditional = {} as UnionWithAnyConditional<K>;
    // this has a type error for `common` not existing on `ConditionalWithAny<K> & InCommon`
    unionWithAnyConditional.common;
    
    // but then this *does* work
    const propWithAnyConditional = {} as (ConditionalWithAny<K> & InCommon);
    propWithAnyConditional.common;
}
🙁 Actual behavior

When a union type contains a conditional generic whose branch is any, the common fields of the union are not being correctly recognized.

This is illustrated above when TS is unable to recognize that common is a field on unionWithAnyConditional.

🙂 Expected behavior

The expected behavior here is that common fields of the union should be correctly resolved.

From the above example, the expectation is that unionWithAnyConditional.common would not have a "does not exist on type" error.

Additional information about the issue

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked TypeScript Playground repro and confirm the difference between the regular conditional and the conditional with an any branch. Trace the compiler's handling of common properties on the resulting union, then add coverage for unionWithAnyConditional.common. Done means the expected access no longer reports that common is missing.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.