Skip to content

Type narrowing does not work when accessing a Partial<Record> with a Union type as the key #54003

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
ChrisRZen opened this issue Apr 24, 2023 · 7 comments
Labels
Duplicate An existing issue was already created

Comments

@ChrisRZen
Copy link

Bug Report

🔎 Search Terms

type narrowing, union, if, undefined, partial

🕗 Version & Regression Information

I saw this initially with 5.0.4 I used the playground below to try with other versions as old as 3.3

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about narrowing union types

⏯ Playground Link

Playground link with relevant code

💻 Code

type ExplicitUnion = "foo" | "bar" | "baz"

const recordWithPartialUnionKey: Partial<Record<ExplicitUnion, string>> = {
    "foo": "fiz"
}


const useUnionTypeKeys = (key: ExplicitUnion):string => {
    if(recordWithPartialUnionKey[key] !== undefined) {
        return recordWithPartialUnionKey[key] // This fails the function const
    }
    return "test"
}

// Create a Union type with some literal strings
type StringUnion = "foo" | "bar" | "baz"

// Create a record with a partial Record using said Union
const recordWithPartialUnionKey: Partial<Record<StringUnion, string>> = {
    "foo": "fiz"
}


const useUnionTypeKeys = (key: StringUnion):string => {
    if(recordWithPartialUnionKey[key] !== undefined) {
        return recordWithPartialUnionKey[key] // Type 'string | undefined' is not assignable to type 'string'.
    }
    return "test"
}

// String narrowing works fine
type StringRecord = Record<string, string>

const stringRecord:StringRecord = {
    "foo": "fiz"
}

const useStringKeyRecord = (key: string):string => {
    if(stringRecord[key] !== undefined) {
        return stringRecord[key] // This passes the typecheck
    }
    return "test"
}

🙁 Actual behavior

When checking if a key exists on a Partial<Record> with a key value type set to a union of string literals, the type of the value is not narrowed down in the same way as it is for a Record with a string key in a similar situation.

🙂 Expected behavior

When checking if a key exists on a Partial<Record> with a key value type set to a union of string literals, the type of the value is narrowed to exclude undefined

@RyanCavanaugh
Copy link
Member

There's no narrowing going on in the bottom example.

Duplicate #48227, etc

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Apr 24, 2023
@ChrisRZen
Copy link
Author

There's no narrowing going on in the bottom example.

Duplicate #48227, etc

Ah I see. I forgot about the noUncheckedIndexedAccess config which would cause the second example to fail.

@RyanCavanaugh I tried looking through the FAQ and it sounds like this has come up a lot. Did I miss a question that covers this? Is it valid to consider this a bug?

@RyanCavanaugh
Copy link
Member

This should be in the FAQ.

I would say this is really more of a feature request, since to do it soundly requires tracking information that is currently not considered. Conservative implementations of this have also incurred too-large performance hits, so it's a trade-off.

@microsoft-github-policy-service

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@microsoft-github-policy-service

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

2 similar comments
@microsoft-github-policy-service

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@microsoft-github-policy-service

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

2 participants