Skip to content

Optional property could be undefined even after explicitly checking for truthiness #37382

Closed
@mtjn

Description

@mtjn

TypeScript Version: Nightly

Search Terms: "argument not assignable" "optional property" 2345

Expected behavior: Typescript should realise that the property has been checked for truthiness and cannot be undefined, no error should be raised

Actual behavior: Typescript claims that the property could still be undefined and raises this error:

Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
  Type 'undefined' is not assignable to type 'string'.(2345)

Related Issues:
#37240
#35964
#36193

Code

interface IFoo {
  bar?: string;
}

type Obj = {[key: string]: IFoo}

function print(str: string) {
  return console.log(str);
}

export function check(obj: Obj, key: string) {
  if (obj[key]?.bar) {
    print(obj[key]?.bar);
  }
}
Output
function print(str) {
    return console.log(str);
}
export function check(obj, key) {
    var _a, _b;
    if ((_a = obj[key]) === null || _a === void 0 ? void 0 : _a.bar) {
        print((_b = obj[key]) === null || _b === void 0 ? void 0 : _b.bar);
    }
}
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

    DuplicateAn existing issue was already created

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions