From 2fb51e71125a9100c69c8673f3adb65ecbb5be81 Mon Sep 17 00:00:00 2001 From: Herrington Darkholme Date: Sat, 26 Nov 2016 12:49:55 +0800 Subject: [PATCH] address code review feedback --- src/compiler/checker.ts | 6 +-- .../nonPrimitiveAccessProperty.ts | 3 ++ .../nonPrimitive/nonPrimitiveAssignError.ts | 8 ++++ .../nonPrimitive/nonPrimitiveInGeneric.ts | 7 +++ .../types/nonPrimitive/nonPrimitiveNarrow.ts | 22 +++++++++ .../nonPrimitive/nonPrimitiveStrictNull.ts | 48 +++++++++++++++++++ 6 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts create mode 100644 tests/cases/conformance/types/nonPrimitive/nonPrimitiveNarrow.ts create mode 100644 tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c863e2fd2c7..a1fae5ebbd3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3089,10 +3089,6 @@ namespace ts { return type && (type.flags & TypeFlags.Never) !== 0; } - function isTypeNonPrimitive(type: Type) { - return type === nonPrimitiveType; - } - // Return the type of a binding element parent. We check SymbolLinks first to see if a type has been // assigned by contextual typing. function getTypeForBindingElementParent(node: VariableLikeDeclaration) { @@ -7475,7 +7471,7 @@ namespace ts { } } } - else if (!(source.flags & TypeFlags.Primitive && isTypeNonPrimitive(target))) { + else if (!(source.flags & TypeFlags.Primitive && target === nonPrimitiveType)) { if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (source).target === (target).target) { // We have type references to same target type, see if relationship holds for all type arguments if (result = typeArgumentsRelatedTo(source, target, reportErrors)) { diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts new file mode 100644 index 00000000000..2febbb1e2ca --- /dev/null +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAccessProperty.ts @@ -0,0 +1,3 @@ +var a: object; +a.toString(); +a.nonExist(); // error diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts index f177b5cd255..8fe8c8a3ebb 100644 --- a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts @@ -15,3 +15,11 @@ a = s; // expect error n = a; // expect error b = a; // expect error s = a; // expect error + +var numObj: Number = 123; +var boolObj: Boolean = true; +var strObj: String = "string"; + +a = numObj; // ok +a = boolObj; // ok +a = strObj; // ok diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts index 0e7914ab715..0de4771a5ef 100644 --- a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveInGeneric.ts @@ -13,3 +13,10 @@ bound({}); bound(a); bound(123); // expect error bound(b); // expect error + +function bound2() {} + +bound2<{}>(); +bound2(); +bound2(); // expect error +bound2(); // expect error diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveNarrow.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveNarrow.ts new file mode 100644 index 00000000000..04f7351290e --- /dev/null +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveNarrow.ts @@ -0,0 +1,22 @@ +class Narrow { + narrowed: boolean +} + +var a: object + +if (a instanceof Narrow) { + a.narrowed; // ok + a = 123; // error +} + +if (typeof a === 'number') { + a.toFixed(); // error, never +} + +var b: object | null + +if (typeof b === 'object') { + b.toString(); // error, object | null +} else { + b.toString(); // error, never +} diff --git a/tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts new file mode 100644 index 00000000000..5fbf85dc01b --- /dev/null +++ b/tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts @@ -0,0 +1,48 @@ +// @strictNullChecks: true + +var a: object +declare var b: object | null +declare var c: object | undefined +declare var d: object | null | undefined +var e: object | null +a.toString; // error +a = undefined; // error +a = null; // error +a = b; // error +a = c; // error +a = d; // error + +e = a; // ok +a = e; // ok + +if (typeof b !== 'object') { + b.toString(); // error, never +} + +if (typeof b === 'object') { + a = b; // error, b is not narrowed +} + +if (typeof d === 'object') { + b = d; // ok +} else { + d; // undefined +} + +if (d == null) { + d; // null | undefined +} else { + d.toString(); // object +} + +if (d === null) { + d; // null +} else { + d.toString(); // error, object | undefined +} + +if (typeof d === 'undefined') { + d; // undefined +} else { + d.toString(); // error, object | null +}