Potential Optional Chaining Bug
See original GitHub issueTypeScript Version: 3.7.x-dev.201xxxxx
Search Terms:
Optional Chaining Type bug
Code’
We found a bug within our codebase where a specific instance is returning “undefined” within production code. Upon review, we found this instance and recreated it here. Basically, TypeScript knows that “value” is associated to “string[] | undefined”, however, it ignores “undefined” when “.includes” is added onto it for most instances and acts like it is “string[]”.
interface Model {
MyField: FieldModel
}
interface FieldModel {
value: string[]
}
type ValidateFn<Model, Key extends keyof Model> = (
value: Partial<Model[Key]>,
attributes: Partial<Model>
) => void
const validator:ValidateFn<Model, 'MyField'> = (v, attributes) => {
// value is 'string[] | undefined', yet, shows no error for value/includes.
attributes.MyField?.value.includes('test')
const MyField = attributes.MyField
// value is 'string[] | undefined', yet, shows no error for value/includes.
MyField?.value.includes('test')
const value = attributes.MyField?.value
// value is 'string[] | undefined'. This is the only one that shows an error for value/includes.
value.includes('test')
}
Expected behavior:
Expected an error associated to “value” in each instance as value is a “string[] | undefined”.
Actual behavior:
An error is only returned on the last line. The previous lines are not showing an error. Thus, this would create a false positive that “undefined” is handled to the developer (unless they test or check it manually).
Playground Link:
Related Issues:
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:12 (11 by maintainers)
Top GitHub Comments
@marafat that’s unrelated; please log a new issue. Thanks!
I personally disagree. These are two separate things. If i have
a?.b
then if i hover onb
i want to know whatb
actually is as that will dictate what i can do with it as i continue that expression. For examplea?.b.x
The things i candot off
ofb
will be based onb
’s actual type, not the type of the entirea?.b
expression.It’s the difference between
a?.b.
vs(a?.b).
. Since there is no parenthesization, and since we’re examining the RHS, i think it only makes sense to to state whatb
actually is. If we didn’t, it would actually be more confusing as it would imply that you could get a different set of results than what you actually get.