You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
noUncheckedIndexedAccess does not narrow properly with "prop" in obj #43614
declarefunctioninvariant(condition: boolean): asserts condition;functionfoo(obj: Readonly<Record<string,string>>){invariant(obj&&"test"inobj);// this one below does narrow to `string`// invariant(!!obj["test"]);constx=obj["test"]// string | undefined but should be string}
Ah, I see. When you set --noUncheckedIndexedAccess, the read type of property access on a Readonly<Record<string, string>> goes from string to string | undefined. But we don’t currently have the ability to model the difference between properties that are undefined and properties that are missing. If we were to introduce a missing type in the future, we would be able to implement the behavior you expect here—the read type from that index signature would be string | missing, and you could know that it’s not missing via an in test. But right now, because we lack the concept of missing, an in test on an object with an index signature does nothing.
Activity
andreialecu commentedon Apr 9, 2021
Seems related to #41848
andrewbranch commentedon Apr 9, 2021
This isn’t really related to
noUncheckedIndexedAccess—innarrowing doesn’t ever takeundefinedout of the domain of a property: https://www.typescriptlang.org/play?noUncheckedIndexedAccess=true&ts=4.3.0-beta#code/CYUwxgNghgTiAEA3W8D2AjAVgLngb3gBcQBnQgflzJgEsA7Ac3gF8BuAKHZoDN4AKAETEyA+PTRYAlPnbx4YVHTLwAHvAC8EzAG0hpQgIC6HOQqWF4ATw1aAdMMIdm7IAYou should check for equality / non-equality with
undefinedif you want that behavior.typescript-bot commentedon Apr 12, 2021
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.
andreialecu commentedon Apr 12, 2021
Not sure I understand. The type of
objcannot have undefined values in it as per its definition.How does
undefinedfit intoReadonly<Record<string, string>>?andrewbranch commentedon Apr 12, 2021
Ah, I see. When you set
--noUncheckedIndexedAccess, the read type of property access on aReadonly<Record<string, string>>goes fromstringtostring | undefined. But we don’t currently have the ability to model the difference between properties that areundefinedand properties that are missing. If we were to introduce amissingtype in the future, we would be able to implement the behavior you expect here—the read type from that index signature would bestring | missing, and you could know that it’s notmissingvia anintest. But right now, because we lack the concept ofmissing, anintest on an object with an index signature does nothing.derolf commentedon Sep 23, 2021
With exactOptionalPropertyTypes, unchecked index access could map to
missingand notundefined.Then
key inguarded access should work equally on optionally declared properties and index signatures.Example highlighting the obvious disparity:
https://www.typescriptlang.org/play?noUncheckedIndexedAccess=true&exactOptionalPropertyTypes=true&ts=4.4.2#code/CYUwxgNghgTiAEA3W8D2AjAVgLngJXFRmAB4BnAFxgEsA7AcwBp5KaGA+AbgChRJYEyGGiwAmXAG8KISgH5crOvQC+3btQBm8ABQAiaZV3w6IzAEp4E7vHgB6W-A1RqEMtfhhUtSvACe8BSoleABeUwA6AwoeVXUtPSijEwxMUQsrG3t4AHciAGs3G09vCj8AliCGUNNRSJkKbligA
KaelWD commentedon Dec 10, 2021
This seems like a bug rather than a design limitation then.
tskj commentedon Nov 8, 2022
I agree that this is neither a design limitation nor working as intended. This is simply a bug and Daniel Rolf (@derolf)'s example proves it.