From 60288b7d7b1cb8db2260bd6e5f151bc37c32bf64 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 21 Nov 2016 21:12:46 -0500 Subject: [PATCH] Improve operator expression type checking --- src/compiler/checker.ts | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f16abd2c359..ace0f9e0461 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -166,6 +166,7 @@ namespace ts { const resolvingPartialSignatures: Signature[] = []; const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); + const operatorExpressionTypes = createMap(); const globals = createMap(); /** @@ -241,7 +242,6 @@ namespace ts { const visitedFlowTypes: FlowType[] = []; const potentialThisCollisions: Node[] = []; const awaitedTypeStack: number[] = []; - const operatorExpressionTypes = createMap(); const diagnostics = createDiagnosticCollection(); @@ -14271,16 +14271,28 @@ namespace ts { case SyntaxKind.EqualsEqualsToken: case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: - case SyntaxKind.ExclamationEqualsEqualsToken: - case SyntaxKind.InstanceOfKeyword: - case SyntaxKind.InKeyword: - // TODO: type parameters - return createBinaryOperatorType(undefined, anyType, anyType, booleanType); + case SyntaxKind.ExclamationEqualsEqualsToken: { + const type = createTypeParameter("T"); + return createBinaryOperatorType([type], type, type, booleanType); + } - case SyntaxKind.AmpersandAmpersandToken: - case SyntaxKind.BarBarToken: - // TODO: type parameters - return createBinaryOperatorType(undefined, anyType, anyType, anyType); + case SyntaxKind.InstanceOfKeyword: + return createBinaryOperatorType(undefined, anyType, globalFunctionType, booleanType); + + case SyntaxKind.InKeyword: + return createBinaryOperatorType(undefined, getUnionType([stringType, numberType, esSymbolType]), anyType, booleanType); + + case SyntaxKind.AmpersandAmpersandToken: { + const type1 = createTypeParameter("T"); + const type2 = createTypeParameter("U"); + return createBinaryOperatorType([type1, type2], type1, type2, type2); + } + + case SyntaxKind.BarBarToken: { + const type1 = createTypeParameter("T"); + const type2 = createTypeParameter("U"); + return createBinaryOperatorType([type1, type2], type1, type2, getUnionType([type1, type2])); + } case SyntaxKind.TildeToken: case SyntaxKind.TildePlusToken: @@ -14295,6 +14307,15 @@ namespace ts { } } + function createTypeParameter(name: string, constraint?: Type) { + const type = createType(TypeFlags.TypeParameter); + const symbol = createSymbol(SymbolFlags.Transient | SymbolFlags.TypeParameter, name); + type.symbol = symbol; + type.constraint = constraint || noConstraintType; + symbol.declaredType = type; + return type; + } + function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean { if (!isTypeAnyOrAllConstituentTypesHaveKind(type, TypeFlags.NumberLike)) { error(operand, diagnostic);