@@ -695,14 +695,30 @@ var NoUnnecessaryConditionRule = rule.Rule{
695695 }
696696 }
697697
698- // Helper: Get the return type of a call expression's function
699- // Returns the function's return type, or the full expression type for union of functions
698+ // Helper: Get the effective type of a call expression.
699+ // For plain calls, prefer the resolved call-site type so overloaded APIs like
700+ // react-hook-form's getValues(path) use the selected overload.
701+ // For calls that are themselves part of an optional chain, fall back to the
702+ // callee's return type so we ignore undefined introduced only by short-circuiting
703+ // earlier chain segments.
700704 getCallReturnType := func (callExpr * ast.Node ) * checker.Type {
701705 if callExpr == nil || callExpr .Kind != ast .KindCallExpression {
702706 return nil
703707 }
704708
705709 call := callExpr .AsCallExpression ()
710+ if call .QuestionDotToken == nil && ! hasOptionalChain (call .Expression ) {
711+ if callType := getResolvedType (callExpr ); callType != nil {
712+ return callType
713+ }
714+ }
715+
716+ if resolvedSignature := checker .Checker_getResolvedSignature (ctx .TypeChecker , callExpr , nil , checker .CheckModeNormal ); resolvedSignature != nil {
717+ if returnType := ctx .TypeChecker .GetReturnTypeOfSignature (resolvedSignature ); returnType != nil {
718+ return returnType
719+ }
720+ }
721+
706722 funcType := getResolvedType (call .Expression )
707723 if funcType == nil {
708724 return nil
@@ -862,6 +878,34 @@ var NoUnnecessaryConditionRule = rule.Rule{
862878 return ctx .TypeChecker .GetTypeAtLocation (accessExpr )
863879 }
864880
881+ isCallExpressionNullableOriginFromCallee := func (callExpr * ast.CallExpression ) bool {
882+ if callExpr == nil {
883+ return false
884+ }
885+
886+ prevType := getResolvedType (callExpr .Expression )
887+ if prevType == nil || ! utils .IsUnionType (prevType ) {
888+ return false
889+ }
890+
891+ isOwnNullable := false
892+ for _ , part := range prevType .Types () {
893+ signatures := ctx .TypeChecker .GetCallSignatures (part )
894+ for _ , sig := range signatures {
895+ returnType := ctx .TypeChecker .GetReturnTypeOfSignature (sig )
896+ if returnType != nil && isNullishType (returnType ) {
897+ isOwnNullable = true
898+ break
899+ }
900+ }
901+ if isOwnNullable {
902+ break
903+ }
904+ }
905+
906+ return ! isOwnNullable && isNullishType (prevType )
907+ }
908+
865909 // checkOptionalChain validates optional chaining (?.) to detect unnecessary usage.
866910 //
867911 // Optional chaining is unnecessary when the expression being accessed is never nullish.
@@ -1294,6 +1338,16 @@ var NoUnnecessaryConditionRule = rule.Rule{
12941338 return
12951339 }
12961340
1341+ if isCallExpr (expression ) {
1342+ callExpr := expression .AsCallExpression ()
1343+ if isCallExpressionNullableOriginFromCallee (callExpr ) {
1344+ exprType = removeNullishFromType (exprType )
1345+ if exprType == nil {
1346+ return
1347+ }
1348+ }
1349+ }
1350+
12971351 // Special case: if expression is a call to a union of functions
12981352 // and any function returns nullish, allow the optional chain
12991353 // e.g., type Foo = (() => undefined) | (() => number) | null
0 commit comments