Merge pull request #7140 from Microsoft/strictNullChecks

Non-nullable types
This commit is contained in:
Anders Hejlsberg 2016-03-21 16:52:43 -07:00
commit 3853bb86d0
39 changed files with 1267 additions and 986 deletions

File diff suppressed because it is too large Load Diff

View File

@ -331,6 +331,11 @@ namespace ts {
name: "noImplicitUseStrict",
type: "boolean",
description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output
},
{
name: "strictNullChecks",
type: "boolean",
description: Diagnostics.Enable_strict_null_checks
}
];

View File

@ -242,8 +242,14 @@ namespace ts {
const count = array.length;
if (count > 0) {
let pos = 0;
let result = arguments.length <= 2 ? array[pos] : initial;
pos++;
let result: T | U;
if (arguments.length <= 2) {
result = array[pos];
pos++;
}
else {
result = initial;
}
while (pos < count) {
result = f(<U>result, array[pos]);
pos++;
@ -260,8 +266,14 @@ namespace ts {
if (array) {
let pos = array.length - 1;
if (pos >= 0) {
let result = arguments.length <= 2 ? array[pos] : initial;
pos--;
let result: T | U;
if (arguments.length <= 2) {
result = array[pos];
pos--;
}
else {
result = initial;
}
while (pos >= 0) {
result = f(<U>result, array[pos]);
pos--;

View File

@ -367,6 +367,8 @@ namespace ts {
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.ThisType:
case SyntaxKind.StringLiteralType:
return writeTextOfNode(currentText, type);

View File

@ -1103,6 +1103,10 @@
"category": "Error",
"code": 2365
},
"Function lacks ending return statement and return type does not include 'undefined'.": {
"category": "Error",
"code": 2366
},
"Type parameter name cannot be '{0}'": {
"category": "Error",
"code": 2368
@ -1423,6 +1427,10 @@
"category": "Error",
"code": 2453
},
"Variable '{0}' is used before being assigned.": {
"category": "Error",
"code": 2454
},
"Type argument candidate '{1}' is not a valid type argument because it is not a supertype of candidate '{0}'.": {
"category": "Error",
"code": 2455
@ -1719,6 +1727,10 @@
"category": "Error",
"code": 2530
},
"Object is possibly 'null' or 'undefined'.": {
"category": "Error",
"code": 2531
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@ -2604,6 +2616,11 @@
"category": "Message",
"code": 6112
},
"Enable strict null checks.": {
"category": "Message",
"code": 6113
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005

View File

@ -1533,6 +1533,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
case SyntaxKind.JsxSpreadAttribute:
case SyntaxKind.JsxExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.NonNullExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
@ -2077,8 +2078,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
// When diagnosing whether the expression needs parentheses, the decision should be based
// on the innermost expression in a chain of nested type assertions.
while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) {
expr = (<AssertionExpression>expr).expression;
while (expr.kind === SyntaxKind.TypeAssertionExpression ||
expr.kind === SyntaxKind.AsExpression ||
expr.kind === SyntaxKind.NonNullExpression) {
expr = (<AssertionExpression | NonNullExpression>expr).expression;
}
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
@ -2343,8 +2346,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
function skipParentheses(node: Expression): Expression {
while (node.kind === SyntaxKind.ParenthesizedExpression || node.kind === SyntaxKind.TypeAssertionExpression || node.kind === SyntaxKind.AsExpression) {
node = (<ParenthesizedExpression | AssertionExpression>node).expression;
while (node.kind === SyntaxKind.ParenthesizedExpression ||
node.kind === SyntaxKind.TypeAssertionExpression ||
node.kind === SyntaxKind.AsExpression ||
node.kind === SyntaxKind.NonNullExpression) {
node = (<ParenthesizedExpression | AssertionExpression | NonNullExpression>node).expression;
}
return node;
}
@ -2518,13 +2524,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// not the user. If we didn't want them, the emitter would not have put them
// there.
if (!nodeIsSynthesized(node) && node.parent.kind !== SyntaxKind.ArrowFunction) {
if (node.expression.kind === SyntaxKind.TypeAssertionExpression || node.expression.kind === SyntaxKind.AsExpression) {
let operand = (<TypeAssertion>node.expression).expression;
if (node.expression.kind === SyntaxKind.TypeAssertionExpression ||
node.expression.kind === SyntaxKind.AsExpression ||
node.expression.kind === SyntaxKind.NonNullExpression) {
let operand = (<TypeAssertion | NonNullExpression>node.expression).expression;
// Make sure we consider all nested cast expressions, e.g.:
// (<any><number><any>-A).x;
while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) {
operand = (<TypeAssertion>operand).expression;
while (operand.kind === SyntaxKind.TypeAssertionExpression ||
operand.kind === SyntaxKind.AsExpression ||
operand.kind === SyntaxKind.NonNullExpression) {
operand = (<TypeAssertion | NonNullExpression>operand).expression;
}
// We have an expression of the form: (<Type>SubExpr)
@ -7928,9 +7938,9 @@ const _super = (function (geti, seti) {
case SyntaxKind.TaggedTemplateExpression:
return emitTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.TypeAssertionExpression:
return emit((<TypeAssertion>node).expression);
case SyntaxKind.AsExpression:
return emit((<AsExpression>node).expression);
case SyntaxKind.NonNullExpression:
return emit((<AssertionExpression | NonNullExpression>node).expression);
case SyntaxKind.ParenthesizedExpression:
return emitParenExpression(<ParenthesizedExpression>node);
case SyntaxKind.FunctionDeclaration:

View File

@ -177,6 +177,8 @@ namespace ts {
case SyntaxKind.AsExpression:
return visitNode(cbNode, (<AsExpression>node).expression) ||
visitNode(cbNode, (<AsExpression>node).type);
case SyntaxKind.NonNullExpression:
return visitNode(cbNode, (<NonNullExpression>node).expression);
case SyntaxKind.ConditionalExpression:
return visitNode(cbNode, (<ConditionalExpression>node).condition) ||
visitNode(cbNode, (<ConditionalExpression>node).questionToken) ||
@ -2361,12 +2363,14 @@ namespace ts {
case SyntaxKind.NumberKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.UndefinedKeyword:
// If these are followed by a dot, then parse these out as a dotted type reference instead.
const node = tryParse(parseKeywordAndNoDot);
return node || parseTypeReference();
case SyntaxKind.StringLiteral:
return parseStringLiteralTypeNode();
case SyntaxKind.VoidKeyword:
case SyntaxKind.NullKeyword:
return parseTokenNode<TypeNode>();
case SyntaxKind.ThisKeyword: {
const thisKeyword = parseThisTypeNode();
@ -2398,6 +2402,8 @@ namespace ts {
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.UndefinedKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.ThisKeyword:
case SyntaxKind.TypeOfKeyword:
case SyntaxKind.OpenBraceToken:
@ -3724,6 +3730,14 @@ namespace ts {
continue;
}
if (token === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
nextToken();
const nonNullExpression = <NonNullExpression>createNode(SyntaxKind.NonNullExpression, expression.pos);
nonNullExpression.expression = expression;
expression = finishNode(nonNullExpression);
continue;
}
// when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName
if (!inDecoratorContext() && parseOptional(SyntaxKind.OpenBracketToken)) {
const indexedAccess = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, expression.pos);

View File

@ -114,6 +114,7 @@ namespace ts {
"try": SyntaxKind.TryKeyword,
"type": SyntaxKind.TypeKeyword,
"typeof": SyntaxKind.TypeOfKeyword,
"undefined": SyntaxKind.UndefinedKeyword,
"var": SyntaxKind.VarKeyword,
"void": SyntaxKind.VoidKeyword,
"while": SyntaxKind.WhileKeyword,

View File

@ -171,6 +171,7 @@ namespace ts {
StringKeyword,
SymbolKeyword,
TypeKeyword,
UndefinedKeyword,
FromKeyword,
GlobalKeyword,
OfKeyword, // LastKeyword and LastToken
@ -240,6 +241,7 @@ namespace ts {
OmittedExpression,
ExpressionWithTypeArguments,
AsExpression,
NonNullExpression,
// Misc
TemplateSpan,
@ -475,6 +477,11 @@ namespace ts {
originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later
}
// Transient identifier node (marked by id === -1)
export interface TransientIdentifier extends Identifier {
resolvedSymbol: Symbol;
}
// @kind(SyntaxKind.QualifiedName)
export interface QualifiedName extends Node {
// Must have same layout as PropertyAccess
@ -968,6 +975,8 @@ namespace ts {
name: Identifier;
}
export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression;
// @kind(SyntaxKind.ElementAccessExpression)
export interface ElementAccessExpression extends MemberExpression {
expression: LeftHandSideExpression;
@ -1012,6 +1021,11 @@ namespace ts {
export type AssertionExpression = TypeAssertion | AsExpression;
// @kind(SyntaxKind.NonNullExpression)
export interface NonNullExpression extends LeftHandSideExpression {
expression: Expression;
}
/// A JSX expression of the form <TagName attrs>...</TagName>
// @kind(SyntaxKind.JsxElement)
export interface JsxElement extends PrimaryExpression {
@ -2029,7 +2043,9 @@ namespace ts {
exportsChecked?: boolean; // True if exports of external module have been checked
isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration
bindingElement?: BindingElement; // Binding element associated with property symbol
exportsSomeValue?: boolean; // true if module exports some value (not just types)
exportsSomeValue?: boolean; // True if module exports some value (not just types)
firstAssignmentChecked?: boolean; // True if first assignment node has been computed
firstAssignment?: Node; // First assignment node (undefined if no assignments)
}
/* @internal */
@ -2072,7 +2088,7 @@ namespace ts {
isVisible?: boolean; // Is this node visible
generatedName?: string; // Generated name for module, enum, or import declaration
generatedNames?: Map<string>; // Generated names table for source file
assignmentChecks?: Map<boolean>; // Cache of assignment checks
assignmentMap?: Map<boolean>; // Cached map of references assigned within this node
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
importOnRightSide?: Symbol; // for import declarations - import that appear on the right side
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
@ -2106,7 +2122,7 @@ namespace ts {
/* @internal */
FreshObjectLiteral = 0x00100000, // Fresh object literal type
/* @internal */
ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type
ContainsUndefinedOrNull = 0x00200000, // Type is or contains undefined or null type
/* @internal */
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
/* @internal */
@ -2115,6 +2131,8 @@ namespace ts {
ThisType = 0x02000000, // This type
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
/* @internal */
Nullable = Undefined | Null,
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
/* @internal */
@ -2439,6 +2457,7 @@ namespace ts {
allowSyntheticDefaultImports?: boolean;
allowJs?: boolean;
noImplicitUseStrict?: boolean;
strictNullChecks?: boolean;
lib?: string[];
/* @internal */ stripInternal?: boolean;

View File

@ -511,6 +511,7 @@ namespace ts {
case SyntaxKind.StringKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.UndefinedKeyword:
return true;
case SyntaxKind.VoidKeyword:
return node.parent.kind !== SyntaxKind.VoidExpression;
@ -968,6 +969,7 @@ namespace ts {
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.AsExpression:
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.NonNullExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ClassExpression:
@ -2406,6 +2408,7 @@ namespace ts {
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression:
case SyntaxKind.NonNullExpression:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.TaggedTemplateExpression:

View File

@ -19,7 +19,7 @@ var a = [undefined, undefined];
var b = [[], [null, null]]; // any[][]
>b : any[][]
>[[], [null, null]] : null[][]
>[[], [null, null]] : undefined[][]
>[] : undefined[]
>[null, null] : null[]
>null : null

View File

@ -1,7 +1,3 @@
tests/cases/conformance/types/tuple/castingTuple.ts(13,23): error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other.
Property '2' is missing in type '[number, string]'.
tests/cases/conformance/types/tuple/castingTuple.ts(16,21): error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other.
Property '2' is missing in type '[C, D]'.
tests/cases/conformance/types/tuple/castingTuple.ts(28,10): error TS2352: Neither type '[number, string]' nor type '[number, number]' is assignable to the other.
Types of property '1' are incompatible.
Type 'string' is not assignable to type 'number'.
@ -10,15 +6,10 @@ tests/cases/conformance/types/tuple/castingTuple.ts(29,10): error TS2352: Neithe
Type 'C' is not assignable to type 'A'.
Property 'a' is missing in type 'C'.
tests/cases/conformance/types/tuple/castingTuple.ts(30,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'.
tests/cases/conformance/types/tuple/castingTuple.ts(30,14): error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other.
Types of property 'pop' are incompatible.
Type '() => number | string' is not assignable to type '() => number'.
Type 'number | string' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot find name 't4'.
==== tests/cases/conformance/types/tuple/castingTuple.ts (7 errors) ====
==== tests/cases/conformance/types/tuple/castingTuple.ts (4 errors) ====
interface I { }
class A { a = 10; }
class C implements I { c };
@ -32,15 +23,9 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot
var numStrTuple: [number, string] = [5, "foo"];
var emptyObjTuple = <[{}, {}]>numStrTuple;
var numStrBoolTuple = <[number, string, boolean]>numStrTuple;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type '[number, string]' nor type '[number, string, boolean]' is assignable to the other.
!!! error TS2352: Property '2' is missing in type '[number, string]'.
var classCDTuple: [C, D] = [new C(), new D()];
var interfaceIITuple = <[I, I]>classCDTuple;
var classCDATuple = <[C, D, A]>classCDTuple;
~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type '[C, D]' nor type '[C, D, A]' is assignable to the other.
!!! error TS2352: Property '2' is missing in type '[C, D]'.
var eleFromCDA1 = classCDATuple[2]; // A
var eleFromCDA2 = classCDATuple[5]; // C | D | A
var t10: [E1, E2] = [E1.one, E2.one];
@ -66,12 +51,6 @@ tests/cases/conformance/types/tuple/castingTuple.ts(31,1): error TS2304: Cannot
var array1 = <number[]>numStrTuple;
~~~~~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'array1' must be of type '{}[]', but here has type 'number[]'.
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2352: Neither type '[number, string]' nor type 'number[]' is assignable to the other.
!!! error TS2352: Types of property 'pop' are incompatible.
!!! error TS2352: Type '() => number | string' is not assignable to type '() => number'.
!!! error TS2352: Type 'number | string' is not assignable to type 'number'.
!!! error TS2352: Type 'string' is not assignable to type 'number'.
t4[2] = 10;
~~
!!! error TS2304: Cannot find name 't4'.

View File

@ -623,7 +623,7 @@ var rj8 = a8 && undefined;
var rj9 = null && undefined;
>rj9 : any
>null && undefined : undefined
>null && undefined : null
>null : null
>undefined : undefined

View File

@ -1,19 +1,13 @@
tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(5,17): error TS1005: ',' expected.
tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(5,18): error TS1109: Expression expected.
tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(8,16): error TS2365: Operator '+' cannot be applied to types 'boolean' and 'number'.
tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts(11,16): error TS1109: Expression expected.
==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts (4 errors) ====
==== tests/cases/conformance/expressions/unaryOperators/logicalNotOperator/logicalNotOperatorInvalidOperations.ts (2 errors) ====
// Unary operator !
var b: number;
// operand before !
var BOOLEAN1 = b!; //expect error
~
!!! error TS1005: ',' expected.
~
!!! error TS1109: Expression expected.
// miss parentheses
var BOOLEAN2 = !b + b;

View File

@ -15,8 +15,7 @@ var BOOLEAN3 =!;
// Unary operator !
var b;
// operand before !
var BOOLEAN1 = b;
!; //expect error
var BOOLEAN1 = b; //expect error
// miss parentheses
var BOOLEAN2 = !b + b;
// miss an operand

View File

@ -7,9 +7,12 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperato
tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(13,11): error TS2356: An arithmetic operand must be of type 'any', 'number' or an enum type.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(14,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(15,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(16,9): error TS2365: Operator '<' cannot be applied to types '"ABC"' and '"XYZ"'.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(17,9): error TS2365: Operator '===' cannot be applied to types '"ABC"' and '"XYZ"'.
tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts(18,9): error TS2365: Operator '!=' cannot be applied to types '"ABC"' and '"XYZ"'.
==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts (9 errors) ====
==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperators02.ts (12 errors) ====
let abc: "ABC" = "ABC";
let xyz: "XYZ" = "XYZ";
@ -44,5 +47,11 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesWithVariousOperato
~~~~~~~~~~~~~~~~
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
let j = abc < xyz;
~~~~~~~~~
!!! error TS2365: Operator '<' cannot be applied to types '"ABC"' and '"XYZ"'.
let k = abc === xyz;
let l = abc != xyz;
~~~~~~~~~~~
!!! error TS2365: Operator '===' cannot be applied to types '"ABC"' and '"XYZ"'.
let l = abc != xyz;
~~~~~~~~~~
!!! error TS2365: Operator '!=' cannot be applied to types '"ABC"' and '"XYZ"'.

View File

@ -174,9 +174,9 @@ if (holder2.a.isLeader()) {
>isLeader : () => this is LeadGuard
holder2.a;
>holder2.a : RoyalGuard
>holder2.a : LeadGuard
>holder2 : { a: RoyalGuard; }
>a : RoyalGuard
>a : LeadGuard
}
else {
holder2.a;

View File

@ -0,0 +1,30 @@
tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts(6,17): error TS2322: Type 'string | number' is not assignable to type 'string'.
Type 'number' is not assignable to type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts(13,17): error TS2322: Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts (2 errors) ====
let x: string | number;
if (typeof x === "string") {
let n = class {
constructor() {
let y: string = x;
~
!!! error TS2322: Type 'string | number' is not assignable to type 'string'.
!!! error TS2322: Type 'number' is not assignable to type 'string'.
}
}
}
else {
let m = class {
constructor() {
let y: number = x;
~
!!! error TS2322: Type 'string | number' is not assignable to type 'number'.
!!! error TS2322: Type 'string' is not assignable to type 'number'.
}
}
}

View File

@ -1,29 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts ===
let x: string | number;
>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3))
let n = class {
>n : Symbol(n, Decl(typeGuardInClass.ts, 3, 7))
constructor() {
let y: string = x;
>y : Symbol(y, Decl(typeGuardInClass.ts, 5, 15))
>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3))
}
}
}
else {
let m = class {
>m : Symbol(m, Decl(typeGuardInClass.ts, 10, 7))
constructor() {
let y: number = x;
>y : Symbol(y, Decl(typeGuardInClass.ts, 12, 15))
>x : Symbol(x, Decl(typeGuardInClass.ts, 0, 3))
}
}
}

View File

@ -1,34 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardInClass.ts ===
let x: string | number;
>x : string | number
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : string | number
>"string" : string
let n = class {
>n : typeof (Anonymous class)
>class { constructor() { let y: string = x; } } : typeof (Anonymous class)
constructor() {
let y: string = x;
>y : string
>x : string
}
}
}
else {
let m = class {
>m : typeof (Anonymous class)
>class { constructor() { let y: number = x; } } : typeof (Anonymous class)
constructor() {
let y: number = x;
>y : number
>x : number
}
}
}

View File

@ -0,0 +1,50 @@
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(13,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'string', but here has type 'number'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(20,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'boolean', but here has type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(27,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'number', but here has type 'boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(34,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'C', but here has type 'string'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts (4 errors) ====
class C { private p: string };
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrC: string | C;
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'string', but here has type 'number'.
}
if (typeof strOrBool == "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'boolean', but here has type 'string'.
}
if (typeof numOrBool == "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'number', but here has type 'boolean'.
}
if (typeof strOrC == "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'C', but here has type 'string'.
}

View File

@ -1,70 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts ===
class C { private p: string };
>C : Symbol(C, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 0, 0))
>p : Symbol(C.p, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 0, 9))
var strOrNum: string | number;
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3))
var strOrBool: string | boolean;
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3))
var numOrBool: number | boolean
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3))
var strOrC: string | C;
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3))
>C : Symbol(C, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 0, 0))
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3))
var r1 = strOrNum; // string | number
>r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 12, 7))
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3))
}
else {
var r1 = strOrNum; // string | number
>r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 12, 7))
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 2, 3))
}
if (typeof strOrBool == "boolean") {
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3))
var r2 = strOrBool; // string | boolean
>r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 19, 7))
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3))
}
else {
var r2 = strOrBool; // string | boolean
>r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 19, 7))
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 3, 3))
}
if (typeof numOrBool == "number") {
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3))
var r3 = numOrBool; // number | boolean
>r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 26, 7))
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3))
}
else {
var r3 = numOrBool; // number | boolean
>r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 26, 7))
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 4, 3))
}
if (typeof strOrC == "Object") {
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3))
var r4 = strOrC; // string | C
>r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 33, 7))
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3))
}
else {
var r4 = strOrC; // string | C
>r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 33, 7))
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts, 5, 3))
}

View File

@ -1,82 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts ===
class C { private p: string };
>C : C
>p : string
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
// typeof x == s has not effect on typeguard
if (typeof strOrNum == "string") {
>typeof strOrNum == "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
>"string" : string
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
else {
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
if (typeof strOrBool == "boolean") {
>typeof strOrBool == "boolean" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
>"boolean" : string
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
else {
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
if (typeof numOrBool == "number") {
>typeof numOrBool == "number" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
>"number" : string
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
else {
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
if (typeof strOrC == "Object") {
>typeof strOrC == "Object" : boolean
>typeof strOrC : string
>strOrC : string | C
>"Object" : string
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}
else {
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}

View File

@ -0,0 +1,50 @@
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(13,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'number', but here has type 'string'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(20,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'string', but here has type 'boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(27,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'boolean', but here has type 'number'.
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(34,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'string', but here has type 'C'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts (4 errors) ====
class C { private p: string };
var strOrNum: string | number;
var strOrBool: string | boolean;
var numOrBool: number | boolean
var strOrC: string | C;
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
var r1 = strOrNum; // string | number
}
else {
var r1 = strOrNum; // string | number
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'number', but here has type 'string'.
}
if (typeof strOrBool != "boolean") {
var r2 = strOrBool; // string | boolean
}
else {
var r2 = strOrBool; // string | boolean
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'string', but here has type 'boolean'.
}
if (typeof numOrBool != "number") {
var r3 = numOrBool; // number | boolean
}
else {
var r3 = numOrBool; // number | boolean
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'boolean', but here has type 'number'.
}
if (typeof strOrC != "Object") {
var r4 = strOrC; // string | C
}
else {
var r4 = strOrC; // string | C
~~
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'string', but here has type 'C'.
}

View File

@ -1,70 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts ===
class C { private p: string };
>C : Symbol(C, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 0, 0))
>p : Symbol(C.p, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 0, 9))
var strOrNum: string | number;
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3))
var strOrBool: string | boolean;
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3))
var numOrBool: number | boolean
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3))
var strOrC: string | C;
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3))
>C : Symbol(C, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 0, 0))
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3))
var r1 = strOrNum; // string | number
>r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 12, 7))
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3))
}
else {
var r1 = strOrNum; // string | number
>r1 : Symbol(r1, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 9, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 12, 7))
>strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 2, 3))
}
if (typeof strOrBool != "boolean") {
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3))
var r2 = strOrBool; // string | boolean
>r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 19, 7))
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3))
}
else {
var r2 = strOrBool; // string | boolean
>r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 16, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 19, 7))
>strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 3, 3))
}
if (typeof numOrBool != "number") {
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3))
var r3 = numOrBool; // number | boolean
>r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 26, 7))
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3))
}
else {
var r3 = numOrBool; // number | boolean
>r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 23, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 26, 7))
>numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 4, 3))
}
if (typeof strOrC != "Object") {
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3))
var r4 = strOrC; // string | C
>r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 33, 7))
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3))
}
else {
var r4 = strOrC; // string | C
>r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 30, 7), Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 33, 7))
>strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfNotEqualHasNoEffect.ts, 5, 3))
}

View File

@ -1,82 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts ===
class C { private p: string };
>C : C
>p : string
var strOrNum: string | number;
>strOrNum : string | number
var strOrBool: string | boolean;
>strOrBool : string | boolean
var numOrBool: number | boolean
>numOrBool : number | boolean
var strOrC: string | C;
>strOrC : string | C
>C : C
// typeof x != s has not effect on typeguard
if (typeof strOrNum != "string") {
>typeof strOrNum != "string" : boolean
>typeof strOrNum : string
>strOrNum : string | number
>"string" : string
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
else {
var r1 = strOrNum; // string | number
>r1 : string | number
>strOrNum : string | number
}
if (typeof strOrBool != "boolean") {
>typeof strOrBool != "boolean" : boolean
>typeof strOrBool : string
>strOrBool : string | boolean
>"boolean" : string
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
else {
var r2 = strOrBool; // string | boolean
>r2 : string | boolean
>strOrBool : string | boolean
}
if (typeof numOrBool != "number") {
>typeof numOrBool != "number" : boolean
>typeof numOrBool : string
>numOrBool : number | boolean
>"number" : string
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
else {
var r3 = numOrBool; // number | boolean
>r3 : number | boolean
>numOrBool : number | boolean
}
if (typeof strOrC != "Object") {
>typeof strOrC != "Object" : boolean
>typeof strOrC : string
>strOrC : string | C
>"Object" : string
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}
else {
var r4 = strOrC; // string | C
>r4 : string | C
>strOrC : string | C
}

View File

@ -0,0 +1,52 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(21,20): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(21,24): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(32,23): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts(32,27): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
==== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts (4 errors) ====
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x: number | string) {
function f() {
x = 10;
}
if (typeof x === "string") {
f();
return x.length; // string
}
else {
return x++; // number
}
}
function foo2(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
var f = function () {
return x * x;
~
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
~
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
};
}
x = "hello";
f();
}
function foo3(x: number | string) {
if (typeof x === "string") {
return x.length; // string
}
else {
var f = () => x * x;
~
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
~
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
}
x = "hello";
f();
}

View File

@ -1,82 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts ===
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x: number | string) {
>foo : Symbol(foo, Decl(typeGuardsDefeat.ts, 0, 0))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13))
function f() {
>f : Symbol(f, Decl(typeGuardsDefeat.ts, 2, 34))
x = 10;
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13))
}
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13))
f();
>f : Symbol(f, Decl(typeGuardsDefeat.ts, 2, 34))
return x.length; // string
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
else {
return x++; // number
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 2, 13))
}
}
function foo2(x: number | string) {
>foo2 : Symbol(foo2, Decl(typeGuardsDefeat.ts, 13, 1))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14))
return x.length; // string
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
else {
var f = function () {
>f : Symbol(f, Decl(typeGuardsDefeat.ts, 19, 11))
return x * x;
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14))
};
}
x = "hello";
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 14, 14))
f();
>f : Symbol(f, Decl(typeGuardsDefeat.ts, 19, 11))
}
function foo3(x: number | string) {
>foo3 : Symbol(foo3, Decl(typeGuardsDefeat.ts, 25, 1))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14))
if (typeof x === "string") {
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14))
return x.length; // string
>x.length : Symbol(String.length, Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14))
>length : Symbol(String.length, Decl(lib.d.ts, --, --))
}
else {
var f = () => x * x;
>f : Symbol(f, Decl(typeGuardsDefeat.ts, 31, 11))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14))
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14))
}
x = "hello";
>x : Symbol(x, Decl(typeGuardsDefeat.ts, 26, 14))
f();
>f : Symbol(f, Decl(typeGuardsDefeat.ts, 31, 11))
}

View File

@ -1,105 +0,0 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsDefeat.ts ===
// Also note that it is possible to defeat a type guard by calling a function that changes the
// type of the guarded variable.
function foo(x: number | string) {
>foo : (x: number | string) => number
>x : number | string
function f() {
>f : () => void
x = 10;
>x = 10 : number
>x : number | string
>10 : number
}
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
f();
>f() : void
>f : () => void
return x.length; // string
>x.length : number
>x : string
>length : number
}
else {
return x++; // number
>x++ : number
>x : number
}
}
function foo2(x: number | string) {
>foo2 : (x: number | string) => number
>x : number | string
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
return x.length; // string
>x.length : number
>x : string
>length : number
}
else {
var f = function () {
>f : () => number
>function () { return x * x; } : () => number
return x * x;
>x * x : number
>x : number
>x : number
};
}
x = "hello";
>x = "hello" : string
>x : number | string
>"hello" : string
f();
>f() : number
>f : () => number
}
function foo3(x: number | string) {
>foo3 : (x: number | string) => number
>x : number | string
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : string
>x : number | string
>"string" : string
return x.length; // string
>x.length : number
>x : string
>length : number
}
else {
var f = () => x * x;
>f : () => number
>() => x * x : () => number
>x * x : number
>x : number
>x : number
}
x = "hello";
>x = "hello" : string
>x : number | string
>"hello" : string
f();
>f() : number
>f : () => number
}

View File

@ -44,13 +44,13 @@ if (typeof var2 === "string") {
// export makes the var property and not variable
strOrNum = var2; // string | number
>strOrNum = var2 : string | number
>strOrNum = var2 : string
>strOrNum : string | number
>var2 : string | number
>var2 : string
}
else {
strOrNum = var2; // number | string
>strOrNum = var2 : string | number
>strOrNum = var2 : number
>strOrNum : string | number
>var2 : string | number
>var2 : number
}

View File

@ -27,9 +27,9 @@ function foo(x: number | string | boolean) {
>toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
: x.toString(); // number
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 2, 13))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
} ();
}
@ -60,9 +60,9 @@ function foo2(x: number | string | boolean) {
>toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
: x.toString(); // number
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 12, 14))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
} (x); // x here is narrowed to number | boolean
>x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 12, 14))
@ -91,9 +91,9 @@ function foo3(x: number | string | boolean) {
>toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
: x.toString(); // number
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 22, 14))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
})();
}
@ -123,9 +123,9 @@ function foo4(x: number | string | boolean) {
>toString : Symbol(Object.toString, Decl(lib.d.ts, --, --))
: x.toString(); // number
>x.toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>x.toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 32, 14))
>toString : Symbol(Number.toString, Decl(lib.d.ts, --, --))
>toString : Symbol(toString, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
})(x); // x here is narrowed to number | boolean
>x : Symbol(x, Decl(typeGuardsInFunctionAndModuleBlock.ts, 32, 14))

View File

@ -21,14 +21,14 @@ function foo(x: number | string | boolean) {
>f : () => string
var b = x; // number | boolean
>b : number | boolean
>x : number | boolean
>b : number | string | boolean
>x : number | string | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
>x : number | string | boolean
>"boolean" : string
? x.toString() // boolean
@ -40,7 +40,7 @@ function foo(x: number | string | boolean) {
: x.toString(); // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>x : number | string
>toString : (radix?: number) => string
} ();
@ -66,14 +66,14 @@ function foo2(x: number | string | boolean) {
>a : number | boolean
var b = x; // new scope - number | boolean
>b : number | boolean
>x : number | boolean
>b : number | string | boolean
>x : number | string | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
>x : number | string | boolean
>"boolean" : string
? x.toString() // boolean
@ -85,7 +85,7 @@ function foo2(x: number | string | boolean) {
: x.toString(); // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>x : number | string
>toString : (radix?: number) => string
} (x); // x here is narrowed to number | boolean
@ -111,14 +111,14 @@ function foo3(x: number | string | boolean) {
>() => { var b = x; // new scope - number | boolean return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number } : () => string
var b = x; // new scope - number | boolean
>b : number | boolean
>x : number | boolean
>b : number | string | boolean
>x : number | string | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
>x : number | string | boolean
>"boolean" : string
? x.toString() // boolean
@ -130,7 +130,7 @@ function foo3(x: number | string | boolean) {
: x.toString(); // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>x : number | string
>toString : (radix?: number) => string
})();
@ -156,14 +156,14 @@ function foo4(x: number | string | boolean) {
>a : number | boolean
var b = x; // new scope - number | boolean
>b : number | boolean
>x : number | boolean
>b : number | string | boolean
>x : number | string | boolean
return typeof x === "boolean"
>typeof x === "boolean" ? x.toString() // boolean : x.toString() : string
>typeof x === "boolean" : boolean
>typeof x : string
>x : number | boolean
>x : number | string | boolean
>"boolean" : string
? x.toString() // boolean
@ -175,7 +175,7 @@ function foo4(x: number | string | boolean) {
: x.toString(); // number
>x.toString() : string
>x.toString : (radix?: number) => string
>x : number
>x : number | string
>toString : (radix?: number) => string
})(x); // x here is narrowed to number | boolean
@ -200,8 +200,8 @@ function foo5(x: number | string | boolean) {
>foo : () => void
var z = x; // string
>z : string
>x : string
>z : number | string | boolean
>x : number | string | boolean
}
}
}

View File

@ -64,15 +64,15 @@ module m1 {
>"string" : string
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum = var3 : string
>strOrNum : string | number
>var3 : string | number
>var3 : string
}
else {
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum = var3 : number
>strOrNum : string | number
>var3 : string | number
>var3 : number
}
}
// local module
@ -116,14 +116,14 @@ module m2 {
// exported variable from outer the module
strOrNum = typeof var3 === "string" && var3; // string | number
>strOrNum = typeof var3 === "string" && var3 : string | number
>strOrNum = typeof var3 === "string" && var3 : string
>strOrNum : string | number
>typeof var3 === "string" && var3 : string | number
>typeof var3 === "string" && var3 : string
>typeof var3 === "string" : boolean
>typeof var3 : string
>var3 : string | number
>"string" : string
>var3 : string | number
>var3 : string
// variables in module declaration
var var4: string | number;
@ -160,15 +160,15 @@ module m2 {
>"string" : string
strOrNum = var5; // string | number
>strOrNum = var5 : string | number
>strOrNum = var5 : string
>strOrNum : string | number
>var5 : string | number
>var5 : string
}
else {
strOrNum = var5; // string | number
>strOrNum = var5 : string | number
>strOrNum = var5 : number
>strOrNum : string | number
>var5 : string | number
>var5 : number
}
}
}
@ -225,15 +225,15 @@ module m3.m4 {
>"string" : string
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum = var3 : string
>strOrNum : string | number
>var3 : string | number
>var3 : string
}
else {
strOrNum = var3; // string | number
>strOrNum = var3 : string | number
>strOrNum = var3 : number
>strOrNum : string | number
>var3 : string | number
>var3 : number
}
}

View File

@ -29,32 +29,32 @@ class C1 {
>method : () => void
strOrNum = typeof this.pp1 === "string" && this.pp1; // string | number
>strOrNum = typeof this.pp1 === "string" && this.pp1 : string | number
>strOrNum = typeof this.pp1 === "string" && this.pp1 : string
>strOrNum : string | number
>typeof this.pp1 === "string" && this.pp1 : string | number
>typeof this.pp1 === "string" && this.pp1 : string
>typeof this.pp1 === "string" : boolean
>typeof this.pp1 : string
>this.pp1 : string | number
>this : this
>pp1 : string | number
>"string" : string
>this.pp1 : string | number
>this.pp1 : string
>this : this
>pp1 : string | number
>pp1 : string
strOrNum = typeof this.pp2 === "string" && this.pp2; // string | number
>strOrNum = typeof this.pp2 === "string" && this.pp2 : string | number
>strOrNum = typeof this.pp2 === "string" && this.pp2 : string
>strOrNum : string | number
>typeof this.pp2 === "string" && this.pp2 : string | number
>typeof this.pp2 === "string" && this.pp2 : string
>typeof this.pp2 === "string" : boolean
>typeof this.pp2 : string
>this.pp2 : string | number
>this : this
>pp2 : string | number
>"string" : string
>this.pp2 : string | number
>this.pp2 : string
>this : this
>pp2 : string | number
>pp2 : string
strOrNum = typeof this.pp3 === "string" && this.pp3; // string | number
>strOrNum = typeof this.pp3 === "string" && this.pp3 : string | number
@ -76,18 +76,18 @@ var c1: C1;
>C1 : C1
strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number
>strOrNum = typeof c1.pp2 === "string" && c1.pp2 : string | number
>strOrNum = typeof c1.pp2 === "string" && c1.pp2 : string
>strOrNum : string | number
>typeof c1.pp2 === "string" && c1.pp2 : string | number
>typeof c1.pp2 === "string" && c1.pp2 : string
>typeof c1.pp2 === "string" : boolean
>typeof c1.pp2 : string
>c1.pp2 : string | number
>c1 : C1
>pp2 : string | number
>"string" : string
>c1.pp2 : string | number
>c1.pp2 : string
>c1 : C1
>pp2 : string | number
>pp2 : string
strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number
>strOrNum = typeof c1.pp3 === "string" && c1.pp3 : string | number
@ -111,16 +111,16 @@ var obj1: {
};
strOrNum = typeof obj1.x === "string" && obj1.x; // string | number
>strOrNum = typeof obj1.x === "string" && obj1.x : string | number
>strOrNum = typeof obj1.x === "string" && obj1.x : string
>strOrNum : string | number
>typeof obj1.x === "string" && obj1.x : string | number
>typeof obj1.x === "string" && obj1.x : string
>typeof obj1.x === "string" : boolean
>typeof obj1.x : string
>obj1.x : string | number
>obj1 : { x: string | number; }
>x : string | number
>"string" : string
>obj1.x : string | number
>obj1.x : string
>obj1 : { x: string | number; }
>x : string | number
>x : string

View File

@ -1,37 +0,0 @@
tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts(14,70): error TS2339: Property 'join' does not exist on type 'string | string[]'.
tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts(26,44): error TS2339: Property 'toLowerCase' does not exist on type 'number | string'.
==== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts (2 errors) ====
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// Note that the class's property must be copied to a local variable for
// the type guard to have an effect
class D {
data: string | string[];
getData() {
var data = this.data;
return typeof data === "string" ? data : data.join(" ");
}
getData1() {
return typeof this.data === "string" ? this.data : this.data.join(" ");
~~~~
!!! error TS2339: Property 'join' does not exist on type 'string | string[]'.
}
}
var o: {
prop1: number|string;
prop2: boolean|string;
} = {
prop1: "string" ,
prop2: true
}
if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {}
~~~~~~~~~~~
!!! error TS2339: Property 'toLowerCase' does not exist on type 'number | string'.
var prop1 = o.prop1;
if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { }

View File

@ -0,0 +1,86 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// Note that the class's property must be copied to a local variable for
// the type guard to have an effect
class D {
>D : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0))
data: string | string[];
>data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
getData() {
>getData : Symbol(D.getData, Decl(typeGuardsOnClassProperty.ts, 6, 28))
var data = this.data;
>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11))
>this.data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0))
>data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
return typeof data === "string" ? data : data.join(" ");
>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11))
>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11))
>data.join : Symbol(Array.join, Decl(lib.d.ts, --, --))
>data : Symbol(data, Decl(typeGuardsOnClassProperty.ts, 8, 11))
>join : Symbol(Array.join, Decl(lib.d.ts, --, --))
}
getData1() {
>getData1 : Symbol(D.getData1, Decl(typeGuardsOnClassProperty.ts, 10, 5))
return typeof this.data === "string" ? this.data : this.data.join(" ");
>this.data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0))
>data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>this.data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0))
>data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>this.data.join : Symbol(Array.join, Decl(lib.d.ts, --, --))
>this.data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>this : Symbol(D, Decl(typeGuardsOnClassProperty.ts, 0, 0))
>data : Symbol(D.data, Decl(typeGuardsOnClassProperty.ts, 5, 9))
>join : Symbol(Array.join, Decl(lib.d.ts, --, --))
}
}
var o: {
>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3))
prop1: number|string;
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
prop2: boolean|string;
>prop2 : Symbol(prop2, Decl(typeGuardsOnClassProperty.ts, 18, 25))
} = {
prop1: "string" ,
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 20, 5))
prop2: true
>prop2 : Symbol(prop2, Decl(typeGuardsOnClassProperty.ts, 21, 25))
}
if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {}
>o.prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3))
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
>o.prop1.toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
>o.prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3))
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.d.ts, --, --))
var prop1 = o.prop1;
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 26, 3))
>o.prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
>o : Symbol(o, Decl(typeGuardsOnClassProperty.ts, 17, 3))
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 17, 8))
if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { }
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 26, 3))
>prop1.toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.d.ts, --, --))
>prop1 : Symbol(prop1, Decl(typeGuardsOnClassProperty.ts, 26, 3))
>toLocaleLowerCase : Symbol(String.toLocaleLowerCase, Decl(lib.d.ts, --, --))

View File

@ -0,0 +1,112 @@
=== tests/cases/conformance/expressions/typeGuards/typeGuardsOnClassProperty.ts ===
// Note that type guards affect types of variables and parameters only and
// have no effect on members of objects such as properties.
// Note that the class's property must be copied to a local variable for
// the type guard to have an effect
class D {
>D : D
data: string | string[];
>data : string | string[]
getData() {
>getData : () => string
var data = this.data;
>data : string | string[]
>this.data : string | string[]
>this : this
>data : string | string[]
return typeof data === "string" ? data : data.join(" ");
>typeof data === "string" ? data : data.join(" ") : string
>typeof data === "string" : boolean
>typeof data : string
>data : string | string[]
>"string" : string
>data : string
>data.join(" ") : string
>data.join : (separator?: string) => string
>data : string[]
>join : (separator?: string) => string
>" " : string
}
getData1() {
>getData1 : () => string
return typeof this.data === "string" ? this.data : this.data.join(" ");
>typeof this.data === "string" ? this.data : this.data.join(" ") : string
>typeof this.data === "string" : boolean
>typeof this.data : string
>this.data : string | string[]
>this : this
>data : string | string[]
>"string" : string
>this.data : string
>this : this
>data : string
>this.data.join(" ") : string
>this.data.join : (separator?: string) => string
>this.data : string[]
>this : this
>data : string[]
>join : (separator?: string) => string
>" " : string
}
}
var o: {
>o : { prop1: number | string; prop2: boolean | string; }
prop1: number|string;
>prop1 : number | string
prop2: boolean|string;
>prop2 : boolean | string
} = {
>{ prop1: "string" , prop2: true } : { prop1: string; prop2: boolean; }
prop1: "string" ,
>prop1 : string
>"string" : string
prop2: true
>prop2 : boolean
>true : boolean
}
if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {}
>typeof o.prop1 === "string" && o.prop1.toLowerCase() : string
>typeof o.prop1 === "string" : boolean
>typeof o.prop1 : string
>o.prop1 : number | string
>o : { prop1: number | string; prop2: boolean | string; }
>prop1 : number | string
>"string" : string
>o.prop1.toLowerCase() : string
>o.prop1.toLowerCase : () => string
>o.prop1 : string
>o : { prop1: number | string; prop2: boolean | string; }
>prop1 : string
>toLowerCase : () => string
var prop1 = o.prop1;
>prop1 : number | string
>o.prop1 : number | string
>o : { prop1: number | string; prop2: boolean | string; }
>prop1 : number | string
if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { }
>typeof prop1 === "string" && prop1.toLocaleLowerCase() : string
>typeof prop1 === "string" : boolean
>typeof prop1 : string
>prop1 : number | string
>"string" : string
>prop1.toLocaleLowerCase() : string
>prop1.toLocaleLowerCase : () => string
>prop1 : string
>toLocaleLowerCase : () => string

View File

@ -1,11 +1,9 @@
tests/cases/compiler/typeParameterConstraints1.ts(6,25): error TS2304: Cannot find name 'hm'.
tests/cases/compiler/typeParameterConstraints1.ts(9,25): error TS1110: Type expected.
tests/cases/compiler/typeParameterConstraints1.ts(10,26): error TS1110: Type expected.
tests/cases/compiler/typeParameterConstraints1.ts(11,26): error TS1110: Type expected.
tests/cases/compiler/typeParameterConstraints1.ts(12,26): error TS2304: Cannot find name 'undefined'.
==== tests/cases/compiler/typeParameterConstraints1.ts (5 errors) ====
==== tests/cases/compiler/typeParameterConstraints1.ts (3 errors) ====
function foo1<T extends any>(test: T) { }
function foo2<T extends number>(test: T) { }
function foo3<T extends string>(test: T) { }
@ -23,9 +21,5 @@ tests/cases/compiler/typeParameterConstraints1.ts(12,26): error TS2304: Cannot f
~
!!! error TS1110: Type expected.
function foo11<T extends null> (test: T) { }
~~~~
!!! error TS1110: Type expected.
function foo12<T extends undefined>(test: T) { }
~~~~~~~~~
!!! error TS2304: Cannot find name 'undefined'.
function foo13<T extends void>(test: T) { }

View File

@ -793,6 +793,7 @@ module ts {
"kind": "Identifier",
"pos": 1,
"end": 10,
"originalKeywordKind": "UndefinedKeyword",
"text": "undefined"
}
}`);