Skip to content

TS "Optional Properties" accepts "undefined" as a value when it shouldn't...Β #57479

Closed
@denis-migdal

Description

@denis-migdal

πŸ”Ž Search Terms

Optional Properties accept undefined

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the documentation

⏯ Playground Link

Playground Link

πŸ’» Code

{
    type T = {
        DELETED?: string
    }

    let t1: T = {};
    console.log( Object.keys(t1) ); // []
    console.log( "DELETED" in t1 ); // false

    let t2: T = {DELETED: undefined}; // WRONG
    console.log( Object.keys(t2) ); // ["DELETED"]
    console.log( "DELETED" in t2 ); // true
}


{
    function foo(_a: number, _b?: string) {
        console.log(arguments);
    }

    console.log("test 1");
    foo(3); // [3]
    foo(3, undefined); // WRONG [3, undefined]
}

πŸ™ Actual behavior

In JS, there is a difference in behavior between properties that :

  1. doesn't exist (i.e. without value), and returns undefined when accessed.
  2. exists, with undefined as a value.

TS enables to declare a property optional with the "?" symbol (so normally corresponding to case 1.). However, this notation also allows case 2., which shouldn't be the case:

{
    type T = {
        DELETED?: string
    }

    let t1: T = {};
    console.log( Object.keys(t1) ); // []
    console.log( "DELETED" in t1 ); // false

    let t2: T = {DELETED: undefined}; // WRONG
    console.log( Object.keys(t2) ); // ["DELETED"]
    console.log( "DELETED" in t2 ); // true
}


{
    function foo(_a: number, _b?: string) {
        console.log(arguments);
    }

    console.log("test 1");
    foo(3); // [3]
    foo(3, undefined); // WRONG [3, undefined]
}

πŸ™‚ Expected behavior

When assigning a value to a type with optional fields, TS should forbid undefined values except if explicitly authorized :

type T1 = {field?: string};
type T2 = {field?: string|undefined};

let t1: T1 = {field: undefined} // should raise an error.
let t2: T2 = {field: undefined} // ok

Additional information about the issue

I get this would likely be a breaking change... but this is a bug.
Maybe a flag or a way to change TS behavior on this matter could help keeping retro-compatibility ?

Metadata

Metadata

Assignees

No one assigned

    Labels

    QuestionAn issue which isn't directly actionable in code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions