Skip to content

Wrong Type Error on missing property when using optional chaining #35543

@Ninerian

Description

@Ninerian

TypeScript Version: 3.7.2

Search Terms:

  • optional chainging
  • missing property

Expected behavior:
Typescript should handle the optional method as same as optional properties

Actual behavior:
Typescript throws a warning:

Property 'foo' does not exist on type 'A | B'.
  Property 'foo' does not exist on type 'B'.(2339)

The code itself is doing what I expected. When the method is not found, it uses the right hand value.

Related Issues:
No issue found

Code

class A {
    public foo() {
        return 'foo'
    }
    public bar() {
        return 'bar'
    }
}

class B {
    public bar() {
        return 'bar'
    }
}

const x = (F: typeof A | typeof B) => {
    const f = new F();

    return f.foo?.() ?? 'baz';
}

console.log(x(A)); // foo
console.log(x(B)); // baz
Output
"use strict";
class A {
    foo() {
        return 'foo';
    }
    bar() {
        return 'bar';
    }
}
class B {
    bar() {
        return 'bar';
    }
}
const x = (F) => {
    var _a, _b, _c;
    const f = new F();
    return _c = (_b = (_a = f).foo) === null || _b === void 0 ? void 0 : _b.call(_a), (_c !== null && _c !== void 0 ? _c : 'baz');
};
console.log(x(A)); // foo
console.log(x(B)); // baz
Compiler Options
{
  "compilerOptions": {
    "noImplicitAny": true,
    "strictNullChecks": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true,
    "strictBindCallApply": true,
    "noImplicitThis": true,
    "noImplicitReturns": true,
    "useDefineForClassFields": false,
    "alwaysStrict": true,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "downlevelIteration": false,
    "noEmitHelpers": false,
    "noLib": false,
    "noStrictGenericChecks": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "esModuleInterop": true,
    "preserveConstEnums": false,
    "removeComments": false,
    "skipLibCheck": false,
    "checkJs": false,
    "allowJs": false,
    "declaration": true,
    "experimentalDecorators": false,
    "emitDecoratorMetadata": false,
    "target": "ES2017",
    "module": "ESNext"
  }
}

Playground Link: Provided

Metadata

Metadata

Assignees

No one assigned

    Labels

    Working as IntendedThe behavior described is the intended behavior; this is not a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions