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'*/
}