Merge pull request #10334 from yortus/narrow-from-any
Narrow from 'any' in most situations
This commit is contained in:
commit
78cea2adb5
|
@ -8548,10 +8548,6 @@ namespace ts {
|
|||
}
|
||||
return type;
|
||||
}
|
||||
// We never narrow type any in an instanceof guard
|
||||
if (isTypeAny(type)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Check that right operand is a function type with a prototype property
|
||||
const rightType = checkExpression(expr.right);
|
||||
|
@ -8569,6 +8565,11 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
// Don't narrow from 'any' if the target type is exactly 'Object' or 'Function'
|
||||
if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (!targetType) {
|
||||
// Target type is type of construct signature
|
||||
let constructSignatures: Signature[];
|
||||
|
@ -8615,7 +8616,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
|
||||
if (type.flags & TypeFlags.Any || !hasMatchingArgument(callExpression, reference)) {
|
||||
if (!hasMatchingArgument(callExpression, reference)) {
|
||||
return type;
|
||||
}
|
||||
const signature = getResolvedSignature(callExpression);
|
||||
|
@ -8623,6 +8624,12 @@ namespace ts {
|
|||
if (!predicate) {
|
||||
return type;
|
||||
}
|
||||
|
||||
// Don't narrow from 'any' if the predicate type is exactly 'Object' or 'Function'
|
||||
if (isTypeAny(type) && (predicate.type === globalObjectType || predicate.type === globalFunctionType)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (isIdentifierTypePredicate(predicate)) {
|
||||
const predicateArgument = callExpression.arguments[predicate.parameterIndex];
|
||||
if (predicateArgument) {
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
tests/cases/conformance/types/any/narrowExceptionVariableInCatchClause.ts(11,17): error TS2339: Property 'doPanic' does not exist on type '{ type: "foo"; dontPanic(): any; }'.
|
||||
tests/cases/conformance/types/any/narrowExceptionVariableInCatchClause.ts(16,17): error TS2339: Property 'massage' does not exist on type 'Error'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/any/narrowExceptionVariableInCatchClause.ts (2 errors) ====
|
||||
declare function isFooError(x: any): x is { type: 'foo'; dontPanic(); };
|
||||
|
||||
function tryCatch() {
|
||||
try {
|
||||
// do stuff...
|
||||
}
|
||||
catch (err) { // err is implicitly 'any' and cannot be annotated
|
||||
|
||||
if (isFooError(err)) {
|
||||
err.dontPanic(); // OK
|
||||
err.doPanic(); // ERROR: Property 'doPanic' does not exist on type '{...}'
|
||||
~~~~~~~
|
||||
!!! error TS2339: Property 'doPanic' does not exist on type '{ type: "foo"; dontPanic(): any; }'.
|
||||
}
|
||||
|
||||
else if (err instanceof Error) {
|
||||
err.message;
|
||||
err.massage; // ERROR: Property 'massage' does not exist on type 'Error'
|
||||
~~~~~~~
|
||||
!!! error TS2339: Property 'massage' does not exist on type 'Error'.
|
||||
}
|
||||
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//// [narrowExceptionVariableInCatchClause.ts]
|
||||
declare function isFooError(x: any): x is { type: 'foo'; dontPanic(); };
|
||||
|
||||
function tryCatch() {
|
||||
try {
|
||||
// do stuff...
|
||||
}
|
||||
catch (err) { // err is implicitly 'any' and cannot be annotated
|
||||
|
||||
if (isFooError(err)) {
|
||||
err.dontPanic(); // OK
|
||||
err.doPanic(); // ERROR: Property 'doPanic' does not exist on type '{...}'
|
||||
}
|
||||
|
||||
else if (err instanceof Error) {
|
||||
err.message;
|
||||
err.massage; // ERROR: Property 'massage' does not exist on type 'Error'
|
||||
}
|
||||
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [narrowExceptionVariableInCatchClause.js]
|
||||
function tryCatch() {
|
||||
try {
|
||||
}
|
||||
catch (err) {
|
||||
if (isFooError(err)) {
|
||||
err.dontPanic(); // OK
|
||||
err.doPanic(); // ERROR: Property 'doPanic' does not exist on type '{...}'
|
||||
}
|
||||
else if (err instanceof Error) {
|
||||
err.message;
|
||||
err.massage; // ERROR: Property 'massage' does not exist on type 'Error'
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
tests/cases/conformance/types/any/narrowFromAnyWithInstanceof.ts(17,7): error TS2339: Property 'mesage' does not exist on type 'Error'.
|
||||
tests/cases/conformance/types/any/narrowFromAnyWithInstanceof.ts(22,7): error TS2339: Property 'getHuors' does not exist on type 'Date'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/any/narrowFromAnyWithInstanceof.ts (2 errors) ====
|
||||
declare var x: any;
|
||||
|
||||
if (x instanceof Function) { // 'any' is not narrowed when target type is 'Function'
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
|
||||
if (x instanceof Object) { // 'any' is not narrowed when target type is 'Object'
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (x instanceof Error) { // 'any' is narrowed to types other than 'Function'/'Object'
|
||||
x.message;
|
||||
x.mesage;
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'mesage' does not exist on type 'Error'.
|
||||
}
|
||||
|
||||
if (x instanceof Date) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
~~~~~~~~
|
||||
!!! error TS2339: Property 'getHuors' does not exist on type 'Date'.
|
||||
}
|
||||
|
45
tests/baselines/reference/narrowFromAnyWithInstanceof.js
Normal file
45
tests/baselines/reference/narrowFromAnyWithInstanceof.js
Normal file
|
@ -0,0 +1,45 @@
|
|||
//// [narrowFromAnyWithInstanceof.ts]
|
||||
declare var x: any;
|
||||
|
||||
if (x instanceof Function) { // 'any' is not narrowed when target type is 'Function'
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
|
||||
if (x instanceof Object) { // 'any' is not narrowed when target type is 'Object'
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (x instanceof Error) { // 'any' is narrowed to types other than 'Function'/'Object'
|
||||
x.message;
|
||||
x.mesage;
|
||||
}
|
||||
|
||||
if (x instanceof Date) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
}
|
||||
|
||||
|
||||
//// [narrowFromAnyWithInstanceof.js]
|
||||
if (x instanceof Function) {
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
if (x instanceof Object) {
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
if (x instanceof Error) {
|
||||
x.message;
|
||||
x.mesage;
|
||||
}
|
||||
if (x instanceof Date) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(22,7): error TS2339: Property 'method' does not exist on type '{}'.
|
||||
tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(23,5): error TS2349: Cannot invoke an expression whose type lacks a call signature.
|
||||
tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(28,7): error TS2339: Property 'mesage' does not exist on type 'Error'.
|
||||
tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts(33,7): error TS2339: Property 'getHuors' does not exist on type 'Date'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/any/narrowFromAnyWithTypePredicate.ts (4 errors) ====
|
||||
declare var x: any;
|
||||
declare function isFunction(x): x is Function;
|
||||
declare function isObject(x): x is Object;
|
||||
declare function isAnything(x): x is {};
|
||||
declare function isError(x): x is Error;
|
||||
declare function isDate(x): x is Date;
|
||||
|
||||
|
||||
if (isFunction(x)) { // 'any' is not narrowed when target type is 'Function'
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
|
||||
if (isObject(x)) { // 'any' is not narrowed when target type is 'Object'
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (isAnything(x)) { // 'any' is narrowed to types other than 'Function'/'Object' (including {})
|
||||
x.method();
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'method' does not exist on type '{}'.
|
||||
x();
|
||||
~~~
|
||||
!!! error TS2349: Cannot invoke an expression whose type lacks a call signature.
|
||||
}
|
||||
|
||||
if (isError(x)) {
|
||||
x.message;
|
||||
x.mesage;
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'mesage' does not exist on type 'Error'.
|
||||
}
|
||||
|
||||
if (isDate(x)) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
~~~~~~~~
|
||||
!!! error TS2339: Property 'getHuors' does not exist on type 'Date'.
|
||||
}
|
||||
|
60
tests/baselines/reference/narrowFromAnyWithTypePredicate.js
Normal file
60
tests/baselines/reference/narrowFromAnyWithTypePredicate.js
Normal file
|
@ -0,0 +1,60 @@
|
|||
//// [narrowFromAnyWithTypePredicate.ts]
|
||||
declare var x: any;
|
||||
declare function isFunction(x): x is Function;
|
||||
declare function isObject(x): x is Object;
|
||||
declare function isAnything(x): x is {};
|
||||
declare function isError(x): x is Error;
|
||||
declare function isDate(x): x is Date;
|
||||
|
||||
|
||||
if (isFunction(x)) { // 'any' is not narrowed when target type is 'Function'
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
|
||||
if (isObject(x)) { // 'any' is not narrowed when target type is 'Object'
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (isAnything(x)) { // 'any' is narrowed to types other than 'Function'/'Object' (including {})
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (isError(x)) {
|
||||
x.message;
|
||||
x.mesage;
|
||||
}
|
||||
|
||||
if (isDate(x)) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
}
|
||||
|
||||
|
||||
//// [narrowFromAnyWithTypePredicate.js]
|
||||
if (isFunction(x)) {
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
if (isObject(x)) {
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
if (isAnything(x)) {
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
if (isError(x)) {
|
||||
x.message;
|
||||
x.mesage;
|
||||
}
|
||||
if (isDate(x)) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
}
|
|
@ -1,16 +1,26 @@
|
|||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(12,10): error TS2339: Property 'bar' does not exist on type 'A'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(18,10): error TS2339: Property 'bar' does not exist on type 'A'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(33,5): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(34,10): error TS2339: Property 'bar' does not exist on type 'B<number>'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(41,10): error TS2339: Property 'bar' does not exist on type 'B<any>'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(66,10): error TS2339: Property 'bar2' does not exist on type 'C1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(72,10): error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(73,10): error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(85,10): error TS2339: Property 'bar' does not exist on type 'D'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(91,10): error TS2339: Property 'bar' does not exist on type 'D'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(112,10): error TS2339: Property 'bar2' does not exist on type 'E1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(118,11): error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(119,11): error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(134,11): error TS2339: Property 'foo' does not exist on type 'string | F'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(135,11): error TS2339: Property 'bar' does not exist on type 'string | F'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(160,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(166,11): error TS2339: Property 'foo2' does not exist on type 'G1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(182,11): error TS2339: Property 'bar' does not exist on type 'H'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(187,11): error TS2339: Property 'foo1' does not exist on type 'H'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts(188,11): error TS2339: Property 'foo2' does not exist on type 'H'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (10 errors) ====
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstructorSignature.ts (20 errors) ====
|
||||
interface AConstructor {
|
||||
new (): A;
|
||||
}
|
||||
|
@ -28,9 +38,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj2: any;
|
||||
if (obj2 instanceof A) { // can't narrow type from 'any'
|
||||
if (obj2 instanceof A) {
|
||||
obj2.foo;
|
||||
obj2.bar;
|
||||
~~~
|
||||
!!! error TS2339: Property 'bar' does not exist on type 'A'.
|
||||
}
|
||||
|
||||
// a construct signature with generics
|
||||
|
@ -54,10 +66,12 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj4: any;
|
||||
if (obj4 instanceof B) { // can't narrow type from 'any'
|
||||
if (obj4 instanceof B) {
|
||||
obj4.foo = "str";
|
||||
obj4.foo = 1;
|
||||
obj4.bar = "str";
|
||||
~~~
|
||||
!!! error TS2339: Property 'bar' does not exist on type 'B<any>'.
|
||||
}
|
||||
|
||||
// has multiple construct signature
|
||||
|
@ -88,10 +102,14 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj6: any;
|
||||
if (obj6 instanceof C) { // can't narrow type from 'any'
|
||||
if (obj6 instanceof C) {
|
||||
obj6.foo;
|
||||
obj6.bar1;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar1' does not exist on type 'C1 | C2'.
|
||||
obj6.bar2;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar2' does not exist on type 'C1 | C2'.
|
||||
}
|
||||
|
||||
// with object type literal
|
||||
|
@ -109,9 +127,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj8: any;
|
||||
if (obj8 instanceof D) { // can't narrow type from 'any'
|
||||
if (obj8 instanceof D) {
|
||||
obj8.foo;
|
||||
obj8.bar;
|
||||
~~~
|
||||
!!! error TS2339: Property 'bar' does not exist on type 'D'.
|
||||
}
|
||||
|
||||
// a construct signature that returns a union type
|
||||
|
@ -138,10 +158,14 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj10: any;
|
||||
if (obj10 instanceof E) { // can't narrow type from 'any'
|
||||
if (obj10 instanceof E) {
|
||||
obj10.foo;
|
||||
obj10.bar1;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar1' does not exist on type 'E1 | E2'.
|
||||
obj10.bar2;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'bar2' does not exist on type 'E1 | E2'.
|
||||
}
|
||||
|
||||
// a construct signature that returns any
|
||||
|
@ -165,7 +189,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj12: any;
|
||||
if (obj12 instanceof F) { // can't narrow type from 'any'
|
||||
if (obj12 instanceof F) {
|
||||
obj12.foo;
|
||||
obj12.bar;
|
||||
}
|
||||
|
@ -192,9 +216,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj14: any;
|
||||
if (obj14 instanceof G) { // can't narrow type from 'any'
|
||||
if (obj14 instanceof G) {
|
||||
obj14.foo1;
|
||||
obj14.foo2;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'foo2' does not exist on type 'G1'.
|
||||
}
|
||||
|
||||
// a type with a prototype that has any type
|
||||
|
@ -216,8 +242,24 @@ tests/cases/conformance/expressions/typeGuards/typeGuardsWithInstanceOfByConstru
|
|||
}
|
||||
|
||||
var obj16: any;
|
||||
if (obj16 instanceof H) { // can't narrow type from 'any'
|
||||
if (obj16 instanceof H) {
|
||||
obj16.foo1;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'foo1' does not exist on type 'H'.
|
||||
obj16.foo2;
|
||||
~~~~
|
||||
!!! error TS2339: Property 'foo2' does not exist on type 'H'.
|
||||
}
|
||||
|
||||
var obj17: any;
|
||||
if (obj17 instanceof Object) { // can't narrow type from 'any' to 'Object'
|
||||
obj17.foo1;
|
||||
obj17.foo2;
|
||||
}
|
||||
|
||||
var obj18: any;
|
||||
if (obj18 instanceof Function) { // can't narrow type from 'any' to 'Function'
|
||||
obj18.foo1;
|
||||
obj18.foo2;
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ if (obj1 instanceof A) { // narrowed to A.
|
|||
}
|
||||
|
||||
var obj2: any;
|
||||
if (obj2 instanceof A) { // can't narrow type from 'any'
|
||||
if (obj2 instanceof A) {
|
||||
obj2.foo;
|
||||
obj2.bar;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ if (obj3 instanceof B) { // narrowed to B<number>.
|
|||
}
|
||||
|
||||
var obj4: any;
|
||||
if (obj4 instanceof B) { // can't narrow type from 'any'
|
||||
if (obj4 instanceof B) {
|
||||
obj4.foo = "str";
|
||||
obj4.foo = 1;
|
||||
obj4.bar = "str";
|
||||
|
@ -68,7 +68,7 @@ if (obj5 instanceof C) { // narrowed to C1|C2.
|
|||
}
|
||||
|
||||
var obj6: any;
|
||||
if (obj6 instanceof C) { // can't narrow type from 'any'
|
||||
if (obj6 instanceof C) {
|
||||
obj6.foo;
|
||||
obj6.bar1;
|
||||
obj6.bar2;
|
||||
|
@ -87,7 +87,7 @@ if (obj7 instanceof D) { // narrowed to D.
|
|||
}
|
||||
|
||||
var obj8: any;
|
||||
if (obj8 instanceof D) { // can't narrow type from 'any'
|
||||
if (obj8 instanceof D) {
|
||||
obj8.foo;
|
||||
obj8.bar;
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ if (obj9 instanceof E) { // narrowed to E1 | E2
|
|||
}
|
||||
|
||||
var obj10: any;
|
||||
if (obj10 instanceof E) { // can't narrow type from 'any'
|
||||
if (obj10 instanceof E) {
|
||||
obj10.foo;
|
||||
obj10.bar1;
|
||||
obj10.bar2;
|
||||
|
@ -137,7 +137,7 @@ if (obj11 instanceof F) { // can't type narrowing, construct signature returns a
|
|||
}
|
||||
|
||||
var obj12: any;
|
||||
if (obj12 instanceof F) { // can't narrow type from 'any'
|
||||
if (obj12 instanceof F) {
|
||||
obj12.foo;
|
||||
obj12.bar;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ if (obj13 instanceof G) { // narrowed to G1. G1 is return type of prototype prop
|
|||
}
|
||||
|
||||
var obj14: any;
|
||||
if (obj14 instanceof G) { // can't narrow type from 'any'
|
||||
if (obj14 instanceof G) {
|
||||
obj14.foo1;
|
||||
obj14.foo2;
|
||||
}
|
||||
|
@ -184,10 +184,22 @@ if (obj15 instanceof H) { // narrowed to H.
|
|||
}
|
||||
|
||||
var obj16: any;
|
||||
if (obj16 instanceof H) { // can't narrow type from 'any'
|
||||
if (obj16 instanceof H) {
|
||||
obj16.foo1;
|
||||
obj16.foo2;
|
||||
}
|
||||
|
||||
var obj17: any;
|
||||
if (obj17 instanceof Object) { // can't narrow type from 'any' to 'Object'
|
||||
obj17.foo1;
|
||||
obj17.foo2;
|
||||
}
|
||||
|
||||
var obj18: any;
|
||||
if (obj18 instanceof Function) { // can't narrow type from 'any' to 'Function'
|
||||
obj18.foo1;
|
||||
obj18.foo2;
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardsWithInstanceOfByConstructorSignature.js]
|
||||
|
@ -278,3 +290,13 @@ if (obj16 instanceof H) {
|
|||
obj16.foo1;
|
||||
obj16.foo2;
|
||||
}
|
||||
var obj17;
|
||||
if (obj17 instanceof Object) {
|
||||
obj17.foo1;
|
||||
obj17.foo2;
|
||||
}
|
||||
var obj18;
|
||||
if (obj18 instanceof Function) {
|
||||
obj18.foo1;
|
||||
obj18.foo2;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ if (obj1 instanceof A) { // narrowed to A.
|
|||
}
|
||||
|
||||
var obj2: any;
|
||||
if (obj2 instanceof A) { // can't narrow type from 'any'
|
||||
if (obj2 instanceof A) {
|
||||
obj2.foo;
|
||||
obj2.bar;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ if (obj3 instanceof B) { // narrowed to B<number>.
|
|||
}
|
||||
|
||||
var obj4: any;
|
||||
if (obj4 instanceof B) { // can't narrow type from 'any'
|
||||
if (obj4 instanceof B) {
|
||||
obj4.foo = "str";
|
||||
obj4.foo = 1;
|
||||
obj4.bar = "str";
|
||||
|
@ -67,7 +67,7 @@ if (obj5 instanceof C) { // narrowed to C1|C2.
|
|||
}
|
||||
|
||||
var obj6: any;
|
||||
if (obj6 instanceof C) { // can't narrow type from 'any'
|
||||
if (obj6 instanceof C) {
|
||||
obj6.foo;
|
||||
obj6.bar1;
|
||||
obj6.bar2;
|
||||
|
@ -86,7 +86,7 @@ if (obj7 instanceof D) { // narrowed to D.
|
|||
}
|
||||
|
||||
var obj8: any;
|
||||
if (obj8 instanceof D) { // can't narrow type from 'any'
|
||||
if (obj8 instanceof D) {
|
||||
obj8.foo;
|
||||
obj8.bar;
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ if (obj9 instanceof E) { // narrowed to E1 | E2
|
|||
}
|
||||
|
||||
var obj10: any;
|
||||
if (obj10 instanceof E) { // can't narrow type from 'any'
|
||||
if (obj10 instanceof E) {
|
||||
obj10.foo;
|
||||
obj10.bar1;
|
||||
obj10.bar2;
|
||||
|
@ -136,7 +136,7 @@ if (obj11 instanceof F) { // can't type narrowing, construct signature returns a
|
|||
}
|
||||
|
||||
var obj12: any;
|
||||
if (obj12 instanceof F) { // can't narrow type from 'any'
|
||||
if (obj12 instanceof F) {
|
||||
obj12.foo;
|
||||
obj12.bar;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ if (obj13 instanceof G) { // narrowed to G1. G1 is return type of prototype prop
|
|||
}
|
||||
|
||||
var obj14: any;
|
||||
if (obj14 instanceof G) { // can't narrow type from 'any'
|
||||
if (obj14 instanceof G) {
|
||||
obj14.foo1;
|
||||
obj14.foo2;
|
||||
}
|
||||
|
@ -183,7 +183,19 @@ if (obj15 instanceof H) { // narrowed to H.
|
|||
}
|
||||
|
||||
var obj16: any;
|
||||
if (obj16 instanceof H) { // can't narrow type from 'any'
|
||||
if (obj16 instanceof H) {
|
||||
obj16.foo1;
|
||||
obj16.foo2;
|
||||
}
|
||||
|
||||
var obj17: any;
|
||||
if (obj17 instanceof Object) { // can't narrow type from 'any' to 'Object'
|
||||
obj17.foo1;
|
||||
obj17.foo2;
|
||||
}
|
||||
|
||||
var obj18: any;
|
||||
if (obj18 instanceof Function) { // can't narrow type from 'any' to 'Function'
|
||||
obj18.foo1;
|
||||
obj18.foo2;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
declare function isFooError(x: any): x is { type: 'foo'; dontPanic(); };
|
||||
|
||||
function tryCatch() {
|
||||
try {
|
||||
// do stuff...
|
||||
}
|
||||
catch (err) { // err is implicitly 'any' and cannot be annotated
|
||||
|
||||
if (isFooError(err)) {
|
||||
err.dontPanic(); // OK
|
||||
err.doPanic(); // ERROR: Property 'doPanic' does not exist on type '{...}'
|
||||
}
|
||||
|
||||
else if (err instanceof Error) {
|
||||
err.message;
|
||||
err.massage; // ERROR: Property 'massage' does not exist on type 'Error'
|
||||
}
|
||||
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
declare var x: any;
|
||||
|
||||
if (x instanceof Function) { // 'any' is not narrowed when target type is 'Function'
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
|
||||
if (x instanceof Object) { // 'any' is not narrowed when target type is 'Object'
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (x instanceof Error) { // 'any' is narrowed to types other than 'Function'/'Object'
|
||||
x.message;
|
||||
x.mesage;
|
||||
}
|
||||
|
||||
if (x instanceof Date) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
declare var x: any;
|
||||
declare function isFunction(x): x is Function;
|
||||
declare function isObject(x): x is Object;
|
||||
declare function isAnything(x): x is {};
|
||||
declare function isError(x): x is Error;
|
||||
declare function isDate(x): x is Date;
|
||||
|
||||
|
||||
if (isFunction(x)) { // 'any' is not narrowed when target type is 'Function'
|
||||
x();
|
||||
x(1, 2, 3);
|
||||
x("hello!");
|
||||
x.prop;
|
||||
}
|
||||
|
||||
if (isObject(x)) { // 'any' is not narrowed when target type is 'Object'
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (isAnything(x)) { // 'any' is narrowed to types other than 'Function'/'Object' (including {})
|
||||
x.method();
|
||||
x();
|
||||
}
|
||||
|
||||
if (isError(x)) {
|
||||
x.message;
|
||||
x.mesage;
|
||||
}
|
||||
|
||||
if (isDate(x)) {
|
||||
x.getDate();
|
||||
x.getHuors();
|
||||
}
|
Loading…
Reference in a new issue