Skip to content

Distinguish missing and undefined #13195

Closed

Description

TypeScript Version: 2.1.4

Code

Current, with --strictNullChecks on, the typescript compiler seems to treat

interface Foo1 {
  bar?: string;
}

and

interface Foo2 {
  bar?: string | undefined;
}

as being the same type - in that let foo: Foo1 = {bar: undefined}; is legal. However, this does not seem to be the original intent of the language - while some people have used ? as a shortcut for | undefined (e.g. #12793 (comment)), it seems that the intent of the operator was to signify that the property either did not appear, or appeared and is of the specified type (as alluded in #12793 (comment)) - which might not include undefined - and in particular it would let us write types that either have a property that, if enumerable is not undefined, or is not present on the object.

In other places it might make sense for ? to keep serving as a shorthand for | undefined, e.g. for function parameters. (or maybe for consistency it would make sense to stick with it meaning "always pass something undefined if you pass anything"? not sure what's best there. Happy to discuss.)

Expected behavior:

interface Foo1 {
  bar?: string;
}
function baz(bar: string) {};

let foo: Foo1 = {bar: undefined}; // type error: string? is incompatible with undefined

if (foo.hasOwnProperty("bar")) {
  baz(foo.bar); // control flow analysis should figure out foo must have a bar attribute here that's not undefined
}
if ("bar" in foo) {
  baz(foo.bar); // control flow analysis should figure out foo must have a bar attribute here that's not undefined
}

Actual behavior:

interface Foo1 {
  bar?: string;
}
function baz(bar: string) {};

let foo: Foo1 = {bar: undefined}; // compiler is happy

if (foo.hasOwnProperty("bar")) {
  baz(foo.bar); /*  error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.  Type 'undefined' is not assignable to type 'string'*/

}
if ("bar" in foo) {
  baz(foo.bar); /* error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.  Type 'undefined' is not assignable to type 'string'*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

No one assigned

    Labels

    Breaking ChangeWould introduce errors in existing codeWould introduce errors in existing codeSuggestionAn idea for TypeScriptAn idea for TypeScript

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions