Merge pull request #32695 from microsoft/assertionsInControlFlow

Assertions in control flow analysis
This commit is contained in:
Anders Hejlsberg
2019-09-23 16:57:56 -07:00
committed by GitHub
35 changed files with 6253 additions and 604 deletions
+39 -15
View File
@@ -564,7 +564,7 @@ namespace ts {
if (!isIIFE) {
currentFlow = { flags: FlowFlags.Start };
if (containerFlags & (ContainerFlags.IsFunctionExpression | ContainerFlags.IsObjectLiteralOrClassExpressionMethod)) {
currentFlow.container = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
currentFlow.node = <FunctionExpression | ArrowFunction | MethodDeclaration>node;
}
}
// We create a return control flow graph for IIFEs and constructors. For constructors
@@ -581,6 +581,7 @@ namespace ts {
if (!(currentFlow.flags & FlowFlags.Unreachable) && containerFlags & ContainerFlags.IsFunctionLike && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
node.flags |= NodeFlags.HasImplicitReturn;
if (hasExplicitReturn) node.flags |= NodeFlags.HasExplicitReturn;
(<FunctionLikeDeclaration>node).endFlowNode = currentFlow;
}
if (node.kind === SyntaxKind.SourceFile) {
node.flags |= emitFlags;
@@ -671,6 +672,9 @@ namespace ts {
bindJSDoc(node);
return;
}
if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement && !options.allowUnreachableCode) {
node.flowNode = currentFlow;
}
switch (node.kind) {
case SyntaxKind.WhileStatement:
bindWhileStatement(<WhileStatement>node);
@@ -708,6 +712,9 @@ namespace ts {
case SyntaxKind.CaseClause:
bindCaseClause(<CaseClause>node);
break;
case SyntaxKind.ExpressionStatement:
bindExpressionStatement(<ExpressionStatement>node);
break;
case SyntaxKind.LabeledStatement:
bindLabeledStatement(<LabeledStatement>node);
break;
@@ -845,17 +852,11 @@ namespace ts {
}
function createBranchLabel(): FlowLabel {
return {
flags: FlowFlags.BranchLabel,
antecedents: undefined
};
return { flags: FlowFlags.BranchLabel, antecedents: undefined };
}
function createLoopLabel(): FlowLabel {
return {
flags: FlowFlags.LoopLabel,
antecedents: undefined
};
return { flags: FlowFlags.LoopLabel, antecedents: undefined };
}
function setFlowNodeReferenced(flow: FlowNode) {
@@ -885,7 +886,7 @@ namespace ts {
return antecedent;
}
setFlowNodeReferenced(antecedent);
return flowNodeCreated({ flags, expression, antecedent });
return flowNodeCreated({ flags, antecedent, node: expression });
}
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
@@ -893,7 +894,7 @@ namespace ts {
return antecedent;
}
setFlowNodeReferenced(antecedent);
return flowNodeCreated({ flags: FlowFlags.SwitchClause, switchStatement, clauseStart, clauseEnd, antecedent });
return flowNodeCreated({ flags: FlowFlags.SwitchClause, antecedent, switchStatement, clauseStart, clauseEnd });
}
function createFlowAssignment(antecedent: FlowNode, node: Expression | VariableDeclaration | BindingElement): FlowNode {
@@ -901,10 +902,14 @@ namespace ts {
return flowNodeCreated({ flags: FlowFlags.Assignment, antecedent, node });
}
function createFlowCall(antecedent: FlowNode, node: CallExpression): FlowNode {
setFlowNodeReferenced(antecedent);
return flowNodeCreated({ flags: FlowFlags.Call, antecedent, node });
}
function createFlowArrayMutation(antecedent: FlowNode, node: CallExpression | BinaryExpression): FlowNode {
setFlowNodeReferenced(antecedent);
const res: FlowArrayMutation = flowNodeCreated({ flags: FlowFlags.ArrayMutation, antecedent, node });
return res;
return flowNodeCreated({ flags: FlowFlags.ArrayMutation, antecedent, node });
}
function finishFlowLabel(flow: FlowLabel): FlowNode {
@@ -1030,12 +1035,12 @@ namespace ts {
function bindForInOrForOfStatement(node: ForInOrOfStatement): void {
const preLoopLabel = createLoopLabel();
const postLoopLabel = createBranchLabel();
bind(node.expression);
addAntecedent(preLoopLabel, currentFlow);
currentFlow = preLoopLabel;
if (node.kind === SyntaxKind.ForOfStatement) {
bind(node.awaitModifier);
}
bind(node.expression);
addAntecedent(postLoopLabel, currentFlow);
bind(node.initializer);
if (node.initializer.kind !== SyntaxKind.VariableDeclarationList) {
@@ -1222,7 +1227,8 @@ namespace ts {
addAntecedent(postSwitchLabel, currentFlow);
const hasDefault = forEach(node.caseBlock.clauses, c => c.kind === SyntaxKind.DefaultClause);
// We mark a switch statement as possibly exhaustive if it has no default clause and if all
// case clauses have unreachable end points (e.g. they all return).
// case clauses have unreachable end points (e.g. they all return). Note, we no longer need
// this property in control flow analysis, it's there only for backwards compatibility.
node.possiblyExhaustive = !hasDefault && !postSwitchLabel.antecedents;
if (!hasDefault) {
addAntecedent(postSwitchLabel, createFlowSwitchClause(preSwitchCaseFlow, node, 0, 0));
@@ -1281,6 +1287,24 @@ namespace ts {
activeLabels!.pop();
}
function isDottedName(node: Expression): boolean {
return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword ||
node.kind === SyntaxKind.PropertyAccessExpression && isDottedName((<PropertyAccessExpression>node).expression) ||
node.kind === SyntaxKind.ParenthesizedExpression && isDottedName((<ParenthesizedExpression>node).expression);
}
function bindExpressionStatement(node: ExpressionStatement): void {
bind(node.expression);
// A top level call expression with a dotted function name and at least one argument
// is potentially an assertion and is therefore included in the control flow.
if (node.expression.kind === SyntaxKind.CallExpression) {
const call = <CallExpression>node.expression;
if (isDottedName(call.expression)) {
currentFlow = createFlowCall(currentFlow, call);
}
}
}
function bindLabeledStatement(node: LabeledStatement): void {
const preStatementLabel = createLoopLabel();
const postStatementLabel = createBranchLabel();
+246 -111
View File
@@ -672,6 +672,7 @@ namespace ts {
const silentNeverType = createIntrinsicType(TypeFlags.Never, "never");
const nonInferrableType = createIntrinsicType(TypeFlags.Never, "never", ObjectFlags.NonInferrableType);
const implicitNeverType = createIntrinsicType(TypeFlags.Never, "never");
const unreachableNeverType = createIntrinsicType(TypeFlags.Never, "never");
const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object");
const stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]);
const keyofConstraintType = keyofStringsOnly ? stringType : stringNumberSymbolType;
@@ -702,7 +703,7 @@ namespace ts {
markerSubType.constraint = markerSuperType;
const markerOtherType = createTypeParameter();
const noTypePredicate = createIdentifierTypePredicate("<<unresolved>>", 0, anyType);
const noTypePredicate = createTypePredicate(TypePredicateKind.Identifier, "<<unresolved>>", 0, anyType);
const anySignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, errorType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
@@ -821,6 +822,8 @@ namespace ts {
let sharedFlowCount = 0;
let flowAnalysisDisabled = false;
let flowInvocationCount = 0;
let lastFlowNode: FlowNode | undefined;
let lastFlowNodeReachable: boolean;
const emptyStringType = getLiteralType("");
const zeroType = getLiteralType(0);
@@ -842,6 +845,7 @@ namespace ts {
const flowLoopTypes: Type[][] = [];
const sharedFlowNodes: FlowNode[] = [];
const sharedFlowTypes: FlowType[] = [];
const flowNodeReachable: (boolean | undefined)[] = [];
const potentialThisCollisions: Node[] = [];
const potentialNewTargetCollisions: Node[] = [];
const awaitedTypeStack: number[] = [];
@@ -4247,11 +4251,14 @@ namespace ts {
let returnTypeNode: TypeNode | undefined;
const typePredicate = getTypePredicateOfSignature(signature);
if (typePredicate) {
const parameterName = typePredicate.kind === TypePredicateKind.Identifier ?
const assertsModifier = typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ?
createToken(SyntaxKind.AssertsKeyword) :
undefined;
const parameterName = typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ?
setEmitFlags(createIdentifier(typePredicate.parameterName), EmitFlags.NoAsciiEscaping) :
createThisTypeNode();
const typeNode = typeToTypeNodeHelper(typePredicate.type, context);
returnTypeNode = createTypePredicateNode(parameterName, typeNode);
const typeNode = typePredicate.type && typeToTypeNodeHelper(typePredicate.type, context);
returnTypeNode = createTypePredicateNodeWithModifier(assertsModifier, parameterName, typeNode);
}
else {
const returnType = getReturnTypeOfSignature(signature);
@@ -4718,9 +4725,10 @@ namespace ts {
return writer ? typePredicateToStringWorker(writer).getText() : usingSingleLineStringWriter(typePredicateToStringWorker);
function typePredicateToStringWorker(writer: EmitTextWriter) {
const predicate = createTypePredicateNode(
typePredicate.kind === TypePredicateKind.Identifier ? createIdentifier(typePredicate.parameterName) : createThisTypeNode(),
nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)!, // TODO: GH#18217
const predicate = createTypePredicateNodeWithModifier(
typePredicate.kind === TypePredicateKind.AssertsThis || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? createToken(SyntaxKind.AssertsKeyword) : undefined,
typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? createIdentifier(typePredicate.parameterName) : createThisTypeNode(),
typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217
);
const printer = createPrinter({ removeComments: true });
const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
@@ -8497,12 +8505,8 @@ namespace ts {
return isBracketed || !!typeExpression && typeExpression.type.kind === SyntaxKind.JSDocOptionalType;
}
function createIdentifierTypePredicate(parameterName: string, parameterIndex: number, type: Type): IdentifierTypePredicate {
return { kind: TypePredicateKind.Identifier, parameterName, parameterIndex, type };
}
function createThisTypePredicate(type: Type): ThisTypePredicate {
return { kind: TypePredicateKind.This, type };
function createTypePredicate(kind: TypePredicateKind, parameterName: string | undefined, parameterIndex: number | undefined, type: Type | undefined): TypePredicate {
return { kind, parameterName, parameterIndex, type } as TypePredicate;
}
/**
@@ -8737,10 +8741,6 @@ namespace ts {
}
}
function signatureHasTypePredicate(signature: Signature): boolean {
return getTypePredicateOfSignature(signature) !== undefined;
}
function getTypePredicateOfSignature(signature: Signature): TypePredicate | undefined {
if (!signature.resolvedTypePredicate) {
if (signature.target) {
@@ -8768,18 +8768,13 @@ namespace ts {
return signature.resolvedTypePredicate === noTypePredicate ? undefined : signature.resolvedTypePredicate;
}
function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, signature: Signature): IdentifierTypePredicate | ThisTypePredicate {
const { parameterName } = node;
const type = getTypeFromTypeNode(node.type);
if (parameterName.kind === SyntaxKind.Identifier) {
return createIdentifierTypePredicate(
parameterName.escapedText as string,
findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText),
type);
}
else {
return createThisTypePredicate(type);
}
function createTypePredicateFromTypePredicateNode(node: TypePredicateNode, signature: Signature): TypePredicate {
const parameterName = node.parameterName;
const type = node.type && getTypeFromTypeNode(node.type);
return parameterName.kind === SyntaxKind.ThisType ?
createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsThis : TypePredicateKind.This, /*parameterName*/ undefined, /*parameterIndex*/ undefined, type) :
createTypePredicate(node.assertsModifier ? TypePredicateKind.AssertsIdentifier : TypePredicateKind.Identifier, parameterName.escapedText as string,
findIndex(signature.parameters, p => p.escapedName === parameterName.escapedText), type);
}
function getReturnTypeOfSignature(signature: Signature): Type {
@@ -9868,7 +9863,7 @@ namespace ts {
const types: Type[] = [];
for (const sig of signatures) {
const pred = getTypePredicateOfSignature(sig);
if (!pred) {
if (!pred || pred.kind === TypePredicateKind.AssertsThis || pred.kind === TypePredicateKind.AssertsIdentifier) {
continue;
}
@@ -9888,15 +9883,11 @@ namespace ts {
return undefined;
}
const unionType = getUnionType(types);
return isIdentifierTypePredicate(first)
? createIdentifierTypePredicate(first.parameterName, first.parameterIndex, unionType)
: createThisTypePredicate(unionType);
return createTypePredicate(first.kind, first.parameterName, first.parameterIndex, unionType);
}
function typePredicateKindsMatch(a: TypePredicate, b: TypePredicate): boolean {
return isIdentifierTypePredicate(a)
? isIdentifierTypePredicate(b) && a.parameterIndex === b.parameterIndex
: !isIdentifierTypePredicate(b);
return a.kind === b.kind && a.parameterIndex === b.parameterIndex;
}
// This function assumes the constituent type list is sorted and deduplicated.
@@ -11196,7 +11187,7 @@ namespace ts {
case SyntaxKind.TypeReference:
return getTypeFromTypeReference(<TypeReferenceNode>node);
case SyntaxKind.TypePredicate:
return booleanType;
return (<TypePredicateNode>node).assertsModifier ? voidType : booleanType;
case SyntaxKind.ExpressionWithTypeArguments:
return getTypeFromTypeReference(<ExpressionWithTypeArguments>node);
case SyntaxKind.TypeQuery:
@@ -11354,21 +11345,8 @@ namespace ts {
return result;
}
function instantiateTypePredicate(predicate: TypePredicate, mapper: TypeMapper): ThisTypePredicate | IdentifierTypePredicate {
if (isIdentifierTypePredicate(predicate)) {
return {
kind: TypePredicateKind.Identifier,
parameterName: predicate.parameterName,
parameterIndex: predicate.parameterIndex,
type: instantiateType(predicate.type, mapper)
};
}
else {
return {
kind: TypePredicateKind.This,
type: instantiateType(predicate.type, mapper)
};
}
function instantiateTypePredicate(predicate: TypePredicate, mapper: TypeMapper): TypePredicate {
return createTypePredicate(predicate.kind, predicate.parameterName, predicate.parameterIndex, instantiateType(predicate.type, mapper));
}
function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature {
@@ -12422,7 +12400,7 @@ namespace ts {
// with respect to T.
const sourceSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(sourceType));
const targetSig = callbackCheck ? undefined : getSingleCallSignature(getNonNullableType(targetType));
const callbacks = sourceSig && targetSig && !signatureHasTypePredicate(sourceSig) && !signatureHasTypePredicate(targetSig) &&
const callbacks = sourceSig && targetSig && !getTypePredicateOfSignature(sourceSig) && !getTypePredicateOfSignature(targetSig) &&
(getFalsyFlags(sourceType) & TypeFlags.Nullable) === (getFalsyFlags(targetType) & TypeFlags.Nullable);
const related = callbacks ?
// TODO: GH#18217 It will work if they're both `undefined`, but not if only one is
@@ -12496,7 +12474,7 @@ namespace ts {
return Ternary.False;
}
if (source.kind === TypePredicateKind.Identifier) {
if (source.kind === TypePredicateKind.Identifier || source.kind === TypePredicateKind.AssertsIdentifier) {
if (source.parameterIndex !== (target as IdentifierTypePredicate).parameterIndex) {
if (reportErrors) {
errorReporter!(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, (target as IdentifierTypePredicate).parameterName);
@@ -12506,7 +12484,9 @@ namespace ts {
}
}
const related = compareTypes(source.type, target.type, reportErrors);
const related = source.type === target.type ? Ternary.True :
source.type && target.type ? compareTypes(source.type, target.type, reportErrors) :
Ternary.False;
if (related === Ternary.False && reportErrors) {
errorReporter!(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
}
@@ -14893,16 +14873,18 @@ namespace ts {
if (!ignoreReturnTypes) {
const sourceTypePredicate = getTypePredicateOfSignature(source);
const targetTypePredicate = getTypePredicateOfSignature(target);
result &= sourceTypePredicate !== undefined || targetTypePredicate !== undefined
? compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes)
// If they're both type predicates their return types will both be `boolean`, so no need to compare those.
: compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
result &= sourceTypePredicate || targetTypePredicate ?
compareTypePredicatesIdentical(sourceTypePredicate, targetTypePredicate, compareTypes) :
compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
}
return result;
}
function compareTypePredicatesIdentical(source: TypePredicate | undefined, target: TypePredicate | undefined, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
return source === undefined || target === undefined || !typePredicateKindsMatch(source, target) ? Ternary.False : compareTypes(source.type, target.type);
return !(source && target && typePredicateKindsMatch(source, target)) ? Ternary.False :
source.type === target.type ? Ternary.True :
source.type && target.type ? compareTypes(source.type, target.type) :
Ternary.False;
}
function literalTypesWithSameBaseType(types: Type[]): boolean {
@@ -15510,8 +15492,7 @@ namespace ts {
function applyToReturnTypes(source: Signature, target: Signature, callback: (s: Type, t: Type) => void) {
const sourceTypePredicate = getTypePredicateOfSignature(source);
const targetTypePredicate = getTypePredicateOfSignature(target);
if (sourceTypePredicate && targetTypePredicate && sourceTypePredicate.kind === targetTypePredicate.kind &&
(sourceTypePredicate.kind === TypePredicateKind.This || sourceTypePredicate.parameterIndex === (<IdentifierTypePredicate>targetTypePredicate).parameterIndex)) {
if (sourceTypePredicate && targetTypePredicate && typePredicateKindsMatch(sourceTypePredicate, targetTypePredicate) && sourceTypePredicate.type && targetTypePredicate.type) {
callback(sourceTypePredicate.type, targetTypePredicate.type);
}
else {
@@ -17127,23 +17108,64 @@ namespace ts {
return isLengthPushOrUnshift || isElementAssignment;
}
function maybeTypePredicateCall(node: CallExpression) {
const links = getNodeLinks(node);
if (links.maybeTypePredicate === undefined) {
links.maybeTypePredicate = getMaybeTypePredicate(node);
}
return links.maybeTypePredicate;
function isDeclarationWithExplicitTypeAnnotation(declaration: Declaration | undefined) {
return !!(declaration && (
declaration.kind === SyntaxKind.VariableDeclaration || declaration.kind === SyntaxKind.Parameter ||
declaration.kind === SyntaxKind.PropertyDeclaration || declaration.kind === SyntaxKind.PropertySignature) &&
getEffectiveTypeAnnotationNode(declaration as VariableDeclaration | ParameterDeclaration | PropertyDeclaration | PropertySignature));
}
function getMaybeTypePredicate(node: CallExpression) {
if (node.expression.kind !== SyntaxKind.SuperKeyword) {
const funcType = checkNonNullExpression(node.expression);
if (funcType !== silentNeverType) {
const apparentType = getApparentType(funcType);
return apparentType !== errorType && some(getSignaturesOfType(apparentType, SignatureKind.Call), signatureHasTypePredicate);
function getExplicitTypeOfSymbol(symbol: Symbol) {
return symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.ValueModule) ||
symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property) && isDeclarationWithExplicitTypeAnnotation(symbol.valueDeclaration) ?
getTypeOfSymbol(symbol) : undefined;
}
// We require the dotted function name in an assertion expression to be comprised of identifiers
// that reference function, method, class or value module symbols; or variable, property or
// parameter symbols with declarations that have explicit type annotations. Such references are
// resolvable with no possibility of triggering circularities in control flow analysis.
function getTypeOfDottedName(node: Expression): Type | undefined {
if (!(node.flags & NodeFlags.InWithStatement)) {
switch (node.kind) {
case SyntaxKind.Identifier:
const symbol = getResolvedSymbol(<Identifier>node);
return getExplicitTypeOfSymbol(symbol.flags & SymbolFlags.Alias ? resolveAlias(symbol) : symbol);
case SyntaxKind.ThisKeyword:
return checkThisExpression(node);
case SyntaxKind.PropertyAccessExpression:
const type = getTypeOfDottedName((<PropertyAccessExpression>node).expression);
const prop = type && getPropertyOfType(type, (<PropertyAccessExpression>node).name.escapedText);
return prop && getExplicitTypeOfSymbol(prop);
case SyntaxKind.ParenthesizedExpression:
return getTypeOfDottedName((<ParenthesizedExpression>node).expression);
}
}
return false;
}
function getEffectsSignature(node: CallExpression) {
const links = getNodeLinks(node);
let signature = links.effectsSignature;
if (signature === undefined) {
// A call expression parented by an expression statement is a potential assertion. Other call
// expressions are potential type predicate function calls. In order to avoid triggering
// circularities in control flow analysis, we use getTypeOfDottedName when resolving the call
// target expression of an assertion.
const funcType = node.parent.kind === SyntaxKind.ExpressionStatement ? getTypeOfDottedName(node.expression) :
node.expression.kind !== SyntaxKind.SuperKeyword ? checkNonNullExpression(node.expression) :
undefined;
const signatures = getSignaturesOfType(funcType && getApparentType(funcType) || unknownType, SignatureKind.Call);
const candidate = signatures.length === 1 && !signatures[0].typeParameters ? signatures[0] :
some(signatures, hasTypePredicateOrNeverReturnType) ? getResolvedSignature(node) :
undefined;
signature = links.effectsSignature = candidate && hasTypePredicateOrNeverReturnType(candidate) ? candidate : unknownSignature;
}
return signature === unknownSignature ? undefined : signature;
}
function hasTypePredicateOrNeverReturnType(signature: Signature) {
return !!(getTypePredicateOfSignature(signature) ||
signature.declaration && (getReturnTypeFromAnnotation(signature.declaration) || unknownType).flags & TypeFlags.Never);
}
function reportFlowControlError(node: Node) {
@@ -17153,6 +17175,71 @@ namespace ts {
diagnostics.add(createFileDiagnostic(sourceFile, span.start, span.length, Diagnostics.The_containing_function_or_module_body_is_too_large_for_control_flow_analysis));
}
function isReachableFlowNode(flow: FlowNode) {
const result = isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ false);
lastFlowNode = flow;
lastFlowNodeReachable = result;
return result;
}
function isUnlockedReachableFlowNode(flow: FlowNode) {
return !(flow.flags & FlowFlags.PreFinally && (<PreFinallyFlow>flow).lock.locked) && isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ false);
}
function isReachableFlowNodeWorker(flow: FlowNode, noCacheCheck: boolean): boolean {
while (true) {
if (flow === lastFlowNode) {
return lastFlowNodeReachable;
}
const flags = flow.flags;
if (flags & FlowFlags.Shared) {
if (!noCacheCheck) {
const id = getFlowNodeId(flow);
const reachable = flowNodeReachable[id];
return reachable !== undefined ? reachable : (flowNodeReachable[id] = isReachableFlowNodeWorker(flow, /*skipCacheCheck*/ true));
}
noCacheCheck = false;
}
if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.PreFinally)) {
flow = (<FlowAssignment | FlowCondition | FlowArrayMutation | PreFinallyFlow>flow).antecedent;
}
else if (flags & FlowFlags.Call) {
const signature = getEffectsSignature((<FlowCall>flow).node);
if (signature && getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
return false;
}
flow = (<FlowCall>flow).antecedent;
}
else if (flags & FlowFlags.BranchLabel) {
// A branching point is reachable if any branch is reachable.
return some((<FlowLabel>flow).antecedents, isUnlockedReachableFlowNode);
}
else if (flags & FlowFlags.LoopLabel) {
// A loop is reachable if the control flow path that leads to the top is reachable.
flow = (<FlowLabel>flow).antecedents![0];
}
else if (flags & FlowFlags.SwitchClause) {
// The control flow path representing an unmatched value in a switch statement with
// no default clause is unreachable if the switch statement is exhaustive.
if ((<FlowSwitchClause>flow).clauseStart === (<FlowSwitchClause>flow).clauseEnd && isExhaustiveSwitchStatement((<FlowSwitchClause>flow).switchStatement)) {
return false;
}
flow = (<FlowSwitchClause>flow).antecedent;
}
else if (flags & FlowFlags.AfterFinally) {
// Cache is unreliable once we start locking nodes
lastFlowNode = undefined;
(<AfterFinallyFlow>flow).locked = true;
const result = isReachableFlowNodeWorker((<AfterFinallyFlow>flow).antecedent, /*skipCacheCheck*/ false);
(<AfterFinallyFlow>flow).locked = false;
return result;
}
else {
return !(flags & FlowFlags.Unreachable);
}
}
}
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
let key: string | undefined;
let keySet = false;
@@ -17172,7 +17259,7 @@ namespace ts {
// on empty arrays are possible without implicit any errors and new element types can be inferred without
// type mismatch errors.
const resultType = getObjectFlags(evolvedType) & ObjectFlags.EvolvingArray && isEvolvingArrayOperationTarget(reference) ? autoArrayType : finalizeEvolvingArrayType(evolvedType);
if (reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
if (resultType === unreachableNeverType|| reference.parent && reference.parent.kind === SyntaxKind.NonNullExpression && getTypeWithFacts(resultType, TypeFacts.NEUndefinedOrNull).flags & TypeFlags.Never) {
return declaredType;
}
return resultType;
@@ -17227,6 +17314,13 @@ namespace ts {
continue;
}
}
else if (flags & FlowFlags.Call) {
type = getTypeAtFlowCall(<FlowCall>flow);
if (!type) {
flow = (<FlowCall>flow).antecedent;
continue;
}
}
else if (flags & FlowFlags.Condition) {
type = getTypeAtFlowCondition(<FlowCondition>flow);
}
@@ -17251,7 +17345,7 @@ namespace ts {
}
else if (flags & FlowFlags.Start) {
// Check if we should continue with the control flow of the containing function.
const container = (<FlowStart>flow).container;
const container = (<FlowStart>flow).node;
if (container && container !== flowContainer &&
reference.kind !== SyntaxKind.PropertyAccessExpression &&
reference.kind !== SyntaxKind.ElementAccessExpression &&
@@ -17304,6 +17398,9 @@ namespace ts {
// Assignments only narrow the computed type if the declared type is a union type. Thus, we
// only need to evaluate the assigned type if the declared type is a union type.
if (isMatchingReference(reference, node)) {
if (!isReachableFlowNode(flow)) {
return unreachableNeverType;
}
if (getAssignmentTargetKind(node) === AssignmentKind.Compound) {
const flowType = getTypeAtFlowNode(flow.antecedent);
return createFlowType(getBaseTypeOfLiteralType(getTypeFromFlowType(flowType)), isIncomplete(flowType));
@@ -17325,6 +17422,9 @@ namespace ts {
// reference 'x.y.z', we may be at an assignment to 'x.y' or 'x'. In that case,
// return the declared type.
if (containsMatchingReference(reference, node)) {
if (!isReachableFlowNode(flow)) {
return unreachableNeverType;
}
// A matching dotted name might also be an expando property on a function *expression*,
// in which case we continue control flow analysis back to the function's declaration
if (isVariableDeclaration(node) && (isInJSFile(node) || isVarConst(node))) {
@@ -17343,6 +17443,38 @@ namespace ts {
return undefined;
}
function narrowTypeByAssertion(type: Type, expr: Expression): Type {
const node = skipParentheses(expr);
if (node.kind === SyntaxKind.BinaryExpression) {
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
return narrowTypeByAssertion(narrowTypeByAssertion(type, (<BinaryExpression>node).left), (<BinaryExpression>node).right);
}
if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken) {
return getUnionType([narrowTypeByAssertion(type, (<BinaryExpression>node).left), narrowTypeByAssertion(type, (<BinaryExpression>node).right)]);
}
}
return narrowType(type, node, /*assumeTrue*/ true);
}
function getTypeAtFlowCall(flow: FlowCall): FlowType | undefined {
const signature = getEffectsSignature(flow.node);
if (signature) {
const predicate = getTypePredicateOfSignature(signature);
if (predicate && (predicate.kind === TypePredicateKind.AssertsThis || predicate.kind === TypePredicateKind.AssertsIdentifier)) {
const flowType = getTypeAtFlowNode(flow.antecedent);
const type = getTypeFromFlowType(flowType);
const narrowedType = predicate.type ? narrowTypeByTypePredicate(type, predicate, flow.node, /*assumeTrue*/ true) :
predicate.kind === TypePredicateKind.AssertsIdentifier ? narrowTypeByAssertion(type, flow.node.arguments[predicate.parameterIndex]) :
type;
return narrowedType === type ? flowType : createFlowType(narrowedType, isIncomplete(flowType));
}
if (getReturnTypeOfSignature(signature).flags & TypeFlags.Never) {
return unreachableNeverType;
}
}
return undefined;
}
function getTypeAtFlowArrayMutation(flow: FlowArrayMutation): FlowType | undefined {
if (declaredType === autoType || declaredType === autoArrayType) {
const node = flow.node;
@@ -17389,7 +17521,7 @@ namespace ts {
// *only* place a silent never type is ever generated.
const assumeTrue = (flow.flags & FlowFlags.TrueCondition) !== 0;
const nonEvolvingType = finalizeEvolvingArrayType(type);
const narrowedType = narrowType(nonEvolvingType, flow.expression, assumeTrue);
const narrowedType = narrowType(nonEvolvingType, flow.node, assumeTrue);
if (narrowedType === nonEvolvingType) {
return flowType;
}
@@ -17417,6 +17549,9 @@ namespace ts {
else if (containsMatchingReferenceDiscriminant(reference, expr)) {
type = declaredType;
}
else if (flow.clauseStart === flow.clauseEnd && isExhaustiveSwitchStatement(flow.switchStatement)) {
return unreachableNeverType;
}
return createFlowType(type, isIncomplete(flowType));
}
@@ -17933,24 +18068,25 @@ namespace ts {
getIntersectionType([type, candidate]);
}
function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
if (!hasMatchingArgument(callExpression, reference) || !maybeTypePredicateCall(callExpression)) {
return type;
}
const signature = getResolvedSignature(callExpression);
const predicate = getTypePredicateOfSignature(signature);
if (!predicate) {
return type;
function narrowTypeByCallExpression(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
if (hasMatchingArgument(callExpression, reference)) {
const signature = getEffectsSignature(callExpression);
const predicate = signature && getTypePredicateOfSignature(signature);
if (predicate && (predicate.kind === TypePredicateKind.This || predicate.kind === TypePredicateKind.Identifier)) {
return narrowTypeByTypePredicate(type, predicate, callExpression, assumeTrue);
}
}
return type;
}
function narrowTypeByTypePredicate(type: Type, predicate: TypePredicate, callExpression: CallExpression, assumeTrue: boolean): 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)) {
if (predicate.kind === TypePredicateKind.Identifier || predicate.kind === TypePredicateKind.AssertsIdentifier) {
const predicateArgument = callExpression.arguments[predicate.parameterIndex];
if (predicateArgument) {
if (predicateArgument && predicate.type) {
if (isMatchingReference(reference, predicateArgument)) {
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
}
@@ -17961,7 +18097,7 @@ namespace ts {
}
else {
const invokedExpression = skipParentheses(callExpression.expression);
if (isAccessExpression(invokedExpression)) {
if (isAccessExpression(invokedExpression) && predicate.type) {
const possibleReference = skipParentheses(invokedExpression.expression);
if (isMatchingReference(reference, possibleReference)) {
return getNarrowedType(type, predicate.type, assumeTrue, isTypeSubtypeOf);
@@ -17985,7 +18121,7 @@ namespace ts {
case SyntaxKind.ElementAccessExpression:
return narrowTypeByTruthiness(type, expr, assumeTrue);
case SyntaxKind.CallExpression:
return narrowTypeByTypePredicate(type, <CallExpression>expr, assumeTrue);
return narrowTypeByCallExpression(type, <CallExpression>expr, assumeTrue);
case SyntaxKind.ParenthesizedExpression:
return narrowType(type, (<ParenthesizedExpression>expr).expression, assumeTrue);
case SyntaxKind.BinaryExpression:
@@ -23871,9 +24007,11 @@ namespace ts {
}
function isExhaustiveSwitchStatement(node: SwitchStatement): boolean {
if (!node.possiblyExhaustive) {
return false;
}
const links = getNodeLinks(node);
return links.isExhaustive !== undefined ? links.isExhaustive : (links.isExhaustive = computeExhaustiveSwitchStatement(node));
}
function computeExhaustiveSwitchStatement(node: SwitchStatement): boolean {
if (node.expression.kind === SyntaxKind.TypeOfExpression) {
const operandType = getTypeOfExpression((node.expression as TypeOfExpression).expression);
// This cast is safe because the switch is possibly exhaustive and does not contain a default case, so there can be no undefined.
@@ -23895,14 +24033,7 @@ namespace ts {
}
function functionHasImplicitReturn(func: FunctionLikeDeclaration) {
if (!(func.flags & NodeFlags.HasImplicitReturn)) {
return false;
}
if (some((<Block>func.body).statements, statement => statement.kind === SyntaxKind.SwitchStatement && isExhaustiveSwitchStatement(<SwitchStatement>statement))) {
return false;
}
return true;
return func.endFlowNode && isReachableFlowNode(func.endFlowNode);
}
/** NOTE: Return value of `[]` means a different thing than `undefined`. `[]` means func returns `void`, `undefined` means it returns `never`. */
@@ -25728,7 +25859,7 @@ namespace ts {
checkSourceElement(node.type);
const { parameterName } = node;
if (isThisTypePredicate(typePredicate)) {
if (typePredicate.kind === TypePredicateKind.This || typePredicate.kind === TypePredicateKind.AssertsThis) {
getTypeFromThisTypeNode(parameterName as ThisTypeNode);
}
else {
@@ -25737,12 +25868,14 @@ namespace ts {
error(parameterName, Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
}
else {
const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type);
checkTypeAssignableTo(typePredicate.type,
getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]),
node.type,
/*headMessage*/ undefined,
leadingError);
if (typePredicate.type) {
const leadingError = () => chainDiagnosticMessages(/*details*/ undefined, Diagnostics.A_type_predicate_s_type_must_be_assignable_to_its_parameter_s_type);
checkTypeAssignableTo(typePredicate.type,
getTypeOfSymbol(signature.parameters[typePredicate.parameterIndex]),
node.type,
/*headMessage*/ undefined,
leadingError);
}
}
}
else if (parameterName) {
@@ -30608,6 +30741,9 @@ namespace ts {
cancellationToken.throwIfCancellationRequested();
}
}
if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && node.flowNode && !isReachableFlowNode(node.flowNode)) {
errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, Diagnostics.Unreachable_code_detected);
}
switch (kind) {
case SyntaxKind.TypeParameter:
@@ -31606,8 +31742,7 @@ namespace ts {
const nameType = checkComputedPropertyName(name);
return isTypeAssignableToKind(nameType, TypeFlags.ESSymbolLike) ? nameType : stringType;
default:
Debug.fail("Unsupported property name.");
return errorType;
return Debug.fail("Unsupported property name.");
}
}
+10 -4
View File
@@ -1946,11 +1946,17 @@ namespace ts {
//
function emitTypePredicate(node: TypePredicateNode) {
if (node.assertsModifier) {
emit(node.assertsModifier);
writeSpace();
}
emit(node.parameterName);
writeSpace();
writeKeyword("is");
writeSpace();
emit(node.type);
if (node.type) {
writeSpace();
writeKeyword("is");
writeSpace();
emit(node.type);
}
}
function emitTypeReference(node: TypeReferenceNode) {
+12 -2
View File
@@ -669,16 +669,26 @@ namespace ts {
}
export function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode) {
return createTypePredicateNodeWithModifier(/*assertsModifier*/ undefined, parameterName, type);
}
export function createTypePredicateNodeWithModifier(assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) {
const node = createSynthesizedNode(SyntaxKind.TypePredicate) as TypePredicateNode;
node.assertsModifier = assertsModifier;
node.parameterName = asName(parameterName);
node.type = type;
return node;
}
export function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode) {
return node.parameterName !== parameterName
return updateTypePredicateNodeWithModifier(node, node.assertsModifier, parameterName, type);
}
export function updateTypePredicateNodeWithModifier(node: TypePredicateNode, assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) {
return node.assertsModifier !== assertsModifier
|| node.parameterName !== parameterName
|| node.type !== type
? updateNode(createTypePredicateNode(parameterName, type), node)
? updateNode(createTypePredicateNodeWithModifier(assertsModifier, parameterName, type), node)
: node;
}
+14 -1
View File
@@ -165,7 +165,8 @@ namespace ts {
return visitNode(cbNode, (<TypeReferenceNode>node).typeName) ||
visitNodes(cbNode, cbNodes, (<TypeReferenceNode>node).typeArguments);
case SyntaxKind.TypePredicate:
return visitNode(cbNode, (<TypePredicateNode>node).parameterName) ||
return visitNode(cbNode, (<TypePredicateNode>node).assertsModifier) ||
visitNode(cbNode, (<TypePredicateNode>node).parameterName) ||
visitNode(cbNode, (<TypePredicateNode>node).type);
case SyntaxKind.TypeQuery:
return visitNode(cbNode, (<TypeQueryNode>node).exprName);
@@ -3041,6 +3042,8 @@ namespace ts {
return parseParenthesizedType();
case SyntaxKind.ImportKeyword:
return parseImportType();
case SyntaxKind.AssertsKeyword:
return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference();
default:
return parseTypeReference();
}
@@ -3081,6 +3084,7 @@ namespace ts {
case SyntaxKind.DotDotDotToken:
case SyntaxKind.InferKeyword:
case SyntaxKind.ImportKeyword:
case SyntaxKind.AssertsKeyword:
return true;
case SyntaxKind.FunctionKeyword:
return !inStartOfParameter;
@@ -3257,6 +3261,7 @@ namespace ts {
const type = parseType();
if (typePredicateVariable) {
const node = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, typePredicateVariable.pos);
node.assertsModifier = undefined;
node.parameterName = typePredicateVariable;
node.type = type;
return finishNode(node);
@@ -3274,6 +3279,14 @@ namespace ts {
}
}
function parseAssertsTypePredicate(): TypeNode {
const node = <TypePredicateNode>createNode(SyntaxKind.TypePredicate);
node.assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword);
node.parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier();
node.type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : undefined;
return finishNode(node);
}
function parseType(): TypeNode {
// The rules about 'yield' only apply to actual code/expression contexts. They don't
// apply to 'type' contexts. So we disable these parameters here before moving on.
+1
View File
@@ -66,6 +66,7 @@ namespace ts {
abstract: SyntaxKind.AbstractKeyword,
any: SyntaxKind.AnyKeyword,
as: SyntaxKind.AsKeyword,
asserts: SyntaxKind.AssertsKeyword,
bigint: SyntaxKind.BigIntKeyword,
boolean: SyntaxKind.BooleanKeyword,
break: SyntaxKind.BreakKeyword,
+1 -1
View File
@@ -2871,7 +2871,7 @@ namespace ts {
function tryEnterOrLeaveBlock(operationIndex: number): void {
if (blocks) {
for (; blockIndex < blockActions!.length && blockOffsets![blockIndex] <= operationIndex; blockIndex++) {
const block = blocks[blockIndex];
const block: CodeBlock = blocks[blockIndex];
const blockAction = blockActions![blockIndex];
switch (block.kind) {
case CodeBlockKind.Exception:
+64 -21
View File
@@ -32,6 +32,7 @@ namespace ts {
| SyntaxKind.AbstractKeyword
| SyntaxKind.AnyKeyword
| SyntaxKind.AsKeyword
| SyntaxKind.AssertsKeyword
| SyntaxKind.BigIntKeyword
| SyntaxKind.BooleanKeyword
| SyntaxKind.BreakKeyword
@@ -250,6 +251,7 @@ namespace ts {
// Contextual keywords
AbstractKeyword,
AsKeyword,
AssertsKeyword,
AnyKeyword,
AsyncKeyword,
AwaitKeyword,
@@ -361,8 +363,8 @@ namespace ts {
SemicolonClassElement,
// Element
Block,
VariableStatement,
EmptyStatement,
VariableStatement,
ExpressionStatement,
IfStatement,
DoStatement,
@@ -512,6 +514,8 @@ namespace ts {
LastTemplateToken = TemplateTail,
FirstBinaryOperator = LessThanToken,
LastBinaryOperator = CaretEqualsToken,
FirstStatement = VariableStatement,
LastStatement = DebuggerStatement,
FirstNode = QualifiedName,
FirstJSDocNode = JSDocTypeExpression,
LastJSDocNode = JSDocPropertyTag,
@@ -740,6 +744,7 @@ namespace ts {
export type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
export type PlusToken = Token<SyntaxKind.PlusToken>;
export type MinusToken = Token<SyntaxKind.MinusToken>;
export type AssertsToken = Token<SyntaxKind.AssertsKeyword>;
export type Modifier
= Token<SyntaxKind.AbstractKeyword>
@@ -1041,6 +1046,7 @@ namespace ts {
questionToken?: QuestionToken;
exclamationToken?: ExclamationToken;
body?: Block | Expression;
/* @internal */ endFlowNode?: FlowNode;
}
export type FunctionLikeDeclaration =
@@ -1184,8 +1190,9 @@ namespace ts {
export interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent: SignatureDeclaration | JSDocTypeExpression;
assertsModifier?: AssertsToken;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
type?: TypeNode;
}
export interface TypeQueryNode extends TypeNode {
@@ -2574,16 +2581,33 @@ namespace ts {
FalseCondition = 1 << 6, // Condition known to be false
SwitchClause = 1 << 7, // Switch statement clause
ArrayMutation = 1 << 8, // Potential array mutation
Referenced = 1 << 9, // Referenced as antecedent once
Shared = 1 << 10, // Referenced as antecedent more than once
PreFinally = 1 << 11, // Injected edge that links pre-finally label and pre-try flow
AfterFinally = 1 << 12, // Injected edge that links post-finally flow with the rest of the graph
Call = 1 << 9, // Potential assertion call
Referenced = 1 << 10, // Referenced as antecedent once
Shared = 1 << 11, // Referenced as antecedent more than once
PreFinally = 1 << 12, // Injected edge that links pre-finally label and pre-try flow
AfterFinally = 1 << 13, // Injected edge that links post-finally flow with the rest of the graph
/** @internal */
Cached = 1 << 13, // Indicates that at least one cross-call cache entry exists for this node, even if not a loop participant
Cached = 1 << 14, // Indicates that at least one cross-call cache entry exists for this node, even if not a loop participant
Label = BranchLabel | LoopLabel,
Condition = TrueCondition | FalseCondition
}
export type FlowNode =
| AfterFinallyFlow
| PreFinallyFlow
| FlowStart
| FlowLabel
| FlowAssignment
| FlowCall
| FlowCondition
| FlowSwitchClause
| FlowArrayMutation;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number; // Node id used by flow type cache in checker
}
export interface FlowLock {
locked?: boolean;
}
@@ -2597,18 +2621,11 @@ namespace ts {
lock: FlowLock;
}
export type FlowNode =
| AfterFinallyFlow | PreFinallyFlow | FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number; // Node id used by flow type cache in checker
}
// FlowStart represents the start of a control flow. For a function expression or arrow
// function, the container property references the function (which in turn has a flowNode
// function, the node property references the function (which in turn has a flowNode
// property for the containing control flow).
export interface FlowStart extends FlowNodeBase {
container?: FunctionExpression | ArrowFunction | MethodDeclaration;
node?: FunctionExpression | ArrowFunction | MethodDeclaration;
}
// FlowLabel represents a junction with multiple possible preceding control flows.
@@ -2623,10 +2640,15 @@ namespace ts {
antecedent: FlowNode;
}
export interface FlowCall extends FlowNodeBase {
node: CallExpression;
antecedent: FlowNode;
}
// FlowCondition represents a condition that is known to be true or false at the
// node's location in the control flow.
export interface FlowCondition extends FlowNodeBase {
expression: Expression;
node: Expression;
antecedent: FlowNode;
}
@@ -3531,25 +3553,45 @@ namespace ts {
export const enum TypePredicateKind {
This,
Identifier
Identifier,
AssertsThis,
AssertsIdentifier
}
export interface TypePredicateBase {
kind: TypePredicateKind;
type: Type;
type: Type | undefined;
}
export interface ThisTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.This;
parameterName: undefined;
parameterIndex: undefined;
type: Type;
}
export interface IdentifierTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.Identifier;
parameterName: string;
parameterIndex: number;
type: Type;
}
export type TypePredicate = IdentifierTypePredicate | ThisTypePredicate;
export interface AssertsThisTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.AssertsThis;
parameterName: undefined;
parameterIndex: undefined;
type: Type | undefined;
}
export interface AssertsIdentifierTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.AssertsIdentifier;
parameterName: string;
parameterIndex: number;
type: Type | undefined;
}
export type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | AssertsThisTypePredicate | AssertsIdentifierTypePredicate;
/* @internal */
export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;
@@ -3967,7 +4009,7 @@ namespace ts {
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSymbol?: Symbol; // Cached name resolution result
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
effectsSignature?: Signature; // Signature with possible control flow effects
enumMemberValue?: string | number; // Constant value of enum member
isVisible?: boolean; // Is this node visible
containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference
@@ -3982,6 +4024,7 @@ namespace ts {
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
deferredNodes?: Map<Node>; // Set of nodes whose checking has been deferred
capturedBlockScopeBindings?: Symbol[]; // Block-scoped bindings captured beneath this part of an IterationStatement
isExhaustive?: boolean; // Is node an exhaustive switch statement
}
export const enum TypeFlags {
+2 -1
View File
@@ -333,7 +333,8 @@ namespace ts {
// Types
case SyntaxKind.TypePredicate:
return updateTypePredicateNode(<TypePredicateNode>node,
return updateTypePredicateNodeWithModifier(<TypePredicateNode>node,
visitNode((<TypePredicateNode>node).assertsModifier, visitor),
visitNode((<TypePredicateNode>node).parameterName, visitor),
visitNode((<TypePredicateNode>node).type, visitor, isTypeNode));
+254 -224
View File
@@ -73,7 +73,7 @@ declare namespace ts {
end: number;
}
export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind;
export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
export enum SyntaxKind {
Unknown = 0,
@@ -198,206 +198,207 @@ declare namespace ts {
YieldKeyword = 118,
AbstractKeyword = 119,
AsKeyword = 120,
AnyKeyword = 121,
AsyncKeyword = 122,
AwaitKeyword = 123,
BooleanKeyword = 124,
ConstructorKeyword = 125,
DeclareKeyword = 126,
GetKeyword = 127,
InferKeyword = 128,
IsKeyword = 129,
KeyOfKeyword = 130,
ModuleKeyword = 131,
NamespaceKeyword = 132,
NeverKeyword = 133,
ReadonlyKeyword = 134,
RequireKeyword = 135,
NumberKeyword = 136,
ObjectKeyword = 137,
SetKeyword = 138,
StringKeyword = 139,
SymbolKeyword = 140,
TypeKeyword = 141,
UndefinedKeyword = 142,
UniqueKeyword = 143,
UnknownKeyword = 144,
FromKeyword = 145,
GlobalKeyword = 146,
BigIntKeyword = 147,
OfKeyword = 148,
QualifiedName = 149,
ComputedPropertyName = 150,
TypeParameter = 151,
Parameter = 152,
Decorator = 153,
PropertySignature = 154,
PropertyDeclaration = 155,
MethodSignature = 156,
MethodDeclaration = 157,
Constructor = 158,
GetAccessor = 159,
SetAccessor = 160,
CallSignature = 161,
ConstructSignature = 162,
IndexSignature = 163,
TypePredicate = 164,
TypeReference = 165,
FunctionType = 166,
ConstructorType = 167,
TypeQuery = 168,
TypeLiteral = 169,
ArrayType = 170,
TupleType = 171,
OptionalType = 172,
RestType = 173,
UnionType = 174,
IntersectionType = 175,
ConditionalType = 176,
InferType = 177,
ParenthesizedType = 178,
ThisType = 179,
TypeOperator = 180,
IndexedAccessType = 181,
MappedType = 182,
LiteralType = 183,
ImportType = 184,
ObjectBindingPattern = 185,
ArrayBindingPattern = 186,
BindingElement = 187,
ArrayLiteralExpression = 188,
ObjectLiteralExpression = 189,
PropertyAccessExpression = 190,
ElementAccessExpression = 191,
CallExpression = 192,
NewExpression = 193,
TaggedTemplateExpression = 194,
TypeAssertionExpression = 195,
ParenthesizedExpression = 196,
FunctionExpression = 197,
ArrowFunction = 198,
DeleteExpression = 199,
TypeOfExpression = 200,
VoidExpression = 201,
AwaitExpression = 202,
PrefixUnaryExpression = 203,
PostfixUnaryExpression = 204,
BinaryExpression = 205,
ConditionalExpression = 206,
TemplateExpression = 207,
YieldExpression = 208,
SpreadElement = 209,
ClassExpression = 210,
OmittedExpression = 211,
ExpressionWithTypeArguments = 212,
AsExpression = 213,
NonNullExpression = 214,
MetaProperty = 215,
SyntheticExpression = 216,
TemplateSpan = 217,
SemicolonClassElement = 218,
Block = 219,
VariableStatement = 220,
AssertsKeyword = 121,
AnyKeyword = 122,
AsyncKeyword = 123,
AwaitKeyword = 124,
BooleanKeyword = 125,
ConstructorKeyword = 126,
DeclareKeyword = 127,
GetKeyword = 128,
InferKeyword = 129,
IsKeyword = 130,
KeyOfKeyword = 131,
ModuleKeyword = 132,
NamespaceKeyword = 133,
NeverKeyword = 134,
ReadonlyKeyword = 135,
RequireKeyword = 136,
NumberKeyword = 137,
ObjectKeyword = 138,
SetKeyword = 139,
StringKeyword = 140,
SymbolKeyword = 141,
TypeKeyword = 142,
UndefinedKeyword = 143,
UniqueKeyword = 144,
UnknownKeyword = 145,
FromKeyword = 146,
GlobalKeyword = 147,
BigIntKeyword = 148,
OfKeyword = 149,
QualifiedName = 150,
ComputedPropertyName = 151,
TypeParameter = 152,
Parameter = 153,
Decorator = 154,
PropertySignature = 155,
PropertyDeclaration = 156,
MethodSignature = 157,
MethodDeclaration = 158,
Constructor = 159,
GetAccessor = 160,
SetAccessor = 161,
CallSignature = 162,
ConstructSignature = 163,
IndexSignature = 164,
TypePredicate = 165,
TypeReference = 166,
FunctionType = 167,
ConstructorType = 168,
TypeQuery = 169,
TypeLiteral = 170,
ArrayType = 171,
TupleType = 172,
OptionalType = 173,
RestType = 174,
UnionType = 175,
IntersectionType = 176,
ConditionalType = 177,
InferType = 178,
ParenthesizedType = 179,
ThisType = 180,
TypeOperator = 181,
IndexedAccessType = 182,
MappedType = 183,
LiteralType = 184,
ImportType = 185,
ObjectBindingPattern = 186,
ArrayBindingPattern = 187,
BindingElement = 188,
ArrayLiteralExpression = 189,
ObjectLiteralExpression = 190,
PropertyAccessExpression = 191,
ElementAccessExpression = 192,
CallExpression = 193,
NewExpression = 194,
TaggedTemplateExpression = 195,
TypeAssertionExpression = 196,
ParenthesizedExpression = 197,
FunctionExpression = 198,
ArrowFunction = 199,
DeleteExpression = 200,
TypeOfExpression = 201,
VoidExpression = 202,
AwaitExpression = 203,
PrefixUnaryExpression = 204,
PostfixUnaryExpression = 205,
BinaryExpression = 206,
ConditionalExpression = 207,
TemplateExpression = 208,
YieldExpression = 209,
SpreadElement = 210,
ClassExpression = 211,
OmittedExpression = 212,
ExpressionWithTypeArguments = 213,
AsExpression = 214,
NonNullExpression = 215,
MetaProperty = 216,
SyntheticExpression = 217,
TemplateSpan = 218,
SemicolonClassElement = 219,
Block = 220,
EmptyStatement = 221,
ExpressionStatement = 222,
IfStatement = 223,
DoStatement = 224,
WhileStatement = 225,
ForStatement = 226,
ForInStatement = 227,
ForOfStatement = 228,
ContinueStatement = 229,
BreakStatement = 230,
ReturnStatement = 231,
WithStatement = 232,
SwitchStatement = 233,
LabeledStatement = 234,
ThrowStatement = 235,
TryStatement = 236,
DebuggerStatement = 237,
VariableDeclaration = 238,
VariableDeclarationList = 239,
FunctionDeclaration = 240,
ClassDeclaration = 241,
InterfaceDeclaration = 242,
TypeAliasDeclaration = 243,
EnumDeclaration = 244,
ModuleDeclaration = 245,
ModuleBlock = 246,
CaseBlock = 247,
NamespaceExportDeclaration = 248,
ImportEqualsDeclaration = 249,
ImportDeclaration = 250,
ImportClause = 251,
NamespaceImport = 252,
NamedImports = 253,
ImportSpecifier = 254,
ExportAssignment = 255,
ExportDeclaration = 256,
NamedExports = 257,
ExportSpecifier = 258,
MissingDeclaration = 259,
ExternalModuleReference = 260,
JsxElement = 261,
JsxSelfClosingElement = 262,
JsxOpeningElement = 263,
JsxClosingElement = 264,
JsxFragment = 265,
JsxOpeningFragment = 266,
JsxClosingFragment = 267,
JsxAttribute = 268,
JsxAttributes = 269,
JsxSpreadAttribute = 270,
JsxExpression = 271,
CaseClause = 272,
DefaultClause = 273,
HeritageClause = 274,
CatchClause = 275,
PropertyAssignment = 276,
ShorthandPropertyAssignment = 277,
SpreadAssignment = 278,
EnumMember = 279,
UnparsedPrologue = 280,
UnparsedPrepend = 281,
UnparsedText = 282,
UnparsedInternalText = 283,
UnparsedSyntheticReference = 284,
SourceFile = 285,
Bundle = 286,
UnparsedSource = 287,
InputFiles = 288,
JSDocTypeExpression = 289,
JSDocAllType = 290,
JSDocUnknownType = 291,
JSDocNullableType = 292,
JSDocNonNullableType = 293,
JSDocOptionalType = 294,
JSDocFunctionType = 295,
JSDocVariadicType = 296,
JSDocNamepathType = 297,
JSDocComment = 298,
JSDocTypeLiteral = 299,
JSDocSignature = 300,
JSDocTag = 301,
JSDocAugmentsTag = 302,
JSDocAuthorTag = 303,
JSDocClassTag = 304,
JSDocCallbackTag = 305,
JSDocEnumTag = 306,
JSDocParameterTag = 307,
JSDocReturnTag = 308,
JSDocThisTag = 309,
JSDocTypeTag = 310,
JSDocTemplateTag = 311,
JSDocTypedefTag = 312,
JSDocPropertyTag = 313,
SyntaxList = 314,
NotEmittedStatement = 315,
PartiallyEmittedExpression = 316,
CommaListExpression = 317,
MergeDeclarationMarker = 318,
EndOfDeclarationMarker = 319,
Count = 320,
VariableStatement = 222,
ExpressionStatement = 223,
IfStatement = 224,
DoStatement = 225,
WhileStatement = 226,
ForStatement = 227,
ForInStatement = 228,
ForOfStatement = 229,
ContinueStatement = 230,
BreakStatement = 231,
ReturnStatement = 232,
WithStatement = 233,
SwitchStatement = 234,
LabeledStatement = 235,
ThrowStatement = 236,
TryStatement = 237,
DebuggerStatement = 238,
VariableDeclaration = 239,
VariableDeclarationList = 240,
FunctionDeclaration = 241,
ClassDeclaration = 242,
InterfaceDeclaration = 243,
TypeAliasDeclaration = 244,
EnumDeclaration = 245,
ModuleDeclaration = 246,
ModuleBlock = 247,
CaseBlock = 248,
NamespaceExportDeclaration = 249,
ImportEqualsDeclaration = 250,
ImportDeclaration = 251,
ImportClause = 252,
NamespaceImport = 253,
NamedImports = 254,
ImportSpecifier = 255,
ExportAssignment = 256,
ExportDeclaration = 257,
NamedExports = 258,
ExportSpecifier = 259,
MissingDeclaration = 260,
ExternalModuleReference = 261,
JsxElement = 262,
JsxSelfClosingElement = 263,
JsxOpeningElement = 264,
JsxClosingElement = 265,
JsxFragment = 266,
JsxOpeningFragment = 267,
JsxClosingFragment = 268,
JsxAttribute = 269,
JsxAttributes = 270,
JsxSpreadAttribute = 271,
JsxExpression = 272,
CaseClause = 273,
DefaultClause = 274,
HeritageClause = 275,
CatchClause = 276,
PropertyAssignment = 277,
ShorthandPropertyAssignment = 278,
SpreadAssignment = 279,
EnumMember = 280,
UnparsedPrologue = 281,
UnparsedPrepend = 282,
UnparsedText = 283,
UnparsedInternalText = 284,
UnparsedSyntheticReference = 285,
SourceFile = 286,
Bundle = 287,
UnparsedSource = 288,
InputFiles = 289,
JSDocTypeExpression = 290,
JSDocAllType = 291,
JSDocUnknownType = 292,
JSDocNullableType = 293,
JSDocNonNullableType = 294,
JSDocOptionalType = 295,
JSDocFunctionType = 296,
JSDocVariadicType = 297,
JSDocNamepathType = 298,
JSDocComment = 299,
JSDocTypeLiteral = 300,
JSDocSignature = 301,
JSDocTag = 302,
JSDocAugmentsTag = 303,
JSDocAuthorTag = 304,
JSDocClassTag = 305,
JSDocCallbackTag = 306,
JSDocEnumTag = 307,
JSDocParameterTag = 308,
JSDocReturnTag = 309,
JSDocThisTag = 310,
JSDocTypeTag = 311,
JSDocTemplateTag = 312,
JSDocTypedefTag = 313,
JSDocPropertyTag = 314,
SyntaxList = 315,
NotEmittedStatement = 316,
PartiallyEmittedExpression = 317,
CommaListExpression = 318,
MergeDeclarationMarker = 319,
EndOfDeclarationMarker = 320,
Count = 321,
FirstAssignment = 60,
LastAssignment = 72,
FirstCompoundAssignment = 61,
@@ -405,15 +406,15 @@ declare namespace ts {
FirstReservedWord = 74,
LastReservedWord = 109,
FirstKeyword = 74,
LastKeyword = 148,
LastKeyword = 149,
FirstFutureReservedWord = 110,
LastFutureReservedWord = 118,
FirstTypeNode = 164,
LastTypeNode = 184,
FirstTypeNode = 165,
LastTypeNode = 185,
FirstPunctuation = 18,
LastPunctuation = 72,
FirstToken = 0,
LastToken = 148,
LastToken = 149,
FirstTriviaToken = 2,
LastTriviaToken = 7,
FirstLiteralToken = 8,
@@ -422,11 +423,13 @@ declare namespace ts {
LastTemplateToken = 17,
FirstBinaryOperator = 28,
LastBinaryOperator = 72,
FirstNode = 149,
FirstJSDocNode = 289,
LastJSDocNode = 313,
FirstJSDocTagNode = 301,
LastJSDocTagNode = 313,
FirstStatement = 222,
LastStatement = 238,
FirstNode = 150,
FirstJSDocNode = 290,
LastJSDocNode = 314,
FirstJSDocTagNode = 302,
LastJSDocTagNode = 314,
}
export enum NodeFlags {
None = 0,
@@ -517,6 +520,7 @@ declare namespace ts {
export type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
export type PlusToken = Token<SyntaxKind.PlusToken>;
export type MinusToken = Token<SyntaxKind.MinusToken>;
export type AssertsToken = Token<SyntaxKind.AssertsKeyword>;
export type Modifier = Token<SyntaxKind.AbstractKeyword> | Token<SyntaxKind.AsyncKeyword> | Token<SyntaxKind.ConstKeyword> | Token<SyntaxKind.DeclareKeyword> | Token<SyntaxKind.DefaultKeyword> | Token<SyntaxKind.ExportKeyword> | Token<SyntaxKind.PublicKeyword> | Token<SyntaxKind.PrivateKeyword> | Token<SyntaxKind.ProtectedKeyword> | Token<SyntaxKind.ReadonlyKeyword> | Token<SyntaxKind.StaticKeyword>;
export type ModifiersArray = NodeArray<Modifier>;
export interface Identifier extends PrimaryExpression, Declaration {
@@ -770,8 +774,9 @@ declare namespace ts {
export interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent: SignatureDeclaration | JSDocTypeExpression;
assertsModifier?: AssertsToken;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
type?: TypeNode;
}
export interface TypeQueryNode extends TypeNode {
kind: SyntaxKind.TypeQuery;
@@ -1669,13 +1674,19 @@ declare namespace ts {
FalseCondition = 64,
SwitchClause = 128,
ArrayMutation = 256,
Referenced = 512,
Shared = 1024,
PreFinally = 2048,
AfterFinally = 4096,
Call = 512,
Referenced = 1024,
Shared = 2048,
PreFinally = 4096,
AfterFinally = 8192,
Label = 12,
Condition = 96
}
export type FlowNode = AfterFinallyFlow | PreFinallyFlow | FlowStart | FlowLabel | FlowAssignment | FlowCall | FlowCondition | FlowSwitchClause | FlowArrayMutation;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number;
}
export interface FlowLock {
locked?: boolean;
}
@@ -1686,13 +1697,8 @@ declare namespace ts {
antecedent: FlowNode;
lock: FlowLock;
}
export type FlowNode = AfterFinallyFlow | PreFinallyFlow | FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number;
}
export interface FlowStart extends FlowNodeBase {
container?: FunctionExpression | ArrowFunction | MethodDeclaration;
node?: FunctionExpression | ArrowFunction | MethodDeclaration;
}
export interface FlowLabel extends FlowNodeBase {
antecedents: FlowNode[] | undefined;
@@ -1701,8 +1707,12 @@ declare namespace ts {
node: Expression | VariableDeclaration | BindingElement;
antecedent: FlowNode;
}
export interface FlowCall extends FlowNodeBase {
node: CallExpression;
antecedent: FlowNode;
}
export interface FlowCondition extends FlowNodeBase {
expression: Expression;
node: Expression;
antecedent: FlowNode;
}
export interface FlowSwitchClause extends FlowNodeBase {
@@ -2098,21 +2108,39 @@ declare namespace ts {
}
export enum TypePredicateKind {
This = 0,
Identifier = 1
Identifier = 1,
AssertsThis = 2,
AssertsIdentifier = 3
}
export interface TypePredicateBase {
kind: TypePredicateKind;
type: Type;
type: Type | undefined;
}
export interface ThisTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.This;
parameterName: undefined;
parameterIndex: undefined;
type: Type;
}
export interface IdentifierTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.Identifier;
parameterName: string;
parameterIndex: number;
type: Type;
}
export type TypePredicate = IdentifierTypePredicate | ThisTypePredicate;
export interface AssertsThisTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.AssertsThis;
parameterName: undefined;
parameterIndex: undefined;
type: Type | undefined;
}
export interface AssertsIdentifierTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.AssertsIdentifier;
parameterName: string;
parameterIndex: number;
type: Type | undefined;
}
export type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | AssertsThisTypePredicate | AssertsIdentifierTypePredicate;
export enum SymbolFlags {
None = 0,
FunctionScopedVariable = 1,
@@ -3845,7 +3873,9 @@ declare namespace ts {
function updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration;
function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode;
function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode;
function createTypePredicateNodeWithModifier(assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode;
function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode;
function updateTypePredicateNodeWithModifier(node: TypePredicateNode, assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode;
function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined): TypeReferenceNode;
function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined): TypeReferenceNode;
function createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode;
+254 -224
View File
@@ -73,7 +73,7 @@ declare namespace ts {
end: number;
}
export type JSDocSyntaxKind = SyntaxKind.EndOfFileToken | SyntaxKind.WhitespaceTrivia | SyntaxKind.AtToken | SyntaxKind.NewLineTrivia | SyntaxKind.AsteriskToken | SyntaxKind.OpenBraceToken | SyntaxKind.CloseBraceToken | SyntaxKind.LessThanToken | SyntaxKind.GreaterThanToken | SyntaxKind.OpenBracketToken | SyntaxKind.CloseBracketToken | SyntaxKind.EqualsToken | SyntaxKind.CommaToken | SyntaxKind.DotToken | SyntaxKind.Identifier | SyntaxKind.BacktickToken | SyntaxKind.Unknown | KeywordSyntaxKind;
export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
export type KeywordSyntaxKind = SyntaxKind.AbstractKeyword | SyntaxKind.AnyKeyword | SyntaxKind.AsKeyword | SyntaxKind.AssertsKeyword | SyntaxKind.BigIntKeyword | SyntaxKind.BooleanKeyword | SyntaxKind.BreakKeyword | SyntaxKind.CaseKeyword | SyntaxKind.CatchKeyword | SyntaxKind.ClassKeyword | SyntaxKind.ContinueKeyword | SyntaxKind.ConstKeyword | SyntaxKind.ConstructorKeyword | SyntaxKind.DebuggerKeyword | SyntaxKind.DeclareKeyword | SyntaxKind.DefaultKeyword | SyntaxKind.DeleteKeyword | SyntaxKind.DoKeyword | SyntaxKind.ElseKeyword | SyntaxKind.EnumKeyword | SyntaxKind.ExportKeyword | SyntaxKind.ExtendsKeyword | SyntaxKind.FalseKeyword | SyntaxKind.FinallyKeyword | SyntaxKind.ForKeyword | SyntaxKind.FromKeyword | SyntaxKind.FunctionKeyword | SyntaxKind.GetKeyword | SyntaxKind.IfKeyword | SyntaxKind.ImplementsKeyword | SyntaxKind.ImportKeyword | SyntaxKind.InKeyword | SyntaxKind.InferKeyword | SyntaxKind.InstanceOfKeyword | SyntaxKind.InterfaceKeyword | SyntaxKind.IsKeyword | SyntaxKind.KeyOfKeyword | SyntaxKind.LetKeyword | SyntaxKind.ModuleKeyword | SyntaxKind.NamespaceKeyword | SyntaxKind.NeverKeyword | SyntaxKind.NewKeyword | SyntaxKind.NullKeyword | SyntaxKind.NumberKeyword | SyntaxKind.ObjectKeyword | SyntaxKind.PackageKeyword | SyntaxKind.PrivateKeyword | SyntaxKind.ProtectedKeyword | SyntaxKind.PublicKeyword | SyntaxKind.ReadonlyKeyword | SyntaxKind.RequireKeyword | SyntaxKind.GlobalKeyword | SyntaxKind.ReturnKeyword | SyntaxKind.SetKeyword | SyntaxKind.StaticKeyword | SyntaxKind.StringKeyword | SyntaxKind.SuperKeyword | SyntaxKind.SwitchKeyword | SyntaxKind.SymbolKeyword | SyntaxKind.ThisKeyword | SyntaxKind.ThrowKeyword | SyntaxKind.TrueKeyword | SyntaxKind.TryKeyword | SyntaxKind.TypeKeyword | SyntaxKind.TypeOfKeyword | SyntaxKind.UndefinedKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.UnknownKeyword | SyntaxKind.VarKeyword | SyntaxKind.VoidKeyword | SyntaxKind.WhileKeyword | SyntaxKind.WithKeyword | SyntaxKind.YieldKeyword | SyntaxKind.AsyncKeyword | SyntaxKind.AwaitKeyword | SyntaxKind.OfKeyword;
export type JsxTokenSyntaxKind = SyntaxKind.LessThanSlashToken | SyntaxKind.EndOfFileToken | SyntaxKind.ConflictMarkerTrivia | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.OpenBraceToken | SyntaxKind.LessThanToken;
export enum SyntaxKind {
Unknown = 0,
@@ -198,206 +198,207 @@ declare namespace ts {
YieldKeyword = 118,
AbstractKeyword = 119,
AsKeyword = 120,
AnyKeyword = 121,
AsyncKeyword = 122,
AwaitKeyword = 123,
BooleanKeyword = 124,
ConstructorKeyword = 125,
DeclareKeyword = 126,
GetKeyword = 127,
InferKeyword = 128,
IsKeyword = 129,
KeyOfKeyword = 130,
ModuleKeyword = 131,
NamespaceKeyword = 132,
NeverKeyword = 133,
ReadonlyKeyword = 134,
RequireKeyword = 135,
NumberKeyword = 136,
ObjectKeyword = 137,
SetKeyword = 138,
StringKeyword = 139,
SymbolKeyword = 140,
TypeKeyword = 141,
UndefinedKeyword = 142,
UniqueKeyword = 143,
UnknownKeyword = 144,
FromKeyword = 145,
GlobalKeyword = 146,
BigIntKeyword = 147,
OfKeyword = 148,
QualifiedName = 149,
ComputedPropertyName = 150,
TypeParameter = 151,
Parameter = 152,
Decorator = 153,
PropertySignature = 154,
PropertyDeclaration = 155,
MethodSignature = 156,
MethodDeclaration = 157,
Constructor = 158,
GetAccessor = 159,
SetAccessor = 160,
CallSignature = 161,
ConstructSignature = 162,
IndexSignature = 163,
TypePredicate = 164,
TypeReference = 165,
FunctionType = 166,
ConstructorType = 167,
TypeQuery = 168,
TypeLiteral = 169,
ArrayType = 170,
TupleType = 171,
OptionalType = 172,
RestType = 173,
UnionType = 174,
IntersectionType = 175,
ConditionalType = 176,
InferType = 177,
ParenthesizedType = 178,
ThisType = 179,
TypeOperator = 180,
IndexedAccessType = 181,
MappedType = 182,
LiteralType = 183,
ImportType = 184,
ObjectBindingPattern = 185,
ArrayBindingPattern = 186,
BindingElement = 187,
ArrayLiteralExpression = 188,
ObjectLiteralExpression = 189,
PropertyAccessExpression = 190,
ElementAccessExpression = 191,
CallExpression = 192,
NewExpression = 193,
TaggedTemplateExpression = 194,
TypeAssertionExpression = 195,
ParenthesizedExpression = 196,
FunctionExpression = 197,
ArrowFunction = 198,
DeleteExpression = 199,
TypeOfExpression = 200,
VoidExpression = 201,
AwaitExpression = 202,
PrefixUnaryExpression = 203,
PostfixUnaryExpression = 204,
BinaryExpression = 205,
ConditionalExpression = 206,
TemplateExpression = 207,
YieldExpression = 208,
SpreadElement = 209,
ClassExpression = 210,
OmittedExpression = 211,
ExpressionWithTypeArguments = 212,
AsExpression = 213,
NonNullExpression = 214,
MetaProperty = 215,
SyntheticExpression = 216,
TemplateSpan = 217,
SemicolonClassElement = 218,
Block = 219,
VariableStatement = 220,
AssertsKeyword = 121,
AnyKeyword = 122,
AsyncKeyword = 123,
AwaitKeyword = 124,
BooleanKeyword = 125,
ConstructorKeyword = 126,
DeclareKeyword = 127,
GetKeyword = 128,
InferKeyword = 129,
IsKeyword = 130,
KeyOfKeyword = 131,
ModuleKeyword = 132,
NamespaceKeyword = 133,
NeverKeyword = 134,
ReadonlyKeyword = 135,
RequireKeyword = 136,
NumberKeyword = 137,
ObjectKeyword = 138,
SetKeyword = 139,
StringKeyword = 140,
SymbolKeyword = 141,
TypeKeyword = 142,
UndefinedKeyword = 143,
UniqueKeyword = 144,
UnknownKeyword = 145,
FromKeyword = 146,
GlobalKeyword = 147,
BigIntKeyword = 148,
OfKeyword = 149,
QualifiedName = 150,
ComputedPropertyName = 151,
TypeParameter = 152,
Parameter = 153,
Decorator = 154,
PropertySignature = 155,
PropertyDeclaration = 156,
MethodSignature = 157,
MethodDeclaration = 158,
Constructor = 159,
GetAccessor = 160,
SetAccessor = 161,
CallSignature = 162,
ConstructSignature = 163,
IndexSignature = 164,
TypePredicate = 165,
TypeReference = 166,
FunctionType = 167,
ConstructorType = 168,
TypeQuery = 169,
TypeLiteral = 170,
ArrayType = 171,
TupleType = 172,
OptionalType = 173,
RestType = 174,
UnionType = 175,
IntersectionType = 176,
ConditionalType = 177,
InferType = 178,
ParenthesizedType = 179,
ThisType = 180,
TypeOperator = 181,
IndexedAccessType = 182,
MappedType = 183,
LiteralType = 184,
ImportType = 185,
ObjectBindingPattern = 186,
ArrayBindingPattern = 187,
BindingElement = 188,
ArrayLiteralExpression = 189,
ObjectLiteralExpression = 190,
PropertyAccessExpression = 191,
ElementAccessExpression = 192,
CallExpression = 193,
NewExpression = 194,
TaggedTemplateExpression = 195,
TypeAssertionExpression = 196,
ParenthesizedExpression = 197,
FunctionExpression = 198,
ArrowFunction = 199,
DeleteExpression = 200,
TypeOfExpression = 201,
VoidExpression = 202,
AwaitExpression = 203,
PrefixUnaryExpression = 204,
PostfixUnaryExpression = 205,
BinaryExpression = 206,
ConditionalExpression = 207,
TemplateExpression = 208,
YieldExpression = 209,
SpreadElement = 210,
ClassExpression = 211,
OmittedExpression = 212,
ExpressionWithTypeArguments = 213,
AsExpression = 214,
NonNullExpression = 215,
MetaProperty = 216,
SyntheticExpression = 217,
TemplateSpan = 218,
SemicolonClassElement = 219,
Block = 220,
EmptyStatement = 221,
ExpressionStatement = 222,
IfStatement = 223,
DoStatement = 224,
WhileStatement = 225,
ForStatement = 226,
ForInStatement = 227,
ForOfStatement = 228,
ContinueStatement = 229,
BreakStatement = 230,
ReturnStatement = 231,
WithStatement = 232,
SwitchStatement = 233,
LabeledStatement = 234,
ThrowStatement = 235,
TryStatement = 236,
DebuggerStatement = 237,
VariableDeclaration = 238,
VariableDeclarationList = 239,
FunctionDeclaration = 240,
ClassDeclaration = 241,
InterfaceDeclaration = 242,
TypeAliasDeclaration = 243,
EnumDeclaration = 244,
ModuleDeclaration = 245,
ModuleBlock = 246,
CaseBlock = 247,
NamespaceExportDeclaration = 248,
ImportEqualsDeclaration = 249,
ImportDeclaration = 250,
ImportClause = 251,
NamespaceImport = 252,
NamedImports = 253,
ImportSpecifier = 254,
ExportAssignment = 255,
ExportDeclaration = 256,
NamedExports = 257,
ExportSpecifier = 258,
MissingDeclaration = 259,
ExternalModuleReference = 260,
JsxElement = 261,
JsxSelfClosingElement = 262,
JsxOpeningElement = 263,
JsxClosingElement = 264,
JsxFragment = 265,
JsxOpeningFragment = 266,
JsxClosingFragment = 267,
JsxAttribute = 268,
JsxAttributes = 269,
JsxSpreadAttribute = 270,
JsxExpression = 271,
CaseClause = 272,
DefaultClause = 273,
HeritageClause = 274,
CatchClause = 275,
PropertyAssignment = 276,
ShorthandPropertyAssignment = 277,
SpreadAssignment = 278,
EnumMember = 279,
UnparsedPrologue = 280,
UnparsedPrepend = 281,
UnparsedText = 282,
UnparsedInternalText = 283,
UnparsedSyntheticReference = 284,
SourceFile = 285,
Bundle = 286,
UnparsedSource = 287,
InputFiles = 288,
JSDocTypeExpression = 289,
JSDocAllType = 290,
JSDocUnknownType = 291,
JSDocNullableType = 292,
JSDocNonNullableType = 293,
JSDocOptionalType = 294,
JSDocFunctionType = 295,
JSDocVariadicType = 296,
JSDocNamepathType = 297,
JSDocComment = 298,
JSDocTypeLiteral = 299,
JSDocSignature = 300,
JSDocTag = 301,
JSDocAugmentsTag = 302,
JSDocAuthorTag = 303,
JSDocClassTag = 304,
JSDocCallbackTag = 305,
JSDocEnumTag = 306,
JSDocParameterTag = 307,
JSDocReturnTag = 308,
JSDocThisTag = 309,
JSDocTypeTag = 310,
JSDocTemplateTag = 311,
JSDocTypedefTag = 312,
JSDocPropertyTag = 313,
SyntaxList = 314,
NotEmittedStatement = 315,
PartiallyEmittedExpression = 316,
CommaListExpression = 317,
MergeDeclarationMarker = 318,
EndOfDeclarationMarker = 319,
Count = 320,
VariableStatement = 222,
ExpressionStatement = 223,
IfStatement = 224,
DoStatement = 225,
WhileStatement = 226,
ForStatement = 227,
ForInStatement = 228,
ForOfStatement = 229,
ContinueStatement = 230,
BreakStatement = 231,
ReturnStatement = 232,
WithStatement = 233,
SwitchStatement = 234,
LabeledStatement = 235,
ThrowStatement = 236,
TryStatement = 237,
DebuggerStatement = 238,
VariableDeclaration = 239,
VariableDeclarationList = 240,
FunctionDeclaration = 241,
ClassDeclaration = 242,
InterfaceDeclaration = 243,
TypeAliasDeclaration = 244,
EnumDeclaration = 245,
ModuleDeclaration = 246,
ModuleBlock = 247,
CaseBlock = 248,
NamespaceExportDeclaration = 249,
ImportEqualsDeclaration = 250,
ImportDeclaration = 251,
ImportClause = 252,
NamespaceImport = 253,
NamedImports = 254,
ImportSpecifier = 255,
ExportAssignment = 256,
ExportDeclaration = 257,
NamedExports = 258,
ExportSpecifier = 259,
MissingDeclaration = 260,
ExternalModuleReference = 261,
JsxElement = 262,
JsxSelfClosingElement = 263,
JsxOpeningElement = 264,
JsxClosingElement = 265,
JsxFragment = 266,
JsxOpeningFragment = 267,
JsxClosingFragment = 268,
JsxAttribute = 269,
JsxAttributes = 270,
JsxSpreadAttribute = 271,
JsxExpression = 272,
CaseClause = 273,
DefaultClause = 274,
HeritageClause = 275,
CatchClause = 276,
PropertyAssignment = 277,
ShorthandPropertyAssignment = 278,
SpreadAssignment = 279,
EnumMember = 280,
UnparsedPrologue = 281,
UnparsedPrepend = 282,
UnparsedText = 283,
UnparsedInternalText = 284,
UnparsedSyntheticReference = 285,
SourceFile = 286,
Bundle = 287,
UnparsedSource = 288,
InputFiles = 289,
JSDocTypeExpression = 290,
JSDocAllType = 291,
JSDocUnknownType = 292,
JSDocNullableType = 293,
JSDocNonNullableType = 294,
JSDocOptionalType = 295,
JSDocFunctionType = 296,
JSDocVariadicType = 297,
JSDocNamepathType = 298,
JSDocComment = 299,
JSDocTypeLiteral = 300,
JSDocSignature = 301,
JSDocTag = 302,
JSDocAugmentsTag = 303,
JSDocAuthorTag = 304,
JSDocClassTag = 305,
JSDocCallbackTag = 306,
JSDocEnumTag = 307,
JSDocParameterTag = 308,
JSDocReturnTag = 309,
JSDocThisTag = 310,
JSDocTypeTag = 311,
JSDocTemplateTag = 312,
JSDocTypedefTag = 313,
JSDocPropertyTag = 314,
SyntaxList = 315,
NotEmittedStatement = 316,
PartiallyEmittedExpression = 317,
CommaListExpression = 318,
MergeDeclarationMarker = 319,
EndOfDeclarationMarker = 320,
Count = 321,
FirstAssignment = 60,
LastAssignment = 72,
FirstCompoundAssignment = 61,
@@ -405,15 +406,15 @@ declare namespace ts {
FirstReservedWord = 74,
LastReservedWord = 109,
FirstKeyword = 74,
LastKeyword = 148,
LastKeyword = 149,
FirstFutureReservedWord = 110,
LastFutureReservedWord = 118,
FirstTypeNode = 164,
LastTypeNode = 184,
FirstTypeNode = 165,
LastTypeNode = 185,
FirstPunctuation = 18,
LastPunctuation = 72,
FirstToken = 0,
LastToken = 148,
LastToken = 149,
FirstTriviaToken = 2,
LastTriviaToken = 7,
FirstLiteralToken = 8,
@@ -422,11 +423,13 @@ declare namespace ts {
LastTemplateToken = 17,
FirstBinaryOperator = 28,
LastBinaryOperator = 72,
FirstNode = 149,
FirstJSDocNode = 289,
LastJSDocNode = 313,
FirstJSDocTagNode = 301,
LastJSDocTagNode = 313,
FirstStatement = 222,
LastStatement = 238,
FirstNode = 150,
FirstJSDocNode = 290,
LastJSDocNode = 314,
FirstJSDocTagNode = 302,
LastJSDocTagNode = 314,
}
export enum NodeFlags {
None = 0,
@@ -517,6 +520,7 @@ declare namespace ts {
export type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
export type PlusToken = Token<SyntaxKind.PlusToken>;
export type MinusToken = Token<SyntaxKind.MinusToken>;
export type AssertsToken = Token<SyntaxKind.AssertsKeyword>;
export type Modifier = Token<SyntaxKind.AbstractKeyword> | Token<SyntaxKind.AsyncKeyword> | Token<SyntaxKind.ConstKeyword> | Token<SyntaxKind.DeclareKeyword> | Token<SyntaxKind.DefaultKeyword> | Token<SyntaxKind.ExportKeyword> | Token<SyntaxKind.PublicKeyword> | Token<SyntaxKind.PrivateKeyword> | Token<SyntaxKind.ProtectedKeyword> | Token<SyntaxKind.ReadonlyKeyword> | Token<SyntaxKind.StaticKeyword>;
export type ModifiersArray = NodeArray<Modifier>;
export interface Identifier extends PrimaryExpression, Declaration {
@@ -770,8 +774,9 @@ declare namespace ts {
export interface TypePredicateNode extends TypeNode {
kind: SyntaxKind.TypePredicate;
parent: SignatureDeclaration | JSDocTypeExpression;
assertsModifier?: AssertsToken;
parameterName: Identifier | ThisTypeNode;
type: TypeNode;
type?: TypeNode;
}
export interface TypeQueryNode extends TypeNode {
kind: SyntaxKind.TypeQuery;
@@ -1669,13 +1674,19 @@ declare namespace ts {
FalseCondition = 64,
SwitchClause = 128,
ArrayMutation = 256,
Referenced = 512,
Shared = 1024,
PreFinally = 2048,
AfterFinally = 4096,
Call = 512,
Referenced = 1024,
Shared = 2048,
PreFinally = 4096,
AfterFinally = 8192,
Label = 12,
Condition = 96
}
export type FlowNode = AfterFinallyFlow | PreFinallyFlow | FlowStart | FlowLabel | FlowAssignment | FlowCall | FlowCondition | FlowSwitchClause | FlowArrayMutation;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number;
}
export interface FlowLock {
locked?: boolean;
}
@@ -1686,13 +1697,8 @@ declare namespace ts {
antecedent: FlowNode;
lock: FlowLock;
}
export type FlowNode = AfterFinallyFlow | PreFinallyFlow | FlowStart | FlowLabel | FlowAssignment | FlowCondition | FlowSwitchClause | FlowArrayMutation;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number;
}
export interface FlowStart extends FlowNodeBase {
container?: FunctionExpression | ArrowFunction | MethodDeclaration;
node?: FunctionExpression | ArrowFunction | MethodDeclaration;
}
export interface FlowLabel extends FlowNodeBase {
antecedents: FlowNode[] | undefined;
@@ -1701,8 +1707,12 @@ declare namespace ts {
node: Expression | VariableDeclaration | BindingElement;
antecedent: FlowNode;
}
export interface FlowCall extends FlowNodeBase {
node: CallExpression;
antecedent: FlowNode;
}
export interface FlowCondition extends FlowNodeBase {
expression: Expression;
node: Expression;
antecedent: FlowNode;
}
export interface FlowSwitchClause extends FlowNodeBase {
@@ -2098,21 +2108,39 @@ declare namespace ts {
}
export enum TypePredicateKind {
This = 0,
Identifier = 1
Identifier = 1,
AssertsThis = 2,
AssertsIdentifier = 3
}
export interface TypePredicateBase {
kind: TypePredicateKind;
type: Type;
type: Type | undefined;
}
export interface ThisTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.This;
parameterName: undefined;
parameterIndex: undefined;
type: Type;
}
export interface IdentifierTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.Identifier;
parameterName: string;
parameterIndex: number;
type: Type;
}
export type TypePredicate = IdentifierTypePredicate | ThisTypePredicate;
export interface AssertsThisTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.AssertsThis;
parameterName: undefined;
parameterIndex: undefined;
type: Type | undefined;
}
export interface AssertsIdentifierTypePredicate extends TypePredicateBase {
kind: TypePredicateKind.AssertsIdentifier;
parameterName: string;
parameterIndex: number;
type: Type | undefined;
}
export type TypePredicate = ThisTypePredicate | IdentifierTypePredicate | AssertsThisTypePredicate | AssertsIdentifierTypePredicate;
export enum SymbolFlags {
None = 0,
FunctionScopedVariable = 1,
@@ -3845,7 +3873,9 @@ declare namespace ts {
function updateIndexSignature(node: IndexSignatureDeclaration, decorators: readonly Decorator[] | undefined, modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode): IndexSignatureDeclaration;
function createKeywordTypeNode(kind: KeywordTypeNode["kind"]): KeywordTypeNode;
function createTypePredicateNode(parameterName: Identifier | ThisTypeNode | string, type: TypeNode): TypePredicateNode;
function createTypePredicateNodeWithModifier(assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined): TypePredicateNode;
function updateTypePredicateNode(node: TypePredicateNode, parameterName: Identifier | ThisTypeNode, type: TypeNode): TypePredicateNode;
function updateTypePredicateNodeWithModifier(node: TypePredicateNode, assertsModifier: AssertsToken | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined): TypePredicateNode;
function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined): TypeReferenceNode;
function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined): TypeReferenceNode;
function createFunctionTypeNode(typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): FunctionTypeNode;
@@ -0,0 +1,150 @@
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(116,37): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(117,37): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(118,37): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(121,15): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(122,15): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(123,15): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/controlFlow/assertionTypePredicates1.ts(124,15): error TS1228: A type predicate is only allowed in return type position for functions and methods.
==== tests/cases/conformance/controlFlow/assertionTypePredicates1.ts (7 errors) ====
declare function isString(value: unknown): value is string;
declare function isArrayOfStrings(value: unknown): value is string[];
const assert: (value: unknown) => asserts value = value => {}
declare function assertIsString(value: unknown): asserts value is string;
declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
function f01(x: unknown) {
if (!!true) {
assert(typeof x === "string");
x.length;
}
if (!!true) {
assert(x instanceof Error);
x.message;
}
if (!!true) {
assert(typeof x === "boolean" || typeof x === "number");
x.toLocaleString;
}
if (!!true) {
assert(isArrayOfStrings(x));
x[0].length;
}
if (!!true) {
assertIsArrayOfStrings(x);
x[0].length;
}
if (!!true) {
assert(x === undefined || typeof x === "string");
x; // string | undefined
assertDefined(x);
x; // string
}
}
function f02(x: string | undefined) {
if (!!true) {
assert(x);
x.length;
}
if (!!true) {
assert(x !== undefined);
x.length;
}
if (!!true) {
assertDefined(x);
x.length;
}
}
function f03(x: string | undefined, assert: (value: unknown) => asserts value) {
assert(x);
x.length;
}
namespace Debug {
export declare function assert(value: unknown, message?: string): asserts value;
export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
}
function f10(x: string | undefined) {
if (!!true) {
Debug.assert(x);
x.length;
}
if (!!true) {
Debug.assert(x !== undefined);
x.length;
}
if (!!true) {
Debug.assertDefined(x);
x.length;
}
}
class Test {
assert(value: unknown): asserts value {
if (value) return;
throw new Error();
}
isTest2(): this is Test2 {
return this instanceof Test2;
}
assertIsTest2(): asserts this is Test2 {
if (this instanceof Test2) return;
throw new Error();
}
assertThis(): asserts this {
if (!this) return;
throw new Error();
}
bar() {
this.assertThis();
this;
}
foo(x: unknown) {
this.assert(typeof x === "string");
x.length;
if (this.isTest2()) {
this.z;
}
this.assertIsTest2();
this.z;
}
}
class Test2 extends Test {
z = 0;
}
// Invalid constructs
declare let Q1: new (x: unknown) => x is string;
~~~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
declare let Q2: new (x: boolean) => asserts x;
~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
declare let Q3: new (x: unknown) => asserts x is string;
~~~~~~~~~~~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
declare class Wat {
get p1(): this is string;
~~~~~~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
set p1(x: this is string);
~~~~~~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
get p2(): asserts this is string;
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
set p2(x: asserts this is string);
~~~~~~~~~~~~~~~~~~~~~~
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
}
@@ -0,0 +1,289 @@
//// [assertionTypePredicates1.ts]
declare function isString(value: unknown): value is string;
declare function isArrayOfStrings(value: unknown): value is string[];
const assert: (value: unknown) => asserts value = value => {}
declare function assertIsString(value: unknown): asserts value is string;
declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
function f01(x: unknown) {
if (!!true) {
assert(typeof x === "string");
x.length;
}
if (!!true) {
assert(x instanceof Error);
x.message;
}
if (!!true) {
assert(typeof x === "boolean" || typeof x === "number");
x.toLocaleString;
}
if (!!true) {
assert(isArrayOfStrings(x));
x[0].length;
}
if (!!true) {
assertIsArrayOfStrings(x);
x[0].length;
}
if (!!true) {
assert(x === undefined || typeof x === "string");
x; // string | undefined
assertDefined(x);
x; // string
}
}
function f02(x: string | undefined) {
if (!!true) {
assert(x);
x.length;
}
if (!!true) {
assert(x !== undefined);
x.length;
}
if (!!true) {
assertDefined(x);
x.length;
}
}
function f03(x: string | undefined, assert: (value: unknown) => asserts value) {
assert(x);
x.length;
}
namespace Debug {
export declare function assert(value: unknown, message?: string): asserts value;
export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
}
function f10(x: string | undefined) {
if (!!true) {
Debug.assert(x);
x.length;
}
if (!!true) {
Debug.assert(x !== undefined);
x.length;
}
if (!!true) {
Debug.assertDefined(x);
x.length;
}
}
class Test {
assert(value: unknown): asserts value {
if (value) return;
throw new Error();
}
isTest2(): this is Test2 {
return this instanceof Test2;
}
assertIsTest2(): asserts this is Test2 {
if (this instanceof Test2) return;
throw new Error();
}
assertThis(): asserts this {
if (!this) return;
throw new Error();
}
bar() {
this.assertThis();
this;
}
foo(x: unknown) {
this.assert(typeof x === "string");
x.length;
if (this.isTest2()) {
this.z;
}
this.assertIsTest2();
this.z;
}
}
class Test2 extends Test {
z = 0;
}
// Invalid constructs
declare let Q1: new (x: unknown) => x is string;
declare let Q2: new (x: boolean) => asserts x;
declare let Q3: new (x: unknown) => asserts x is string;
declare class Wat {
get p1(): this is string;
set p1(x: this is string);
get p2(): asserts this is string;
set p2(x: asserts this is string);
}
//// [assertionTypePredicates1.js]
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var assert = function (value) { };
function f01(x) {
if (!!true) {
assert(typeof x === "string");
x.length;
}
if (!!true) {
assert(x instanceof Error);
x.message;
}
if (!!true) {
assert(typeof x === "boolean" || typeof x === "number");
x.toLocaleString;
}
if (!!true) {
assert(isArrayOfStrings(x));
x[0].length;
}
if (!!true) {
assertIsArrayOfStrings(x);
x[0].length;
}
if (!!true) {
assert(x === undefined || typeof x === "string");
x; // string | undefined
assertDefined(x);
x; // string
}
}
function f02(x) {
if (!!true) {
assert(x);
x.length;
}
if (!!true) {
assert(x !== undefined);
x.length;
}
if (!!true) {
assertDefined(x);
x.length;
}
}
function f03(x, assert) {
assert(x);
x.length;
}
var Debug;
(function (Debug) {
})(Debug || (Debug = {}));
function f10(x) {
if (!!true) {
Debug.assert(x);
x.length;
}
if (!!true) {
Debug.assert(x !== undefined);
x.length;
}
if (!!true) {
Debug.assertDefined(x);
x.length;
}
}
var Test = /** @class */ (function () {
function Test() {
}
Test.prototype.assert = function (value) {
if (value)
return;
throw new Error();
};
Test.prototype.isTest2 = function () {
return this instanceof Test2;
};
Test.prototype.assertIsTest2 = function () {
if (this instanceof Test2)
return;
throw new Error();
};
Test.prototype.assertThis = function () {
if (!this)
return;
throw new Error();
};
Test.prototype.bar = function () {
this.assertThis();
this;
};
Test.prototype.foo = function (x) {
this.assert(typeof x === "string");
x.length;
if (this.isTest2()) {
this.z;
}
this.assertIsTest2();
this.z;
};
return Test;
}());
var Test2 = /** @class */ (function (_super) {
__extends(Test2, _super);
function Test2() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.z = 0;
return _this;
}
return Test2;
}(Test));
//// [assertionTypePredicates1.d.ts]
declare function isString(value: unknown): value is string;
declare function isArrayOfStrings(value: unknown): value is string[];
declare const assert: (value: unknown) => asserts value;
declare function assertIsString(value: unknown): asserts value is string;
declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
declare function f01(x: unknown): void;
declare function f02(x: string | undefined): void;
declare function f03(x: string | undefined, assert: (value: unknown) => asserts value): void;
declare namespace Debug {
function assert(value: unknown, message?: string): asserts value;
function assertDefined<T>(value: T): asserts value is NonNullable<T>;
}
declare function f10(x: string | undefined): void;
declare class Test {
assert(value: unknown): asserts value;
isTest2(): this is Test2;
assertIsTest2(): asserts this is Test2;
assertThis(): asserts this;
bar(): void;
foo(x: unknown): void;
}
declare class Test2 extends Test {
z: number;
}
declare let Q1: new (x: unknown) => x is string;
declare let Q2: new (x: boolean) => asserts x;
declare let Q3: new (x: unknown) => asserts x is string;
declare class Wat {
get p1(): this is string;
set p1(x: this is string);
get p2(): asserts this is string;
set p2(x: asserts this is string);
}
@@ -0,0 +1,359 @@
=== tests/cases/conformance/controlFlow/assertionTypePredicates1.ts ===
declare function isString(value: unknown): value is string;
>isString : Symbol(isString, Decl(assertionTypePredicates1.ts, 0, 0))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 0, 26))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 0, 26))
declare function isArrayOfStrings(value: unknown): value is string[];
>isArrayOfStrings : Symbol(isArrayOfStrings, Decl(assertionTypePredicates1.ts, 0, 59))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 1, 34))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 1, 34))
const assert: (value: unknown) => asserts value = value => {}
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 3, 15))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 3, 15))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 3, 49))
declare function assertIsString(value: unknown): asserts value is string;
>assertIsString : Symbol(assertIsString, Decl(assertionTypePredicates1.ts, 3, 61))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 5, 32))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 5, 32))
declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
>assertIsArrayOfStrings : Symbol(assertIsArrayOfStrings, Decl(assertionTypePredicates1.ts, 5, 73))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 6, 40))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 6, 40))
declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
>assertDefined : Symbol(assertDefined, Decl(assertionTypePredicates1.ts, 6, 83))
>T : Symbol(T, Decl(assertionTypePredicates1.ts, 7, 31))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 7, 34))
>T : Symbol(T, Decl(assertionTypePredicates1.ts, 7, 31))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 7, 34))
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(assertionTypePredicates1.ts, 7, 31))
function f01(x: unknown) {
>f01 : Symbol(f01, Decl(assertionTypePredicates1.ts, 7, 77))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
if (!!true) {
assert(typeof x === "string");
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assert(x instanceof Error);
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
x.message;
>x.message : Symbol(Error.message, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>message : Symbol(Error.message, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assert(typeof x === "boolean" || typeof x === "number");
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
x.toLocaleString;
>x.toLocaleString : Symbol(toLocaleString, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>toLocaleString : Symbol(toLocaleString, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assert(isArrayOfStrings(x));
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>isArrayOfStrings : Symbol(isArrayOfStrings, Decl(assertionTypePredicates1.ts, 0, 59))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
x[0].length;
>x[0].length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assertIsArrayOfStrings(x);
>assertIsArrayOfStrings : Symbol(assertIsArrayOfStrings, Decl(assertionTypePredicates1.ts, 5, 73))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
x[0].length;
>x[0].length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assert(x === undefined || typeof x === "string");
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
>undefined : Symbol(undefined)
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
x; // string | undefined
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
assertDefined(x);
>assertDefined : Symbol(assertDefined, Decl(assertionTypePredicates1.ts, 6, 83))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
x; // string
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 9, 13))
}
}
function f02(x: string | undefined) {
>f02 : Symbol(f02, Decl(assertionTypePredicates1.ts, 36, 1))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
if (!!true) {
assert(x);
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assert(x !== undefined);
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 3, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
>undefined : Symbol(undefined)
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assertDefined(x);
>assertDefined : Symbol(assertDefined, Decl(assertionTypePredicates1.ts, 6, 83))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 38, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
}
function f03(x: string | undefined, assert: (value: unknown) => asserts value) {
>f03 : Symbol(f03, Decl(assertionTypePredicates1.ts, 51, 1))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 53, 13))
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 53, 35))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 53, 45))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 53, 45))
assert(x);
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 53, 35))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 53, 13))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 53, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
namespace Debug {
>Debug : Symbol(Debug, Decl(assertionTypePredicates1.ts, 56, 1))
export declare function assert(value: unknown, message?: string): asserts value;
>assert : Symbol(assert, Decl(assertionTypePredicates1.ts, 58, 17))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 59, 35))
>message : Symbol(message, Decl(assertionTypePredicates1.ts, 59, 50))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 59, 35))
export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
>assertDefined : Symbol(assertDefined, Decl(assertionTypePredicates1.ts, 59, 84))
>T : Symbol(T, Decl(assertionTypePredicates1.ts, 60, 42))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 60, 45))
>T : Symbol(T, Decl(assertionTypePredicates1.ts, 60, 42))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 60, 45))
>NonNullable : Symbol(NonNullable, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(assertionTypePredicates1.ts, 60, 42))
}
function f10(x: string | undefined) {
>f10 : Symbol(f10, Decl(assertionTypePredicates1.ts, 61, 1))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
if (!!true) {
Debug.assert(x);
>Debug.assert : Symbol(Debug.assert, Decl(assertionTypePredicates1.ts, 58, 17))
>Debug : Symbol(Debug, Decl(assertionTypePredicates1.ts, 56, 1))
>assert : Symbol(Debug.assert, Decl(assertionTypePredicates1.ts, 58, 17))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
Debug.assert(x !== undefined);
>Debug.assert : Symbol(Debug.assert, Decl(assertionTypePredicates1.ts, 58, 17))
>Debug : Symbol(Debug, Decl(assertionTypePredicates1.ts, 56, 1))
>assert : Symbol(Debug.assert, Decl(assertionTypePredicates1.ts, 58, 17))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
>undefined : Symbol(undefined)
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
Debug.assertDefined(x);
>Debug.assertDefined : Symbol(Debug.assertDefined, Decl(assertionTypePredicates1.ts, 59, 84))
>Debug : Symbol(Debug, Decl(assertionTypePredicates1.ts, 56, 1))
>assertDefined : Symbol(Debug.assertDefined, Decl(assertionTypePredicates1.ts, 59, 84))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 63, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
}
class Test {
>Test : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
assert(value: unknown): asserts value {
>assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 79, 11))
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 79, 11))
if (value) return;
>value : Symbol(value, Decl(assertionTypePredicates1.ts, 79, 11))
throw new Error();
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
isTest2(): this is Test2 {
>isTest2 : Symbol(Test.isTest2, Decl(assertionTypePredicates1.ts, 82, 5))
>Test2 : Symbol(Test2, Decl(assertionTypePredicates1.ts, 107, 1))
return this instanceof Test2;
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
>Test2 : Symbol(Test2, Decl(assertionTypePredicates1.ts, 107, 1))
}
assertIsTest2(): asserts this is Test2 {
>assertIsTest2 : Symbol(Test.assertIsTest2, Decl(assertionTypePredicates1.ts, 85, 5))
>Test2 : Symbol(Test2, Decl(assertionTypePredicates1.ts, 107, 1))
if (this instanceof Test2) return;
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
>Test2 : Symbol(Test2, Decl(assertionTypePredicates1.ts, 107, 1))
throw new Error();
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
assertThis(): asserts this {
>assertThis : Symbol(Test.assertThis, Decl(assertionTypePredicates1.ts, 89, 5))
if (!this) return;
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
throw new Error();
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
bar() {
>bar : Symbol(Test.bar, Decl(assertionTypePredicates1.ts, 93, 5))
this.assertThis();
>this.assertThis : Symbol(Test.assertThis, Decl(assertionTypePredicates1.ts, 89, 5))
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
>assertThis : Symbol(Test.assertThis, Decl(assertionTypePredicates1.ts, 89, 5))
this;
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
}
foo(x: unknown) {
>foo : Symbol(Test.foo, Decl(assertionTypePredicates1.ts, 97, 5))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 98, 8))
this.assert(typeof x === "string");
>this.assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12))
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
>assert : Symbol(Test.assert, Decl(assertionTypePredicates1.ts, 78, 12))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 98, 8))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 98, 8))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
if (this.isTest2()) {
>this.isTest2 : Symbol(Test.isTest2, Decl(assertionTypePredicates1.ts, 82, 5))
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
>isTest2 : Symbol(Test.isTest2, Decl(assertionTypePredicates1.ts, 82, 5))
this.z;
>this.z : Symbol(Test2.z, Decl(assertionTypePredicates1.ts, 109, 26))
>z : Symbol(Test2.z, Decl(assertionTypePredicates1.ts, 109, 26))
}
this.assertIsTest2();
>this.assertIsTest2 : Symbol(Test.assertIsTest2, Decl(assertionTypePredicates1.ts, 85, 5))
>this : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
>assertIsTest2 : Symbol(Test.assertIsTest2, Decl(assertionTypePredicates1.ts, 85, 5))
this.z;
>this.z : Symbol(Test2.z, Decl(assertionTypePredicates1.ts, 109, 26))
>z : Symbol(Test2.z, Decl(assertionTypePredicates1.ts, 109, 26))
}
}
class Test2 extends Test {
>Test2 : Symbol(Test2, Decl(assertionTypePredicates1.ts, 107, 1))
>Test : Symbol(Test, Decl(assertionTypePredicates1.ts, 76, 1))
z = 0;
>z : Symbol(Test2.z, Decl(assertionTypePredicates1.ts, 109, 26))
}
// Invalid constructs
declare let Q1: new (x: unknown) => x is string;
>Q1 : Symbol(Q1, Decl(assertionTypePredicates1.ts, 115, 11))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 115, 21))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 115, 21))
declare let Q2: new (x: boolean) => asserts x;
>Q2 : Symbol(Q2, Decl(assertionTypePredicates1.ts, 116, 11))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 116, 21))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 116, 21))
declare let Q3: new (x: unknown) => asserts x is string;
>Q3 : Symbol(Q3, Decl(assertionTypePredicates1.ts, 117, 11))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 117, 21))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 117, 21))
declare class Wat {
>Wat : Symbol(Wat, Decl(assertionTypePredicates1.ts, 117, 56))
get p1(): this is string;
>p1 : Symbol(Wat.p1, Decl(assertionTypePredicates1.ts, 119, 19), Decl(assertionTypePredicates1.ts, 120, 29))
set p1(x: this is string);
>p1 : Symbol(Wat.p1, Decl(assertionTypePredicates1.ts, 119, 19), Decl(assertionTypePredicates1.ts, 120, 29))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 121, 11))
get p2(): asserts this is string;
>p2 : Symbol(Wat.p2, Decl(assertionTypePredicates1.ts, 121, 30), Decl(assertionTypePredicates1.ts, 122, 37))
set p2(x: asserts this is string);
>p2 : Symbol(Wat.p2, Decl(assertionTypePredicates1.ts, 121, 30), Decl(assertionTypePredicates1.ts, 122, 37))
>x : Symbol(x, Decl(assertionTypePredicates1.ts, 123, 11))
}
@@ -0,0 +1,438 @@
=== tests/cases/conformance/controlFlow/assertionTypePredicates1.ts ===
declare function isString(value: unknown): value is string;
>isString : (value: unknown) => value is string
>value : unknown
declare function isArrayOfStrings(value: unknown): value is string[];
>isArrayOfStrings : (value: unknown) => value is string[]
>value : unknown
const assert: (value: unknown) => asserts value = value => {}
>assert : (value: unknown) => asserts value
>value : unknown
>value => {} : (value: unknown) => void
>value : unknown
declare function assertIsString(value: unknown): asserts value is string;
>assertIsString : (value: unknown) => asserts value is string
>value : unknown
declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
>assertIsArrayOfStrings : (value: unknown) => asserts value is string[]
>value : unknown
declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
>assertDefined : <T>(value: T) => asserts value is NonNullable<T>
>value : T
function f01(x: unknown) {
>f01 : (x: unknown) => void
>x : unknown
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(typeof x === "string");
>assert(typeof x === "string") : void
>assert : (value: unknown) => asserts value
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>"string" : "string"
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(x instanceof Error);
>assert(x instanceof Error) : void
>assert : (value: unknown) => asserts value
>x instanceof Error : boolean
>x : unknown
>Error : ErrorConstructor
x.message;
>x.message : string
>x : Error
>message : string
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(typeof x === "boolean" || typeof x === "number");
>assert(typeof x === "boolean" || typeof x === "number") : void
>assert : (value: unknown) => asserts value
>typeof x === "boolean" || typeof x === "number" : boolean
>typeof x === "boolean" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>"boolean" : "boolean"
>typeof x === "number" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>"number" : "number"
x.toLocaleString;
>x.toLocaleString : ((locales?: string | string[] | undefined, options?: Intl.NumberFormatOptions | undefined) => string) | (() => string)
>x : number | boolean
>toLocaleString : ((locales?: string | string[] | undefined, options?: Intl.NumberFormatOptions | undefined) => string) | (() => string)
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(isArrayOfStrings(x));
>assert(isArrayOfStrings(x)) : void
>assert : (value: unknown) => asserts value
>isArrayOfStrings(x) : boolean
>isArrayOfStrings : (value: unknown) => value is string[]
>x : unknown
x[0].length;
>x[0].length : number
>x[0] : string
>x : string[]
>0 : 0
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assertIsArrayOfStrings(x);
>assertIsArrayOfStrings(x) : void
>assertIsArrayOfStrings : (value: unknown) => asserts value is string[]
>x : unknown
x[0].length;
>x[0].length : number
>x[0] : string
>x : string[]
>0 : 0
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(x === undefined || typeof x === "string");
>assert(x === undefined || typeof x === "string") : void
>assert : (value: unknown) => asserts value
>x === undefined || typeof x === "string" : boolean
>x === undefined : boolean
>x : unknown
>undefined : undefined
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>"string" : "string"
x; // string | undefined
>x : string | undefined
assertDefined(x);
>assertDefined(x) : void
>assertDefined : <T>(value: T) => asserts value is NonNullable<T>
>x : string | undefined
x; // string
>x : string
}
}
function f02(x: string | undefined) {
>f02 : (x: string | undefined) => void
>x : string | undefined
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(x);
>assert(x) : void
>assert : (value: unknown) => asserts value
>x : string | undefined
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assert(x !== undefined);
>assert(x !== undefined) : void
>assert : (value: unknown) => asserts value
>x !== undefined : boolean
>x : string | undefined
>undefined : undefined
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
assertDefined(x);
>assertDefined(x) : void
>assertDefined : <T>(value: T) => asserts value is NonNullable<T>
>x : string | undefined
x.length;
>x.length : number
>x : string
>length : number
}
}
function f03(x: string | undefined, assert: (value: unknown) => asserts value) {
>f03 : (x: string | undefined, assert: (value: unknown) => asserts value) => void
>x : string | undefined
>assert : (value: unknown) => asserts value
>value : unknown
assert(x);
>assert(x) : void
>assert : (value: unknown) => asserts value
>x : string | undefined
x.length;
>x.length : number
>x : string
>length : number
}
namespace Debug {
>Debug : typeof Debug
export declare function assert(value: unknown, message?: string): asserts value;
>assert : (value: unknown, message?: string | undefined) => asserts value
>value : unknown
>message : string | undefined
export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
>assertDefined : <T>(value: T) => asserts value is NonNullable<T>
>value : T
}
function f10(x: string | undefined) {
>f10 : (x: string | undefined) => void
>x : string | undefined
if (!!true) {
>!!true : true
>!true : false
>true : true
Debug.assert(x);
>Debug.assert(x) : void
>Debug.assert : (value: unknown, message?: string | undefined) => asserts value
>Debug : typeof Debug
>assert : (value: unknown, message?: string | undefined) => asserts value
>x : string | undefined
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
Debug.assert(x !== undefined);
>Debug.assert(x !== undefined) : void
>Debug.assert : (value: unknown, message?: string | undefined) => asserts value
>Debug : typeof Debug
>assert : (value: unknown, message?: string | undefined) => asserts value
>x !== undefined : boolean
>x : string | undefined
>undefined : undefined
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : true
>!true : false
>true : true
Debug.assertDefined(x);
>Debug.assertDefined(x) : void
>Debug.assertDefined : <T>(value: T) => asserts value is NonNullable<T>
>Debug : typeof Debug
>assertDefined : <T>(value: T) => asserts value is NonNullable<T>
>x : string | undefined
x.length;
>x.length : number
>x : string
>length : number
}
}
class Test {
>Test : Test
assert(value: unknown): asserts value {
>assert : (value: unknown) => asserts value
>value : unknown
if (value) return;
>value : unknown
throw new Error();
>new Error() : Error
>Error : ErrorConstructor
}
isTest2(): this is Test2 {
>isTest2 : () => this is Test2
return this instanceof Test2;
>this instanceof Test2 : boolean
>this : this
>Test2 : typeof Test2
}
assertIsTest2(): asserts this is Test2 {
>assertIsTest2 : () => asserts this is Test2
if (this instanceof Test2) return;
>this instanceof Test2 : boolean
>this : this
>Test2 : typeof Test2
throw new Error();
>new Error() : Error
>Error : ErrorConstructor
}
assertThis(): asserts this {
>assertThis : () => asserts this
if (!this) return;
>!this : false
>this : this
throw new Error();
>new Error() : Error
>Error : ErrorConstructor
}
bar() {
>bar : () => void
this.assertThis();
>this.assertThis() : void
>this.assertThis : () => asserts this
>this : this
>assertThis : () => asserts this
this;
>this : this
}
foo(x: unknown) {
>foo : (x: unknown) => void
>x : unknown
this.assert(typeof x === "string");
>this.assert(typeof x === "string") : void
>this.assert : (value: unknown) => asserts value
>this : this
>assert : (value: unknown) => asserts value
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>"string" : "string"
x.length;
>x.length : number
>x : string
>length : number
if (this.isTest2()) {
>this.isTest2() : boolean
>this.isTest2 : () => this is Test2
>this : this
>isTest2 : () => this is Test2
this.z;
>this.z : number
>this : this & Test2
>z : number
}
this.assertIsTest2();
>this.assertIsTest2() : void
>this.assertIsTest2 : () => asserts this is Test2
>this : this
>assertIsTest2 : () => asserts this is Test2
this.z;
>this.z : number
>this : this & Test2
>z : number
}
}
class Test2 extends Test {
>Test2 : Test2
>Test : Test
z = 0;
>z : number
>0 : 0
}
// Invalid constructs
declare let Q1: new (x: unknown) => x is string;
>Q1 : new (x: unknown) => x is string
>x : unknown
declare let Q2: new (x: boolean) => asserts x;
>Q2 : new (x: boolean) => asserts x
>x : boolean
declare let Q3: new (x: unknown) => asserts x is string;
>Q3 : new (x: unknown) => asserts x is string
>x : unknown
declare class Wat {
>Wat : Wat
get p1(): this is string;
>p1 : boolean
set p1(x: this is string);
>p1 : boolean
>x : boolean
get p2(): asserts this is string;
>p2 : void
set p2(x: asserts this is string);
>p2 : void
>x : void
}
@@ -0,0 +1,69 @@
tests/cases/conformance/jsdoc/assertionsAndNonReturningFunctions.js(46,9): error TS7027: Unreachable code detected.
tests/cases/conformance/jsdoc/assertionsAndNonReturningFunctions.js(58,5): error TS7027: Unreachable code detected.
==== tests/cases/conformance/jsdoc/assertionsAndNonReturningFunctions.js (2 errors) ====
/** @typedef {(check: boolean) => asserts check} AssertFunc */
/** @type {AssertFunc} */
const assert = check => {
if (!check) throw new Error();
}
/** @type {(x: unknown) => asserts x is string } */
function assertIsString(x) {
if (!(typeof x === "string")) throw new Error();
}
/**
* @param {boolean} check
* @returns {asserts check}
*/
function assert2(check) {
if (!check) throw new Error();
}
/**
* @returns {never}
*/
function fail() {
throw new Error();
}
/**
* @param {*} x
*/
function f1(x) {
if (!!true) {
assert(typeof x === "string");
x.length;
}
if (!!true) {
assert2(typeof x === "string");
x.length;
}
if (!!true) {
assertIsString(x);
x.length;
}
if (!!true) {
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
}
/**
* @param {boolean} b
*/
function f2(b) {
switch (b) {
case true: return 1;
case false: return 0;
}
b; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
@@ -0,0 +1,109 @@
=== tests/cases/conformance/jsdoc/assertionsAndNonReturningFunctions.js ===
/** @typedef {(check: boolean) => asserts check} AssertFunc */
/** @type {AssertFunc} */
const assert = check => {
>assert : Symbol(assert, Decl(assertionsAndNonReturningFunctions.js, 3, 5))
>check : Symbol(check, Decl(assertionsAndNonReturningFunctions.js, 3, 14))
if (!check) throw new Error();
>check : Symbol(check, Decl(assertionsAndNonReturningFunctions.js, 3, 14))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
/** @type {(x: unknown) => asserts x is string } */
function assertIsString(x) {
>assertIsString : Symbol(assertIsString, Decl(assertionsAndNonReturningFunctions.js, 5, 1))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 8, 24))
if (!(typeof x === "string")) throw new Error();
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 8, 24))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
/**
* @param {boolean} check
* @returns {asserts check}
*/
function assert2(check) {
>assert2 : Symbol(assert2, Decl(assertionsAndNonReturningFunctions.js, 10, 1))
>check : Symbol(check, Decl(assertionsAndNonReturningFunctions.js, 16, 17))
if (!check) throw new Error();
>check : Symbol(check, Decl(assertionsAndNonReturningFunctions.js, 16, 17))
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
/**
* @returns {never}
*/
function fail() {
>fail : Symbol(fail, Decl(assertionsAndNonReturningFunctions.js, 18, 1))
throw new Error();
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
/**
* @param {*} x
*/
function f1(x) {
>f1 : Symbol(f1, Decl(assertionsAndNonReturningFunctions.js, 25, 1))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
if (!!true) {
assert(typeof x === "string");
>assert : Symbol(assert, Decl(assertionsAndNonReturningFunctions.js, 3, 5))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assert2(typeof x === "string");
>assert2 : Symbol(assert2, Decl(assertionsAndNonReturningFunctions.js, 10, 1))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
assertIsString(x);
>assertIsString : Symbol(assertIsString, Decl(assertionsAndNonReturningFunctions.js, 5, 1))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
x.length;
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
if (!!true) {
fail();
>fail : Symbol(fail, Decl(assertionsAndNonReturningFunctions.js, 18, 1))
x; // Unreachable
>x : Symbol(x, Decl(assertionsAndNonReturningFunctions.js, 30, 12))
}
}
/**
* @param {boolean} b
*/
function f2(b) {
>f2 : Symbol(f2, Decl(assertionsAndNonReturningFunctions.js, 47, 1))
>b : Symbol(b, Decl(assertionsAndNonReturningFunctions.js, 52, 12))
switch (b) {
>b : Symbol(b, Decl(assertionsAndNonReturningFunctions.js, 52, 12))
case true: return 1;
case false: return 0;
}
b; // Unreachable
>b : Symbol(b, Decl(assertionsAndNonReturningFunctions.js, 52, 12))
}
@@ -0,0 +1,152 @@
=== tests/cases/conformance/jsdoc/assertionsAndNonReturningFunctions.js ===
/** @typedef {(check: boolean) => asserts check} AssertFunc */
/** @type {AssertFunc} */
const assert = check => {
>assert : (check: boolean) => asserts check
>check => { if (!check) throw new Error();} : (check: boolean) => asserts check
>check : boolean
if (!check) throw new Error();
>!check : boolean
>check : boolean
>new Error() : Error
>Error : ErrorConstructor
}
/** @type {(x: unknown) => asserts x is string } */
function assertIsString(x) {
>assertIsString : (x: unknown) => asserts x is string
>x : unknown
if (!(typeof x === "string")) throw new Error();
>!(typeof x === "string") : boolean
>(typeof x === "string") : boolean
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : unknown
>"string" : "string"
>new Error() : Error
>Error : ErrorConstructor
}
/**
* @param {boolean} check
* @returns {asserts check}
*/
function assert2(check) {
>assert2 : (check: boolean) => asserts check
>check : boolean
if (!check) throw new Error();
>!check : boolean
>check : boolean
>new Error() : Error
>Error : ErrorConstructor
}
/**
* @returns {never}
*/
function fail() {
>fail : () => never
throw new Error();
>new Error() : Error
>Error : ErrorConstructor
}
/**
* @param {*} x
*/
function f1(x) {
>f1 : (x: any) => void
>x : any
if (!!true) {
>!!true : boolean
>!true : boolean
>true : true
assert(typeof x === "string");
>assert(typeof x === "string") : void
>assert : (check: boolean) => asserts check
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : any
>"string" : "string"
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : boolean
>!true : boolean
>true : true
assert2(typeof x === "string");
>assert2(typeof x === "string") : void
>assert2 : (check: boolean) => asserts check
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : any
>"string" : "string"
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : boolean
>!true : boolean
>true : true
assertIsString(x);
>assertIsString(x) : void
>assertIsString : (x: unknown) => asserts x is string
>x : any
x.length;
>x.length : number
>x : string
>length : number
}
if (!!true) {
>!!true : boolean
>!true : boolean
>true : true
fail();
>fail() : never
>fail : () => never
x; // Unreachable
>x : any
}
}
/**
* @param {boolean} b
*/
function f2(b) {
>f2 : (b: boolean) => 1 | 0
>b : boolean
switch (b) {
>b : boolean
case true: return 1;
>true : true
>1 : 1
case false: return 0;
>false : false
>0 : 0
}
b; // Unreachable
>b : never
}
@@ -44,4 +44,18 @@ tests/cases/compiler/exhaustiveSwitchImplicitReturn.ts(35,32): error TS7030: Not
return 1;
}
}
function foo6(bar: "a", a: boolean, b: boolean): number {
if (a) {
switch (bar) {
case "a": return 1;
}
}
else {
switch (b) {
case true: return -1;
case false: return 0;
}
}
}
@@ -39,6 +39,20 @@ function foo5(bar: "a" | "b"): number {
return 1;
}
}
function foo6(bar: "a", a: boolean, b: boolean): number {
if (a) {
switch (bar) {
case "a": return 1;
}
}
else {
switch (b) {
case true: return -1;
case false: return 0;
}
}
}
//// [exhaustiveSwitchImplicitReturn.js]
@@ -75,3 +89,16 @@ function foo5(bar) {
return 1;
}
}
function foo6(bar, a, b) {
if (a) {
switch (bar) {
case "a": return 1;
}
}
else {
switch (b) {
case true: return -1;
case false: return 0;
}
}
}
@@ -69,3 +69,28 @@ function foo5(bar: "a" | "b"): number {
}
}
function foo6(bar: "a", a: boolean, b: boolean): number {
>foo6 : Symbol(foo6, Decl(exhaustiveSwitchImplicitReturn.ts, 39, 1))
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 41, 14))
>a : Symbol(a, Decl(exhaustiveSwitchImplicitReturn.ts, 41, 23))
>b : Symbol(b, Decl(exhaustiveSwitchImplicitReturn.ts, 41, 35))
if (a) {
>a : Symbol(a, Decl(exhaustiveSwitchImplicitReturn.ts, 41, 23))
switch (bar) {
>bar : Symbol(bar, Decl(exhaustiveSwitchImplicitReturn.ts, 41, 14))
case "a": return 1;
}
}
else {
switch (b) {
>b : Symbol(b, Decl(exhaustiveSwitchImplicitReturn.ts, 41, 35))
case true: return -1;
case false: return 0;
}
}
}
@@ -85,3 +85,36 @@ function foo5(bar: "a" | "b"): number {
}
}
function foo6(bar: "a", a: boolean, b: boolean): number {
>foo6 : (bar: "a", a: boolean, b: boolean) => number
>bar : "a"
>a : boolean
>b : boolean
if (a) {
>a : boolean
switch (bar) {
>bar : "a"
case "a": return 1;
>"a" : "a"
>1 : 1
}
}
else {
switch (b) {
>b : boolean
case true: return -1;
>true : true
>-1 : -1
>1 : 1
case false: return 0;
>false : false
>0 : 0
}
}
}
@@ -0,0 +1,202 @@
tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts(7,9): error TS7027: Unreachable code detected.
==== tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts (1 errors) ====
function f1(x: 1 | 2): string {
if (!!true) {
switch (x) {
case 1: return 'a';
case 2: return 'b';
}
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
else {
throw 0;
}
}
function f2(x: 1 | 2) {
let z: number;
switch (x) {
case 1: z = 10; break;
case 2: z = 20; break;
}
z; // Definitely assigned
}
function f3(x: 1 | 2) {
switch (x) {
case 1: return 10;
case 2: return 20;
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
}
}
// Repro from #11572
enum E { A, B }
function f(e: E): number {
switch (e) {
case E.A: return 0
case E.B: return 1
}
}
function g(e: E): number {
if (!true)
return -1
else
switch (e) {
case E.A: return 0
case E.B: return 1
}
}
// Repro from #12668
interface Square { kind: "square"; size: number; }
interface Rectangle { kind: "rectangle"; width: number; height: number; }
interface Circle { kind: "circle"; radius: number; }
interface Triangle { kind: "triangle"; side: number; }
type Shape = Square | Rectangle | Circle | Triangle;
function area(s: Shape): number {
let area;
switch (s.kind) {
case "square": area = s.size * s.size; break;
case "rectangle": area = s.width * s.height; break;
case "circle": area = Math.PI * s.radius * s.radius; break;
case "triangle": area = Math.sqrt(3) / 4 * s.side * s.side; break;
}
return area;
}
function areaWrapped(s: Shape): number {
let area;
area = (() => {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
}
})();
return area;
}
// Repro from #13241
enum MyEnum {
A,
B
}
function thisGivesError(e: MyEnum): string {
let s: string;
switch (e) {
case MyEnum.A: s = "it was A"; break;
case MyEnum.B: s = "it was B"; break;
}
return s;
}
function good1(e: MyEnum): string {
let s: string;
switch (e) {
case MyEnum.A: s = "it was A"; break;
case MyEnum.B: s = "it was B"; break;
default: s = "it was something else"; break;
}
return s;
}
function good2(e: MyEnum): string {
switch (e) {
case MyEnum.A: return "it was A";
case MyEnum.B: return "it was B";
}
}
// Repro from #18362
enum Level {
One,
Two,
}
const doSomethingWithLevel = (level: Level) => {
let next: Level;
switch (level) {
case Level.One:
next = Level.Two;
break;
case Level.Two:
next = Level.One;
break;
}
return next;
};
// Repro from #20409
interface Square2 {
kind: "square";
size: number;
}
interface Circle2 {
kind: "circle";
radius: number;
}
type Shape2 = Square2 | Circle2;
function withDefault(s1: Shape2, s2: Shape2): string {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
default:
return "never";
}
}
}
function withoutDefault(s1: Shape2, s2: Shape2): string {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
}
}
}
// Repro from #20823
function test4(value: 1 | 2) {
let x: string;
switch (value) {
case 1: x = "one"; break;
case 2: x = "two"; break;
}
return x;
}
@@ -0,0 +1,437 @@
//// [exhaustiveSwitchStatements1.ts]
function f1(x: 1 | 2): string {
if (!!true) {
switch (x) {
case 1: return 'a';
case 2: return 'b';
}
x; // Unreachable
}
else {
throw 0;
}
}
function f2(x: 1 | 2) {
let z: number;
switch (x) {
case 1: z = 10; break;
case 2: z = 20; break;
}
z; // Definitely assigned
}
function f3(x: 1 | 2) {
switch (x) {
case 1: return 10;
case 2: return 20;
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
}
}
// Repro from #11572
enum E { A, B }
function f(e: E): number {
switch (e) {
case E.A: return 0
case E.B: return 1
}
}
function g(e: E): number {
if (!true)
return -1
else
switch (e) {
case E.A: return 0
case E.B: return 1
}
}
// Repro from #12668
interface Square { kind: "square"; size: number; }
interface Rectangle { kind: "rectangle"; width: number; height: number; }
interface Circle { kind: "circle"; radius: number; }
interface Triangle { kind: "triangle"; side: number; }
type Shape = Square | Rectangle | Circle | Triangle;
function area(s: Shape): number {
let area;
switch (s.kind) {
case "square": area = s.size * s.size; break;
case "rectangle": area = s.width * s.height; break;
case "circle": area = Math.PI * s.radius * s.radius; break;
case "triangle": area = Math.sqrt(3) / 4 * s.side * s.side; break;
}
return area;
}
function areaWrapped(s: Shape): number {
let area;
area = (() => {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
}
})();
return area;
}
// Repro from #13241
enum MyEnum {
A,
B
}
function thisGivesError(e: MyEnum): string {
let s: string;
switch (e) {
case MyEnum.A: s = "it was A"; break;
case MyEnum.B: s = "it was B"; break;
}
return s;
}
function good1(e: MyEnum): string {
let s: string;
switch (e) {
case MyEnum.A: s = "it was A"; break;
case MyEnum.B: s = "it was B"; break;
default: s = "it was something else"; break;
}
return s;
}
function good2(e: MyEnum): string {
switch (e) {
case MyEnum.A: return "it was A";
case MyEnum.B: return "it was B";
}
}
// Repro from #18362
enum Level {
One,
Two,
}
const doSomethingWithLevel = (level: Level) => {
let next: Level;
switch (level) {
case Level.One:
next = Level.Two;
break;
case Level.Two:
next = Level.One;
break;
}
return next;
};
// Repro from #20409
interface Square2 {
kind: "square";
size: number;
}
interface Circle2 {
kind: "circle";
radius: number;
}
type Shape2 = Square2 | Circle2;
function withDefault(s1: Shape2, s2: Shape2): string {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
default:
return "never";
}
}
}
function withoutDefault(s1: Shape2, s2: Shape2): string {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
}
}
}
// Repro from #20823
function test4(value: 1 | 2) {
let x: string;
switch (value) {
case 1: x = "one"; break;
case 2: x = "two"; break;
}
return x;
}
//// [exhaustiveSwitchStatements1.js]
"use strict";
function f1(x) {
if (!!true) {
switch (x) {
case 1: return 'a';
case 2: return 'b';
}
x; // Unreachable
}
else {
throw 0;
}
}
function f2(x) {
var z;
switch (x) {
case 1:
z = 10;
break;
case 2:
z = 20;
break;
}
z; // Definitely assigned
}
function f3(x) {
switch (x) {
case 1: return 10;
case 2: return 20;
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
}
}
// Repro from #11572
var E;
(function (E) {
E[E["A"] = 0] = "A";
E[E["B"] = 1] = "B";
})(E || (E = {}));
function f(e) {
switch (e) {
case E.A: return 0;
case E.B: return 1;
}
}
function g(e) {
if (!true)
return -1;
else
switch (e) {
case E.A: return 0;
case E.B: return 1;
}
}
function area(s) {
var area;
switch (s.kind) {
case "square":
area = s.size * s.size;
break;
case "rectangle":
area = s.width * s.height;
break;
case "circle":
area = Math.PI * s.radius * s.radius;
break;
case "triangle":
area = Math.sqrt(3) / 4 * s.side * s.side;
break;
}
return area;
}
function areaWrapped(s) {
var area;
area = (function () {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
}
})();
return area;
}
// Repro from #13241
var MyEnum;
(function (MyEnum) {
MyEnum[MyEnum["A"] = 0] = "A";
MyEnum[MyEnum["B"] = 1] = "B";
})(MyEnum || (MyEnum = {}));
function thisGivesError(e) {
var s;
switch (e) {
case MyEnum.A:
s = "it was A";
break;
case MyEnum.B:
s = "it was B";
break;
}
return s;
}
function good1(e) {
var s;
switch (e) {
case MyEnum.A:
s = "it was A";
break;
case MyEnum.B:
s = "it was B";
break;
default:
s = "it was something else";
break;
}
return s;
}
function good2(e) {
switch (e) {
case MyEnum.A: return "it was A";
case MyEnum.B: return "it was B";
}
}
// Repro from #18362
var Level;
(function (Level) {
Level[Level["One"] = 0] = "One";
Level[Level["Two"] = 1] = "Two";
})(Level || (Level = {}));
var doSomethingWithLevel = function (level) {
var next;
switch (level) {
case Level.One:
next = Level.Two;
break;
case Level.Two:
next = Level.One;
break;
}
return next;
};
function withDefault(s1, s2) {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
default:
return "never";
}
}
}
function withoutDefault(s1, s2) {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
}
}
}
// Repro from #20823
function test4(value) {
var x;
switch (value) {
case 1:
x = "one";
break;
case 2:
x = "two";
break;
}
return x;
}
//// [exhaustiveSwitchStatements1.d.ts]
declare function f1(x: 1 | 2): string;
declare function f2(x: 1 | 2): void;
declare function f3(x: 1 | 2): 10 | 20;
declare enum E {
A = 0,
B = 1
}
declare function f(e: E): number;
declare function g(e: E): number;
interface Square {
kind: "square";
size: number;
}
interface Rectangle {
kind: "rectangle";
width: number;
height: number;
}
interface Circle {
kind: "circle";
radius: number;
}
interface Triangle {
kind: "triangle";
side: number;
}
declare type Shape = Square | Rectangle | Circle | Triangle;
declare function area(s: Shape): number;
declare function areaWrapped(s: Shape): number;
declare enum MyEnum {
A = 0,
B = 1
}
declare function thisGivesError(e: MyEnum): string;
declare function good1(e: MyEnum): string;
declare function good2(e: MyEnum): string;
declare enum Level {
One = 0,
Two = 1
}
declare const doSomethingWithLevel: (level: Level) => Level;
interface Square2 {
kind: "square";
size: number;
}
interface Circle2 {
kind: "circle";
radius: number;
}
declare type Shape2 = Square2 | Circle2;
declare function withDefault(s1: Shape2, s2: Shape2): string;
declare function withoutDefault(s1: Shape2, s2: Shape2): string;
declare function test4(value: 1 | 2): string;
@@ -0,0 +1,503 @@
=== tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts ===
function f1(x: 1 | 2): string {
>f1 : Symbol(f1, Decl(exhaustiveSwitchStatements1.ts, 0, 0))
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 0, 12))
if (!!true) {
switch (x) {
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 0, 12))
case 1: return 'a';
case 2: return 'b';
}
x; // Unreachable
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 0, 12))
}
else {
throw 0;
}
}
function f2(x: 1 | 2) {
>f2 : Symbol(f2, Decl(exhaustiveSwitchStatements1.ts, 11, 1))
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 13, 12))
let z: number;
>z : Symbol(z, Decl(exhaustiveSwitchStatements1.ts, 14, 7))
switch (x) {
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 13, 12))
case 1: z = 10; break;
>z : Symbol(z, Decl(exhaustiveSwitchStatements1.ts, 14, 7))
case 2: z = 20; break;
>z : Symbol(z, Decl(exhaustiveSwitchStatements1.ts, 14, 7))
}
z; // Definitely assigned
>z : Symbol(z, Decl(exhaustiveSwitchStatements1.ts, 14, 7))
}
function f3(x: 1 | 2) {
>f3 : Symbol(f3, Decl(exhaustiveSwitchStatements1.ts, 20, 1))
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 22, 12))
switch (x) {
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 22, 12))
case 1: return 10;
case 2: return 20;
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
}
}
// Repro from #11572
enum E { A, B }
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
>A : Symbol(E.A, Decl(exhaustiveSwitchStatements1.ts, 33, 8))
>B : Symbol(E.B, Decl(exhaustiveSwitchStatements1.ts, 33, 11))
function f(e: E): number {
>f : Symbol(f, Decl(exhaustiveSwitchStatements1.ts, 33, 15))
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 35, 11))
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
switch (e) {
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 35, 11))
case E.A: return 0
>E.A : Symbol(E.A, Decl(exhaustiveSwitchStatements1.ts, 33, 8))
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
>A : Symbol(E.A, Decl(exhaustiveSwitchStatements1.ts, 33, 8))
case E.B: return 1
>E.B : Symbol(E.B, Decl(exhaustiveSwitchStatements1.ts, 33, 11))
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
>B : Symbol(E.B, Decl(exhaustiveSwitchStatements1.ts, 33, 11))
}
}
function g(e: E): number {
>g : Symbol(g, Decl(exhaustiveSwitchStatements1.ts, 40, 1))
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 42, 11))
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
if (!true)
return -1
else
switch (e) {
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 42, 11))
case E.A: return 0
>E.A : Symbol(E.A, Decl(exhaustiveSwitchStatements1.ts, 33, 8))
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
>A : Symbol(E.A, Decl(exhaustiveSwitchStatements1.ts, 33, 8))
case E.B: return 1
>E.B : Symbol(E.B, Decl(exhaustiveSwitchStatements1.ts, 33, 11))
>E : Symbol(E, Decl(exhaustiveSwitchStatements1.ts, 29, 1))
>B : Symbol(E.B, Decl(exhaustiveSwitchStatements1.ts, 33, 11))
}
}
// Repro from #12668
interface Square { kind: "square"; size: number; }
>Square : Symbol(Square, Decl(exhaustiveSwitchStatements1.ts, 50, 1))
>kind : Symbol(Square.kind, Decl(exhaustiveSwitchStatements1.ts, 54, 18))
>size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
interface Rectangle { kind: "rectangle"; width: number; height: number; }
>Rectangle : Symbol(Rectangle, Decl(exhaustiveSwitchStatements1.ts, 54, 50))
>kind : Symbol(Rectangle.kind, Decl(exhaustiveSwitchStatements1.ts, 56, 21))
>width : Symbol(Rectangle.width, Decl(exhaustiveSwitchStatements1.ts, 56, 40))
>height : Symbol(Rectangle.height, Decl(exhaustiveSwitchStatements1.ts, 56, 55))
interface Circle { kind: "circle"; radius: number; }
>Circle : Symbol(Circle, Decl(exhaustiveSwitchStatements1.ts, 56, 73))
>kind : Symbol(Circle.kind, Decl(exhaustiveSwitchStatements1.ts, 58, 18))
>radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
interface Triangle { kind: "triangle"; side: number; }
>Triangle : Symbol(Triangle, Decl(exhaustiveSwitchStatements1.ts, 58, 52))
>kind : Symbol(Triangle.kind, Decl(exhaustiveSwitchStatements1.ts, 60, 20))
>side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
type Shape = Square | Rectangle | Circle | Triangle;
>Shape : Symbol(Shape, Decl(exhaustiveSwitchStatements1.ts, 60, 54))
>Square : Symbol(Square, Decl(exhaustiveSwitchStatements1.ts, 50, 1))
>Rectangle : Symbol(Rectangle, Decl(exhaustiveSwitchStatements1.ts, 54, 50))
>Circle : Symbol(Circle, Decl(exhaustiveSwitchStatements1.ts, 56, 73))
>Triangle : Symbol(Triangle, Decl(exhaustiveSwitchStatements1.ts, 58, 52))
function area(s: Shape): number {
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 62, 52))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>Shape : Symbol(Shape, Decl(exhaustiveSwitchStatements1.ts, 60, 54))
let area;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 65, 7))
switch (s.kind) {
>s.kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 54, 18), Decl(exhaustiveSwitchStatements1.ts, 56, 21), Decl(exhaustiveSwitchStatements1.ts, 58, 18), Decl(exhaustiveSwitchStatements1.ts, 60, 20))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 54, 18), Decl(exhaustiveSwitchStatements1.ts, 56, 21), Decl(exhaustiveSwitchStatements1.ts, 58, 18), Decl(exhaustiveSwitchStatements1.ts, 60, 20))
case "square": area = s.size * s.size; break;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 65, 7))
>s.size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
>s.size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
case "rectangle": area = s.width * s.height; break;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 65, 7))
>s.width : Symbol(Rectangle.width, Decl(exhaustiveSwitchStatements1.ts, 56, 40))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>width : Symbol(Rectangle.width, Decl(exhaustiveSwitchStatements1.ts, 56, 40))
>s.height : Symbol(Rectangle.height, Decl(exhaustiveSwitchStatements1.ts, 56, 55))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>height : Symbol(Rectangle.height, Decl(exhaustiveSwitchStatements1.ts, 56, 55))
case "circle": area = Math.PI * s.radius * s.radius; break;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 65, 7))
>Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>s.radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
>s.radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
case "triangle": area = Math.sqrt(3) / 4 * s.side * s.side; break;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 65, 7))
>Math.sqrt : Symbol(Math.sqrt, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>sqrt : Symbol(Math.sqrt, Decl(lib.es5.d.ts, --, --))
>s.side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
>s.side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 64, 14))
>side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
}
return area;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 65, 7))
}
function areaWrapped(s: Shape): number {
>areaWrapped : Symbol(areaWrapped, Decl(exhaustiveSwitchStatements1.ts, 73, 1))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>Shape : Symbol(Shape, Decl(exhaustiveSwitchStatements1.ts, 60, 54))
let area;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 76, 7))
area = (() => {
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 76, 7))
switch (s.kind) {
>s.kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 54, 18), Decl(exhaustiveSwitchStatements1.ts, 56, 21), Decl(exhaustiveSwitchStatements1.ts, 58, 18), Decl(exhaustiveSwitchStatements1.ts, 60, 20))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 54, 18), Decl(exhaustiveSwitchStatements1.ts, 56, 21), Decl(exhaustiveSwitchStatements1.ts, 58, 18), Decl(exhaustiveSwitchStatements1.ts, 60, 20))
case "square": return s.size * s.size;
>s.size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
>s.size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>size : Symbol(Square.size, Decl(exhaustiveSwitchStatements1.ts, 54, 34))
case "rectangle": return s.width * s.height;
>s.width : Symbol(Rectangle.width, Decl(exhaustiveSwitchStatements1.ts, 56, 40))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>width : Symbol(Rectangle.width, Decl(exhaustiveSwitchStatements1.ts, 56, 40))
>s.height : Symbol(Rectangle.height, Decl(exhaustiveSwitchStatements1.ts, 56, 55))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>height : Symbol(Rectangle.height, Decl(exhaustiveSwitchStatements1.ts, 56, 55))
case "circle": return Math.PI * s.radius * s.radius;
>Math.PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>PI : Symbol(Math.PI, Decl(lib.es5.d.ts, --, --))
>s.radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
>s.radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>radius : Symbol(Circle.radius, Decl(exhaustiveSwitchStatements1.ts, 58, 34))
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
>Math.sqrt : Symbol(Math.sqrt, Decl(lib.es5.d.ts, --, --))
>Math : Symbol(Math, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>sqrt : Symbol(Math.sqrt, Decl(lib.es5.d.ts, --, --))
>s.side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
>s.side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 75, 21))
>side : Symbol(Triangle.side, Decl(exhaustiveSwitchStatements1.ts, 60, 38))
}
})();
return area;
>area : Symbol(area, Decl(exhaustiveSwitchStatements1.ts, 76, 7))
}
// Repro from #13241
enum MyEnum {
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
A,
>A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
B
>B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
}
function thisGivesError(e: MyEnum): string {
>thisGivesError : Symbol(thisGivesError, Decl(exhaustiveSwitchStatements1.ts, 93, 1))
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 95, 24))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
let s: string;
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 96, 4))
switch (e) {
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 95, 24))
case MyEnum.A: s = "it was A"; break;
>MyEnum.A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
>A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 96, 4))
case MyEnum.B: s = "it was B"; break;
>MyEnum.B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
>B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 96, 4))
}
return s;
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 96, 4))
}
function good1(e: MyEnum): string {
>good1 : Symbol(good1, Decl(exhaustiveSwitchStatements1.ts, 102, 1))
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 104, 15))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
let s: string;
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 105, 4))
switch (e) {
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 104, 15))
case MyEnum.A: s = "it was A"; break;
>MyEnum.A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
>A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 105, 4))
case MyEnum.B: s = "it was B"; break;
>MyEnum.B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
>B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 105, 4))
default: s = "it was something else"; break;
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 105, 4))
}
return s;
>s : Symbol(s, Decl(exhaustiveSwitchStatements1.ts, 105, 4))
}
function good2(e: MyEnum): string {
>good2 : Symbol(good2, Decl(exhaustiveSwitchStatements1.ts, 112, 1))
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 114, 15))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
switch (e) {
>e : Symbol(e, Decl(exhaustiveSwitchStatements1.ts, 114, 15))
case MyEnum.A: return "it was A";
>MyEnum.A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
>A : Symbol(MyEnum.A, Decl(exhaustiveSwitchStatements1.ts, 90, 13))
case MyEnum.B: return "it was B";
>MyEnum.B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
>MyEnum : Symbol(MyEnum, Decl(exhaustiveSwitchStatements1.ts, 86, 1))
>B : Symbol(MyEnum.B, Decl(exhaustiveSwitchStatements1.ts, 91, 3))
}
}
// Repro from #18362
enum Level {
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
One,
>One : Symbol(Level.One, Decl(exhaustiveSwitchStatements1.ts, 123, 12))
Two,
>Two : Symbol(Level.Two, Decl(exhaustiveSwitchStatements1.ts, 124, 6))
}
const doSomethingWithLevel = (level: Level) => {
>doSomethingWithLevel : Symbol(doSomethingWithLevel, Decl(exhaustiveSwitchStatements1.ts, 128, 5))
>level : Symbol(level, Decl(exhaustiveSwitchStatements1.ts, 128, 30))
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
let next: Level;
>next : Symbol(next, Decl(exhaustiveSwitchStatements1.ts, 129, 5))
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
switch (level) {
>level : Symbol(level, Decl(exhaustiveSwitchStatements1.ts, 128, 30))
case Level.One:
>Level.One : Symbol(Level.One, Decl(exhaustiveSwitchStatements1.ts, 123, 12))
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
>One : Symbol(Level.One, Decl(exhaustiveSwitchStatements1.ts, 123, 12))
next = Level.Two;
>next : Symbol(next, Decl(exhaustiveSwitchStatements1.ts, 129, 5))
>Level.Two : Symbol(Level.Two, Decl(exhaustiveSwitchStatements1.ts, 124, 6))
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
>Two : Symbol(Level.Two, Decl(exhaustiveSwitchStatements1.ts, 124, 6))
break;
case Level.Two:
>Level.Two : Symbol(Level.Two, Decl(exhaustiveSwitchStatements1.ts, 124, 6))
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
>Two : Symbol(Level.Two, Decl(exhaustiveSwitchStatements1.ts, 124, 6))
next = Level.One;
>next : Symbol(next, Decl(exhaustiveSwitchStatements1.ts, 129, 5))
>Level.One : Symbol(Level.One, Decl(exhaustiveSwitchStatements1.ts, 123, 12))
>Level : Symbol(Level, Decl(exhaustiveSwitchStatements1.ts, 119, 1))
>One : Symbol(Level.One, Decl(exhaustiveSwitchStatements1.ts, 123, 12))
break;
}
return next;
>next : Symbol(next, Decl(exhaustiveSwitchStatements1.ts, 129, 5))
};
// Repro from #20409
interface Square2 {
>Square2 : Symbol(Square2, Decl(exhaustiveSwitchStatements1.ts, 139, 2))
kind: "square";
>kind : Symbol(Square2.kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19))
size: number;
>size : Symbol(Square2.size, Decl(exhaustiveSwitchStatements1.ts, 144, 19))
}
interface Circle2 {
>Circle2 : Symbol(Circle2, Decl(exhaustiveSwitchStatements1.ts, 146, 1))
kind: "circle";
>kind : Symbol(Circle2.kind, Decl(exhaustiveSwitchStatements1.ts, 148, 19))
radius: number;
>radius : Symbol(Circle2.radius, Decl(exhaustiveSwitchStatements1.ts, 149, 19))
}
type Shape2 = Square2 | Circle2;
>Shape2 : Symbol(Shape2, Decl(exhaustiveSwitchStatements1.ts, 151, 1))
>Square2 : Symbol(Square2, Decl(exhaustiveSwitchStatements1.ts, 139, 2))
>Circle2 : Symbol(Circle2, Decl(exhaustiveSwitchStatements1.ts, 146, 1))
function withDefault(s1: Shape2, s2: Shape2): string {
>withDefault : Symbol(withDefault, Decl(exhaustiveSwitchStatements1.ts, 153, 32))
>s1 : Symbol(s1, Decl(exhaustiveSwitchStatements1.ts, 155, 21))
>Shape2 : Symbol(Shape2, Decl(exhaustiveSwitchStatements1.ts, 151, 1))
>s2 : Symbol(s2, Decl(exhaustiveSwitchStatements1.ts, 155, 32))
>Shape2 : Symbol(Shape2, Decl(exhaustiveSwitchStatements1.ts, 151, 1))
switch (s1.kind) {
>s1.kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
>s1 : Symbol(s1, Decl(exhaustiveSwitchStatements1.ts, 155, 21))
>kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
case "square":
return "1";
case "circle":
switch (s2.kind) {
>s2.kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
>s2 : Symbol(s2, Decl(exhaustiveSwitchStatements1.ts, 155, 32))
>kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
case "square":
return "2";
case "circle":
return "3";
default:
return "never";
}
}
}
function withoutDefault(s1: Shape2, s2: Shape2): string {
>withoutDefault : Symbol(withoutDefault, Decl(exhaustiveSwitchStatements1.ts, 169, 1))
>s1 : Symbol(s1, Decl(exhaustiveSwitchStatements1.ts, 171, 24))
>Shape2 : Symbol(Shape2, Decl(exhaustiveSwitchStatements1.ts, 151, 1))
>s2 : Symbol(s2, Decl(exhaustiveSwitchStatements1.ts, 171, 35))
>Shape2 : Symbol(Shape2, Decl(exhaustiveSwitchStatements1.ts, 151, 1))
switch (s1.kind) {
>s1.kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
>s1 : Symbol(s1, Decl(exhaustiveSwitchStatements1.ts, 171, 24))
>kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
case "square":
return "1";
case "circle":
switch (s2.kind) {
>s2.kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
>s2 : Symbol(s2, Decl(exhaustiveSwitchStatements1.ts, 171, 35))
>kind : Symbol(kind, Decl(exhaustiveSwitchStatements1.ts, 143, 19), Decl(exhaustiveSwitchStatements1.ts, 148, 19))
case "square":
return "2";
case "circle":
return "3";
}
}
}
// Repro from #20823
function test4(value: 1 | 2) {
>test4 : Symbol(test4, Decl(exhaustiveSwitchStatements1.ts, 183, 1))
>value : Symbol(value, Decl(exhaustiveSwitchStatements1.ts, 187, 15))
let x: string;
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 188, 7))
switch (value) {
>value : Symbol(value, Decl(exhaustiveSwitchStatements1.ts, 187, 15))
case 1: x = "one"; break;
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 188, 7))
case 2: x = "two"; break;
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 188, 7))
}
return x;
>x : Symbol(x, Decl(exhaustiveSwitchStatements1.ts, 188, 7))
}
@@ -0,0 +1,595 @@
=== tests/cases/conformance/controlFlow/exhaustiveSwitchStatements1.ts ===
function f1(x: 1 | 2): string {
>f1 : (x: 1 | 2) => string
>x : 1 | 2
if (!!true) {
>!!true : true
>!true : false
>true : true
switch (x) {
>x : 1 | 2
case 1: return 'a';
>1 : 1
>'a' : "a"
case 2: return 'b';
>2 : 2
>'b' : "b"
}
x; // Unreachable
>x : never
}
else {
throw 0;
>0 : 0
}
}
function f2(x: 1 | 2) {
>f2 : (x: 1 | 2) => void
>x : 1 | 2
let z: number;
>z : number
switch (x) {
>x : 1 | 2
case 1: z = 10; break;
>1 : 1
>z = 10 : 10
>z : number
>10 : 10
case 2: z = 20; break;
>2 : 2
>z = 20 : 20
>z : number
>20 : 20
}
z; // Definitely assigned
>z : number
}
function f3(x: 1 | 2) {
>f3 : (x: 1 | 2) => 10 | 20
>x : 1 | 2
switch (x) {
>x : 1 | 2
case 1: return 10;
>1 : 1
>10 : 10
case 2: return 20;
>2 : 2
>20 : 20
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
>new Error("Bad input") : Error
>Error : ErrorConstructor
>"Bad input" : "Bad input"
}
}
// Repro from #11572
enum E { A, B }
>E : E
>A : E.A
>B : E.B
function f(e: E): number {
>f : (e: E) => number
>e : E
switch (e) {
>e : E
case E.A: return 0
>E.A : E.A
>E : typeof E
>A : E.A
>0 : 0
case E.B: return 1
>E.B : E.B
>E : typeof E
>B : E.B
>1 : 1
}
}
function g(e: E): number {
>g : (e: E) => number
>e : E
if (!true)
>!true : false
>true : true
return -1
>-1 : -1
>1 : 1
else
switch (e) {
>e : E
case E.A: return 0
>E.A : E.A
>E : typeof E
>A : E.A
>0 : 0
case E.B: return 1
>E.B : E.B
>E : typeof E
>B : E.B
>1 : 1
}
}
// Repro from #12668
interface Square { kind: "square"; size: number; }
>kind : "square"
>size : number
interface Rectangle { kind: "rectangle"; width: number; height: number; }
>kind : "rectangle"
>width : number
>height : number
interface Circle { kind: "circle"; radius: number; }
>kind : "circle"
>radius : number
interface Triangle { kind: "triangle"; side: number; }
>kind : "triangle"
>side : number
type Shape = Square | Rectangle | Circle | Triangle;
>Shape : Shape
function area(s: Shape): number {
>area : (s: Shape) => number
>s : Shape
let area;
>area : any
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle" | "triangle"
>s : Shape
>kind : "square" | "rectangle" | "circle" | "triangle"
case "square": area = s.size * s.size; break;
>"square" : "square"
>area = s.size * s.size : number
>area : any
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": area = s.width * s.height; break;
>"rectangle" : "rectangle"
>area = s.width * s.height : number
>area : any
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": area = Math.PI * s.radius * s.radius; break;
>"circle" : "circle"
>area = Math.PI * s.radius * s.radius : number
>area : any
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
case "triangle": area = Math.sqrt(3) / 4 * s.side * s.side; break;
>"triangle" : "triangle"
>area = Math.sqrt(3) / 4 * s.side * s.side : number
>area : any
>Math.sqrt(3) / 4 * s.side * s.side : number
>Math.sqrt(3) / 4 * s.side : number
>Math.sqrt(3) / 4 : number
>Math.sqrt(3) : number
>Math.sqrt : (x: number) => number
>Math : Math
>sqrt : (x: number) => number
>3 : 3
>4 : 4
>s.side : number
>s : Triangle
>side : number
>s.side : number
>s : Triangle
>side : number
}
return area;
>area : number
}
function areaWrapped(s: Shape): number {
>areaWrapped : (s: Shape) => number
>s : Shape
let area;
>area : any
area = (() => {
>area = (() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } })() : number
>area : any
>(() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } })() : number
>(() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } }) : () => number
>() => { switch (s.kind) { case "square": return s.size * s.size; case "rectangle": return s.width * s.height; case "circle": return Math.PI * s.radius * s.radius; case "triangle": return Math.sqrt(3) / 4 * s.side * s.side; } } : () => number
switch (s.kind) {
>s.kind : "square" | "rectangle" | "circle" | "triangle"
>s : Shape
>kind : "square" | "rectangle" | "circle" | "triangle"
case "square": return s.size * s.size;
>"square" : "square"
>s.size * s.size : number
>s.size : number
>s : Square
>size : number
>s.size : number
>s : Square
>size : number
case "rectangle": return s.width * s.height;
>"rectangle" : "rectangle"
>s.width * s.height : number
>s.width : number
>s : Rectangle
>width : number
>s.height : number
>s : Rectangle
>height : number
case "circle": return Math.PI * s.radius * s.radius;
>"circle" : "circle"
>Math.PI * s.radius * s.radius : number
>Math.PI * s.radius : number
>Math.PI : number
>Math : Math
>PI : number
>s.radius : number
>s : Circle
>radius : number
>s.radius : number
>s : Circle
>radius : number
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
>"triangle" : "triangle"
>Math.sqrt(3) / 4 * s.side * s.side : number
>Math.sqrt(3) / 4 * s.side : number
>Math.sqrt(3) / 4 : number
>Math.sqrt(3) : number
>Math.sqrt : (x: number) => number
>Math : Math
>sqrt : (x: number) => number
>3 : 3
>4 : 4
>s.side : number
>s : Triangle
>side : number
>s.side : number
>s : Triangle
>side : number
}
})();
return area;
>area : number
}
// Repro from #13241
enum MyEnum {
>MyEnum : MyEnum
A,
>A : MyEnum.A
B
>B : MyEnum.B
}
function thisGivesError(e: MyEnum): string {
>thisGivesError : (e: MyEnum) => string
>e : MyEnum
let s: string;
>s : string
switch (e) {
>e : MyEnum
case MyEnum.A: s = "it was A"; break;
>MyEnum.A : MyEnum.A
>MyEnum : typeof MyEnum
>A : MyEnum.A
>s = "it was A" : "it was A"
>s : string
>"it was A" : "it was A"
case MyEnum.B: s = "it was B"; break;
>MyEnum.B : MyEnum.B
>MyEnum : typeof MyEnum
>B : MyEnum.B
>s = "it was B" : "it was B"
>s : string
>"it was B" : "it was B"
}
return s;
>s : string
}
function good1(e: MyEnum): string {
>good1 : (e: MyEnum) => string
>e : MyEnum
let s: string;
>s : string
switch (e) {
>e : MyEnum
case MyEnum.A: s = "it was A"; break;
>MyEnum.A : MyEnum.A
>MyEnum : typeof MyEnum
>A : MyEnum.A
>s = "it was A" : "it was A"
>s : string
>"it was A" : "it was A"
case MyEnum.B: s = "it was B"; break;
>MyEnum.B : MyEnum.B
>MyEnum : typeof MyEnum
>B : MyEnum.B
>s = "it was B" : "it was B"
>s : string
>"it was B" : "it was B"
default: s = "it was something else"; break;
>s = "it was something else" : "it was something else"
>s : string
>"it was something else" : "it was something else"
}
return s;
>s : string
}
function good2(e: MyEnum): string {
>good2 : (e: MyEnum) => string
>e : MyEnum
switch (e) {
>e : MyEnum
case MyEnum.A: return "it was A";
>MyEnum.A : MyEnum.A
>MyEnum : typeof MyEnum
>A : MyEnum.A
>"it was A" : "it was A"
case MyEnum.B: return "it was B";
>MyEnum.B : MyEnum.B
>MyEnum : typeof MyEnum
>B : MyEnum.B
>"it was B" : "it was B"
}
}
// Repro from #18362
enum Level {
>Level : Level
One,
>One : Level.One
Two,
>Two : Level.Two
}
const doSomethingWithLevel = (level: Level) => {
>doSomethingWithLevel : (level: Level) => Level
>(level: Level) => { let next: Level; switch (level) { case Level.One: next = Level.Two; break; case Level.Two: next = Level.One; break; } return next;} : (level: Level) => Level
>level : Level
let next: Level;
>next : Level
switch (level) {
>level : Level
case Level.One:
>Level.One : Level.One
>Level : typeof Level
>One : Level.One
next = Level.Two;
>next = Level.Two : Level.Two
>next : Level
>Level.Two : Level.Two
>Level : typeof Level
>Two : Level.Two
break;
case Level.Two:
>Level.Two : Level.Two
>Level : typeof Level
>Two : Level.Two
next = Level.One;
>next = Level.One : Level.One
>next : Level
>Level.One : Level.One
>Level : typeof Level
>One : Level.One
break;
}
return next;
>next : Level
};
// Repro from #20409
interface Square2 {
kind: "square";
>kind : "square"
size: number;
>size : number
}
interface Circle2 {
kind: "circle";
>kind : "circle"
radius: number;
>radius : number
}
type Shape2 = Square2 | Circle2;
>Shape2 : Shape2
function withDefault(s1: Shape2, s2: Shape2): string {
>withDefault : (s1: Shape2, s2: Shape2) => string
>s1 : Shape2
>s2 : Shape2
switch (s1.kind) {
>s1.kind : "square" | "circle"
>s1 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "1";
>"1" : "1"
case "circle":
>"circle" : "circle"
switch (s2.kind) {
>s2.kind : "square" | "circle"
>s2 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "2";
>"2" : "2"
case "circle":
>"circle" : "circle"
return "3";
>"3" : "3"
default:
return "never";
>"never" : "never"
}
}
}
function withoutDefault(s1: Shape2, s2: Shape2): string {
>withoutDefault : (s1: Shape2, s2: Shape2) => string
>s1 : Shape2
>s2 : Shape2
switch (s1.kind) {
>s1.kind : "square" | "circle"
>s1 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "1";
>"1" : "1"
case "circle":
>"circle" : "circle"
switch (s2.kind) {
>s2.kind : "square" | "circle"
>s2 : Shape2
>kind : "square" | "circle"
case "square":
>"square" : "square"
return "2";
>"2" : "2"
case "circle":
>"circle" : "circle"
return "3";
>"3" : "3"
}
}
}
// Repro from #20823
function test4(value: 1 | 2) {
>test4 : (value: 1 | 2) => string
>value : 1 | 2
let x: string;
>x : string
switch (value) {
>value : 1 | 2
case 1: x = "one"; break;
>1 : 1
>x = "one" : "one"
>x : string
>"one" : "one"
case 2: x = "two"; break;
>2 : 2
>x = "two" : "two"
>x : string
>"two" : "two"
}
return x;
>x : string
}
@@ -0,0 +1,227 @@
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(13,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(19,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(30,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(36,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(51,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(57,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(63,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(77,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(82,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(89,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(96,13): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(101,13): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(103,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(105,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(111,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(112,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(122,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(127,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(129,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(139,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(141,5): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(148,9): error TS7027: Unreachable code detected.
tests/cases/conformance/controlFlow/neverReturningFunctions1.ts(153,5): error TS7027: Unreachable code detected.
==== tests/cases/conformance/controlFlow/neverReturningFunctions1.ts (23 errors) ====
function fail(message?: string): never {
throw new Error(message);
}
function f01(x: string | undefined) {
if (x === undefined) fail("undefined argument");
x.length; // string
}
function f02(x: number): number {
if (x >= 0) return x;
fail("negative number");
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f03(x: string) {
x; // string
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f11(x: string | undefined, fail: (message?: string) => never) {
if (x === undefined) fail("undefined argument");
x.length; // string
}
function f12(x: number, fail: (message?: string) => never): number {
if (x >= 0) return x;
fail("negative number");
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f13(x: string, fail: (message?: string) => never) {
x; // string
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
namespace Debug {
export declare function fail(message?: string): never;
}
function f21(x: string | undefined) {
if (x === undefined) Debug.fail("undefined argument");
x.length; // string
}
function f22(x: number): number {
if (x >= 0) return x;
Debug.fail("negative number");
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f23(x: string) {
x; // string
Debug.fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f24(x: string) {
x; // string
((Debug).fail)();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
class Test {
fail(message?: string): never {
throw new Error(message);
}
f1(x: string | undefined) {
if (x === undefined) this.fail("undefined argument");
x.length; // string
}
f2(x: number): number {
if (x >= 0) return x;
this.fail("negative number");
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
f3(x: string) {
x; // string
this.fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
}
function f30(x: string | number | undefined) {
if (typeof x === "string") {
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
else {
x; // number | undefined
if (x !== undefined) {
x; // number
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
else {
x; // undefined
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f31(x: { a: string | number }) {
if (typeof x.a === "string") {
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
x.a; // Unreachable
~~~~
!!! error TS7027: Unreachable code detected.
}
x; // { a: string | number }
x.a; // number
}
function f40(x: number) {
try {
x;
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
finally {
x;
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f41(x: number) {
try {
x;
}
finally {
x;
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
function f42(x: number) {
try {
x;
fail();
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
finally {
x;
}
x; // Unreachable
~~
!!! error TS7027: Unreachable code detected.
}
@@ -0,0 +1,337 @@
//// [neverReturningFunctions1.ts]
function fail(message?: string): never {
throw new Error(message);
}
function f01(x: string | undefined) {
if (x === undefined) fail("undefined argument");
x.length; // string
}
function f02(x: number): number {
if (x >= 0) return x;
fail("negative number");
x; // Unreachable
}
function f03(x: string) {
x; // string
fail();
x; // Unreachable
}
function f11(x: string | undefined, fail: (message?: string) => never) {
if (x === undefined) fail("undefined argument");
x.length; // string
}
function f12(x: number, fail: (message?: string) => never): number {
if (x >= 0) return x;
fail("negative number");
x; // Unreachable
}
function f13(x: string, fail: (message?: string) => never) {
x; // string
fail();
x; // Unreachable
}
namespace Debug {
export declare function fail(message?: string): never;
}
function f21(x: string | undefined) {
if (x === undefined) Debug.fail("undefined argument");
x.length; // string
}
function f22(x: number): number {
if (x >= 0) return x;
Debug.fail("negative number");
x; // Unreachable
}
function f23(x: string) {
x; // string
Debug.fail();
x; // Unreachable
}
function f24(x: string) {
x; // string
((Debug).fail)();
x; // Unreachable
}
class Test {
fail(message?: string): never {
throw new Error(message);
}
f1(x: string | undefined) {
if (x === undefined) this.fail("undefined argument");
x.length; // string
}
f2(x: number): number {
if (x >= 0) return x;
this.fail("negative number");
x; // Unreachable
}
f3(x: string) {
x; // string
this.fail();
x; // Unreachable
}
}
function f30(x: string | number | undefined) {
if (typeof x === "string") {
fail();
x; // Unreachable
}
else {
x; // number | undefined
if (x !== undefined) {
x; // number
fail();
x; // Unreachable
}
else {
x; // undefined
fail();
x; // Unreachable
}
x; // Unreachable
}
x; // Unreachable
}
function f31(x: { a: string | number }) {
if (typeof x.a === "string") {
fail();
x; // Unreachable
x.a; // Unreachable
}
x; // { a: string | number }
x.a; // number
}
function f40(x: number) {
try {
x;
fail();
x; // Unreachable
}
finally {
x;
fail();
x; // Unreachable
}
x; // Unreachable
}
function f41(x: number) {
try {
x;
}
finally {
x;
fail();
x; // Unreachable
}
x; // Unreachable
}
function f42(x: number) {
try {
x;
fail();
x; // Unreachable
}
finally {
x;
}
x; // Unreachable
}
//// [neverReturningFunctions1.js]
"use strict";
function fail(message) {
throw new Error(message);
}
function f01(x) {
if (x === undefined)
fail("undefined argument");
x.length; // string
}
function f02(x) {
if (x >= 0)
return x;
fail("negative number");
x; // Unreachable
}
function f03(x) {
x; // string
fail();
x; // Unreachable
}
function f11(x, fail) {
if (x === undefined)
fail("undefined argument");
x.length; // string
}
function f12(x, fail) {
if (x >= 0)
return x;
fail("negative number");
x; // Unreachable
}
function f13(x, fail) {
x; // string
fail();
x; // Unreachable
}
var Debug;
(function (Debug) {
})(Debug || (Debug = {}));
function f21(x) {
if (x === undefined)
Debug.fail("undefined argument");
x.length; // string
}
function f22(x) {
if (x >= 0)
return x;
Debug.fail("negative number");
x; // Unreachable
}
function f23(x) {
x; // string
Debug.fail();
x; // Unreachable
}
function f24(x) {
x; // string
((Debug).fail)();
x; // Unreachable
}
var Test = /** @class */ (function () {
function Test() {
}
Test.prototype.fail = function (message) {
throw new Error(message);
};
Test.prototype.f1 = function (x) {
if (x === undefined)
this.fail("undefined argument");
x.length; // string
};
Test.prototype.f2 = function (x) {
if (x >= 0)
return x;
this.fail("negative number");
x; // Unreachable
};
Test.prototype.f3 = function (x) {
x; // string
this.fail();
x; // Unreachable
};
return Test;
}());
function f30(x) {
if (typeof x === "string") {
fail();
x; // Unreachable
}
else {
x; // number | undefined
if (x !== undefined) {
x; // number
fail();
x; // Unreachable
}
else {
x; // undefined
fail();
x; // Unreachable
}
x; // Unreachable
}
x; // Unreachable
}
function f31(x) {
if (typeof x.a === "string") {
fail();
x; // Unreachable
x.a; // Unreachable
}
x; // { a: string | number }
x.a; // number
}
function f40(x) {
try {
x;
fail();
x; // Unreachable
}
finally {
x;
fail();
x; // Unreachable
}
x; // Unreachable
}
function f41(x) {
try {
x;
}
finally {
x;
fail();
x; // Unreachable
}
x; // Unreachable
}
function f42(x) {
try {
x;
fail();
x; // Unreachable
}
finally {
x;
}
x; // Unreachable
}
//// [neverReturningFunctions1.d.ts]
declare function fail(message?: string): never;
declare function f01(x: string | undefined): void;
declare function f02(x: number): number;
declare function f03(x: string): void;
declare function f11(x: string | undefined, fail: (message?: string) => never): void;
declare function f12(x: number, fail: (message?: string) => never): number;
declare function f13(x: string, fail: (message?: string) => never): void;
declare namespace Debug {
function fail(message?: string): never;
}
declare function f21(x: string | undefined): void;
declare function f22(x: number): number;
declare function f23(x: string): void;
declare function f24(x: string): void;
declare class Test {
fail(message?: string): never;
f1(x: string | undefined): void;
f2(x: number): number;
f3(x: string): void;
}
declare function f30(x: string | number | undefined): void;
declare function f31(x: {
a: string | number;
}): void;
declare function f40(x: number): void;
declare function f41(x: number): void;
declare function f42(x: number): void;
@@ -0,0 +1,387 @@
=== tests/cases/conformance/controlFlow/neverReturningFunctions1.ts ===
function fail(message?: string): never {
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 0, 14))
throw new Error(message);
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 0, 14))
}
function f01(x: string | undefined) {
>f01 : Symbol(f01, Decl(neverReturningFunctions1.ts, 2, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 4, 13))
if (x === undefined) fail("undefined argument");
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 4, 13))
>undefined : Symbol(undefined)
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x.length; // string
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 4, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
function f02(x: number): number {
>f02 : Symbol(f02, Decl(neverReturningFunctions1.ts, 7, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 9, 13))
if (x >= 0) return x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 9, 13))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 9, 13))
fail("negative number");
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 9, 13))
}
function f03(x: string) {
>f03 : Symbol(f03, Decl(neverReturningFunctions1.ts, 13, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 15, 13))
x; // string
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 15, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 15, 13))
}
function f11(x: string | undefined, fail: (message?: string) => never) {
>f11 : Symbol(f11, Decl(neverReturningFunctions1.ts, 19, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 21, 13))
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 21, 35))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 21, 43))
if (x === undefined) fail("undefined argument");
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 21, 13))
>undefined : Symbol(undefined)
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 21, 35))
x.length; // string
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 21, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
function f12(x: number, fail: (message?: string) => never): number {
>f12 : Symbol(f12, Decl(neverReturningFunctions1.ts, 24, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 26, 13))
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 26, 23))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 26, 31))
if (x >= 0) return x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 26, 13))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 26, 13))
fail("negative number");
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 26, 23))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 26, 13))
}
function f13(x: string, fail: (message?: string) => never) {
>f13 : Symbol(f13, Decl(neverReturningFunctions1.ts, 30, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 32, 13))
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 32, 23))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 32, 31))
x; // string
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 32, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 32, 23))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 32, 13))
}
namespace Debug {
>Debug : Symbol(Debug, Decl(neverReturningFunctions1.ts, 36, 1))
export declare function fail(message?: string): never;
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 38, 17))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 39, 33))
}
function f21(x: string | undefined) {
>f21 : Symbol(f21, Decl(neverReturningFunctions1.ts, 40, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 42, 13))
if (x === undefined) Debug.fail("undefined argument");
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 42, 13))
>undefined : Symbol(undefined)
>Debug.fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
>Debug : Symbol(Debug, Decl(neverReturningFunctions1.ts, 36, 1))
>fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
x.length; // string
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 42, 13))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
function f22(x: number): number {
>f22 : Symbol(f22, Decl(neverReturningFunctions1.ts, 45, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 47, 13))
if (x >= 0) return x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 47, 13))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 47, 13))
Debug.fail("negative number");
>Debug.fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
>Debug : Symbol(Debug, Decl(neverReturningFunctions1.ts, 36, 1))
>fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 47, 13))
}
function f23(x: string) {
>f23 : Symbol(f23, Decl(neverReturningFunctions1.ts, 51, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 53, 13))
x; // string
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 53, 13))
Debug.fail();
>Debug.fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
>Debug : Symbol(Debug, Decl(neverReturningFunctions1.ts, 36, 1))
>fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 53, 13))
}
function f24(x: string) {
>f24 : Symbol(f24, Decl(neverReturningFunctions1.ts, 57, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 59, 13))
x; // string
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 59, 13))
((Debug).fail)();
>(Debug).fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
>Debug : Symbol(Debug, Decl(neverReturningFunctions1.ts, 36, 1))
>fail : Symbol(Debug.fail, Decl(neverReturningFunctions1.ts, 38, 17))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 59, 13))
}
class Test {
>Test : Symbol(Test, Decl(neverReturningFunctions1.ts, 63, 1))
fail(message?: string): never {
>fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 66, 9))
throw new Error(message);
>Error : Symbol(Error, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
>message : Symbol(message, Decl(neverReturningFunctions1.ts, 66, 9))
}
f1(x: string | undefined) {
>f1 : Symbol(Test.f1, Decl(neverReturningFunctions1.ts, 68, 5))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 69, 7))
if (x === undefined) this.fail("undefined argument");
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 69, 7))
>undefined : Symbol(undefined)
>this.fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
>this : Symbol(Test, Decl(neverReturningFunctions1.ts, 63, 1))
>fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
x.length; // string
>x.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 69, 7))
>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --))
}
f2(x: number): number {
>f2 : Symbol(Test.f2, Decl(neverReturningFunctions1.ts, 72, 5))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 73, 7))
if (x >= 0) return x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 73, 7))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 73, 7))
this.fail("negative number");
>this.fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
>this : Symbol(Test, Decl(neverReturningFunctions1.ts, 63, 1))
>fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 73, 7))
}
f3(x: string) {
>f3 : Symbol(Test.f3, Decl(neverReturningFunctions1.ts, 77, 5))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 78, 7))
x; // string
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 78, 7))
this.fail();
>this.fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
>this : Symbol(Test, Decl(neverReturningFunctions1.ts, 63, 1))
>fail : Symbol(Test.fail, Decl(neverReturningFunctions1.ts, 65, 12))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 78, 7))
}
}
function f30(x: string | number | undefined) {
>f30 : Symbol(f30, Decl(neverReturningFunctions1.ts, 83, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
if (typeof x === "string") {
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
}
else {
x; // number | undefined
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
if (x !== undefined) {
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
>undefined : Symbol(undefined)
x; // number
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
}
else {
x; // undefined
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
}
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
}
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 85, 13))
}
function f31(x: { a: string | number }) {
>f31 : Symbol(f31, Decl(neverReturningFunctions1.ts, 105, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 107, 13))
>a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
if (typeof x.a === "string") {
>x.a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 107, 13))
>a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 107, 13))
x.a; // Unreachable
>x.a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 107, 13))
>a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
}
x; // { a: string | number }
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 107, 13))
x.a; // number
>x.a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 107, 13))
>a : Symbol(a, Decl(neverReturningFunctions1.ts, 107, 17))
}
function f40(x: number) {
>f40 : Symbol(f40, Decl(neverReturningFunctions1.ts, 115, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 117, 13))
try {
x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 117, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 117, 13))
}
finally {
x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 117, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 117, 13))
}
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 117, 13))
}
function f41(x: number) {
>f41 : Symbol(f41, Decl(neverReturningFunctions1.ts, 129, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 131, 13))
try {
x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 131, 13))
}
finally {
x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 131, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 131, 13))
}
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 131, 13))
}
function f42(x: number) {
>f42 : Symbol(f42, Decl(neverReturningFunctions1.ts, 141, 1))
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13))
try {
x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13))
fail();
>fail : Symbol(fail, Decl(neverReturningFunctions1.ts, 0, 0))
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13))
}
finally {
x;
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13))
}
x; // Unreachable
>x : Symbol(x, Decl(neverReturningFunctions1.ts, 143, 13))
}
@@ -0,0 +1,439 @@
=== tests/cases/conformance/controlFlow/neverReturningFunctions1.ts ===
function fail(message?: string): never {
>fail : (message?: string | undefined) => never
>message : string | undefined
throw new Error(message);
>new Error(message) : Error
>Error : ErrorConstructor
>message : string | undefined
}
function f01(x: string | undefined) {
>f01 : (x: string | undefined) => void
>x : string | undefined
if (x === undefined) fail("undefined argument");
>x === undefined : boolean
>x : string | undefined
>undefined : undefined
>fail("undefined argument") : never
>fail : (message?: string | undefined) => never
>"undefined argument" : "undefined argument"
x.length; // string
>x.length : number
>x : string
>length : number
}
function f02(x: number): number {
>f02 : (x: number) => number
>x : number
if (x >= 0) return x;
>x >= 0 : boolean
>x : number
>0 : 0
>x : number
fail("negative number");
>fail("negative number") : never
>fail : (message?: string | undefined) => never
>"negative number" : "negative number"
x; // Unreachable
>x : number
}
function f03(x: string) {
>f03 : (x: string) => void
>x : string
x; // string
>x : string
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string
}
function f11(x: string | undefined, fail: (message?: string) => never) {
>f11 : (x: string | undefined, fail: (message?: string | undefined) => never) => void
>x : string | undefined
>fail : (message?: string | undefined) => never
>message : string | undefined
if (x === undefined) fail("undefined argument");
>x === undefined : boolean
>x : string | undefined
>undefined : undefined
>fail("undefined argument") : never
>fail : (message?: string | undefined) => never
>"undefined argument" : "undefined argument"
x.length; // string
>x.length : number
>x : string
>length : number
}
function f12(x: number, fail: (message?: string) => never): number {
>f12 : (x: number, fail: (message?: string | undefined) => never) => number
>x : number
>fail : (message?: string | undefined) => never
>message : string | undefined
if (x >= 0) return x;
>x >= 0 : boolean
>x : number
>0 : 0
>x : number
fail("negative number");
>fail("negative number") : never
>fail : (message?: string | undefined) => never
>"negative number" : "negative number"
x; // Unreachable
>x : number
}
function f13(x: string, fail: (message?: string) => never) {
>f13 : (x: string, fail: (message?: string | undefined) => never) => void
>x : string
>fail : (message?: string | undefined) => never
>message : string | undefined
x; // string
>x : string
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string
}
namespace Debug {
>Debug : typeof Debug
export declare function fail(message?: string): never;
>fail : (message?: string | undefined) => never
>message : string | undefined
}
function f21(x: string | undefined) {
>f21 : (x: string | undefined) => void
>x : string | undefined
if (x === undefined) Debug.fail("undefined argument");
>x === undefined : boolean
>x : string | undefined
>undefined : undefined
>Debug.fail("undefined argument") : never
>Debug.fail : (message?: string | undefined) => never
>Debug : typeof Debug
>fail : (message?: string | undefined) => never
>"undefined argument" : "undefined argument"
x.length; // string
>x.length : number
>x : string
>length : number
}
function f22(x: number): number {
>f22 : (x: number) => number
>x : number
if (x >= 0) return x;
>x >= 0 : boolean
>x : number
>0 : 0
>x : number
Debug.fail("negative number");
>Debug.fail("negative number") : never
>Debug.fail : (message?: string | undefined) => never
>Debug : typeof Debug
>fail : (message?: string | undefined) => never
>"negative number" : "negative number"
x; // Unreachable
>x : number
}
function f23(x: string) {
>f23 : (x: string) => void
>x : string
x; // string
>x : string
Debug.fail();
>Debug.fail() : never
>Debug.fail : (message?: string | undefined) => never
>Debug : typeof Debug
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string
}
function f24(x: string) {
>f24 : (x: string) => void
>x : string
x; // string
>x : string
((Debug).fail)();
>((Debug).fail)() : never
>((Debug).fail) : (message?: string | undefined) => never
>(Debug).fail : (message?: string | undefined) => never
>(Debug) : typeof Debug
>Debug : typeof Debug
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string
}
class Test {
>Test : Test
fail(message?: string): never {
>fail : (message?: string | undefined) => never
>message : string | undefined
throw new Error(message);
>new Error(message) : Error
>Error : ErrorConstructor
>message : string | undefined
}
f1(x: string | undefined) {
>f1 : (x: string | undefined) => void
>x : string | undefined
if (x === undefined) this.fail("undefined argument");
>x === undefined : boolean
>x : string | undefined
>undefined : undefined
>this.fail("undefined argument") : never
>this.fail : (message?: string | undefined) => never
>this : this
>fail : (message?: string | undefined) => never
>"undefined argument" : "undefined argument"
x.length; // string
>x.length : number
>x : string
>length : number
}
f2(x: number): number {
>f2 : (x: number) => number
>x : number
if (x >= 0) return x;
>x >= 0 : boolean
>x : number
>0 : 0
>x : number
this.fail("negative number");
>this.fail("negative number") : never
>this.fail : (message?: string | undefined) => never
>this : this
>fail : (message?: string | undefined) => never
>"negative number" : "negative number"
x; // Unreachable
>x : number
}
f3(x: string) {
>f3 : (x: string) => void
>x : string
x; // string
>x : string
this.fail();
>this.fail() : never
>this.fail : (message?: string | undefined) => never
>this : this
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string
}
}
function f30(x: string | number | undefined) {
>f30 : (x: string | number | undefined) => void
>x : string | number | undefined
if (typeof x === "string") {
>typeof x === "string" : boolean
>typeof x : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x : string | number | undefined
>"string" : "string"
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string | number | undefined
}
else {
x; // number | undefined
>x : number | undefined
if (x !== undefined) {
>x !== undefined : boolean
>x : number | undefined
>undefined : undefined
x; // number
>x : number
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string | number | undefined
}
else {
x; // undefined
>x : undefined
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : string | number | undefined
}
x; // Unreachable
>x : string | number | undefined
}
x; // Unreachable
>x : string | number | undefined
}
function f31(x: { a: string | number }) {
>f31 : (x: { a: string | number; }) => void
>x : { a: string | number; }
>a : string | number
if (typeof x.a === "string") {
>typeof x.a === "string" : boolean
>typeof x.a : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>x.a : string | number
>x : { a: string | number; }
>a : string | number
>"string" : "string"
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : { a: string | number; }
x.a; // Unreachable
>x.a : string | number
>x : { a: string | number; }
>a : string | number
}
x; // { a: string | number }
>x : { a: string | number; }
x.a; // number
>x.a : number
>x : { a: string | number; }
>a : number
}
function f40(x: number) {
>f40 : (x: number) => void
>x : number
try {
x;
>x : number
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : number
}
finally {
x;
>x : number
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : number
}
x; // Unreachable
>x : number
}
function f41(x: number) {
>f41 : (x: number) => void
>x : number
try {
x;
>x : number
}
finally {
x;
>x : number
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : number
}
x; // Unreachable
>x : number
}
function f42(x: number) {
>f42 : (x: number) => void
>x : number
try {
x;
>x : number
fail();
>fail() : never
>fail : (message?: string | undefined) => never
x; // Unreachable
>x : number
}
finally {
x;
>x : number
}
x; // Unreachable
>x : number
}
@@ -40,3 +40,17 @@ function foo5(bar: "a" | "b"): number {
return 1;
}
}
function foo6(bar: "a", a: boolean, b: boolean): number {
if (a) {
switch (bar) {
case "a": return 1;
}
}
else {
switch (b) {
case true: return -1;
case false: return 0;
}
}
}
@@ -0,0 +1,128 @@
// @strict: true
// @declaration: true
declare function isString(value: unknown): value is string;
declare function isArrayOfStrings(value: unknown): value is string[];
const assert: (value: unknown) => asserts value = value => {}
declare function assertIsString(value: unknown): asserts value is string;
declare function assertIsArrayOfStrings(value: unknown): asserts value is string[];
declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
function f01(x: unknown) {
if (!!true) {
assert(typeof x === "string");
x.length;
}
if (!!true) {
assert(x instanceof Error);
x.message;
}
if (!!true) {
assert(typeof x === "boolean" || typeof x === "number");
x.toLocaleString;
}
if (!!true) {
assert(isArrayOfStrings(x));
x[0].length;
}
if (!!true) {
assertIsArrayOfStrings(x);
x[0].length;
}
if (!!true) {
assert(x === undefined || typeof x === "string");
x; // string | undefined
assertDefined(x);
x; // string
}
}
function f02(x: string | undefined) {
if (!!true) {
assert(x);
x.length;
}
if (!!true) {
assert(x !== undefined);
x.length;
}
if (!!true) {
assertDefined(x);
x.length;
}
}
function f03(x: string | undefined, assert: (value: unknown) => asserts value) {
assert(x);
x.length;
}
namespace Debug {
export declare function assert(value: unknown, message?: string): asserts value;
export declare function assertDefined<T>(value: T): asserts value is NonNullable<T>;
}
function f10(x: string | undefined) {
if (!!true) {
Debug.assert(x);
x.length;
}
if (!!true) {
Debug.assert(x !== undefined);
x.length;
}
if (!!true) {
Debug.assertDefined(x);
x.length;
}
}
class Test {
assert(value: unknown): asserts value {
if (value) return;
throw new Error();
}
isTest2(): this is Test2 {
return this instanceof Test2;
}
assertIsTest2(): asserts this is Test2 {
if (this instanceof Test2) return;
throw new Error();
}
assertThis(): asserts this {
if (!this) return;
throw new Error();
}
bar() {
this.assertThis();
this;
}
foo(x: unknown) {
this.assert(typeof x === "string");
x.length;
if (this.isTest2()) {
this.z;
}
this.assertIsTest2();
this.z;
}
}
class Test2 extends Test {
z = 0;
}
// Invalid constructs
declare let Q1: new (x: unknown) => x is string;
declare let Q2: new (x: boolean) => asserts x;
declare let Q3: new (x: unknown) => asserts x is string;
declare class Wat {
get p1(): this is string;
set p1(x: this is string);
get p2(): asserts this is string;
set p2(x: asserts this is string);
}
@@ -0,0 +1,199 @@
// @strict: true
// @allowUnreachableCode: false
// @declaration: true
function f1(x: 1 | 2): string {
if (!!true) {
switch (x) {
case 1: return 'a';
case 2: return 'b';
}
x; // Unreachable
}
else {
throw 0;
}
}
function f2(x: 1 | 2) {
let z: number;
switch (x) {
case 1: z = 10; break;
case 2: z = 20; break;
}
z; // Definitely assigned
}
function f3(x: 1 | 2) {
switch (x) {
case 1: return 10;
case 2: return 20;
// Default considered reachable to allow defensive coding
default: throw new Error("Bad input");
}
}
// Repro from #11572
enum E { A, B }
function f(e: E): number {
switch (e) {
case E.A: return 0
case E.B: return 1
}
}
function g(e: E): number {
if (!true)
return -1
else
switch (e) {
case E.A: return 0
case E.B: return 1
}
}
// Repro from #12668
interface Square { kind: "square"; size: number; }
interface Rectangle { kind: "rectangle"; width: number; height: number; }
interface Circle { kind: "circle"; radius: number; }
interface Triangle { kind: "triangle"; side: number; }
type Shape = Square | Rectangle | Circle | Triangle;
function area(s: Shape): number {
let area;
switch (s.kind) {
case "square": area = s.size * s.size; break;
case "rectangle": area = s.width * s.height; break;
case "circle": area = Math.PI * s.radius * s.radius; break;
case "triangle": area = Math.sqrt(3) / 4 * s.side * s.side; break;
}
return area;
}
function areaWrapped(s: Shape): number {
let area;
area = (() => {
switch (s.kind) {
case "square": return s.size * s.size;
case "rectangle": return s.width * s.height;
case "circle": return Math.PI * s.radius * s.radius;
case "triangle": return Math.sqrt(3) / 4 * s.side * s.side;
}
})();
return area;
}
// Repro from #13241
enum MyEnum {
A,
B
}
function thisGivesError(e: MyEnum): string {
let s: string;
switch (e) {
case MyEnum.A: s = "it was A"; break;
case MyEnum.B: s = "it was B"; break;
}
return s;
}
function good1(e: MyEnum): string {
let s: string;
switch (e) {
case MyEnum.A: s = "it was A"; break;
case MyEnum.B: s = "it was B"; break;
default: s = "it was something else"; break;
}
return s;
}
function good2(e: MyEnum): string {
switch (e) {
case MyEnum.A: return "it was A";
case MyEnum.B: return "it was B";
}
}
// Repro from #18362
enum Level {
One,
Two,
}
const doSomethingWithLevel = (level: Level) => {
let next: Level;
switch (level) {
case Level.One:
next = Level.Two;
break;
case Level.Two:
next = Level.One;
break;
}
return next;
};
// Repro from #20409
interface Square2 {
kind: "square";
size: number;
}
interface Circle2 {
kind: "circle";
radius: number;
}
type Shape2 = Square2 | Circle2;
function withDefault(s1: Shape2, s2: Shape2): string {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
default:
return "never";
}
}
}
function withoutDefault(s1: Shape2, s2: Shape2): string {
switch (s1.kind) {
case "square":
return "1";
case "circle":
switch (s2.kind) {
case "square":
return "2";
case "circle":
return "3";
}
}
}
// Repro from #20823
function test4(value: 1 | 2) {
let x: string;
switch (value) {
case 1: x = "one"; break;
case 2: x = "two"; break;
}
return x;
}
@@ -0,0 +1,158 @@
// @strict: true
// @allowUnreachableCode: false
// @declaration: true
function fail(message?: string): never {
throw new Error(message);
}
function f01(x: string | undefined) {
if (x === undefined) fail("undefined argument");
x.length; // string
}
function f02(x: number): number {
if (x >= 0) return x;
fail("negative number");
x; // Unreachable
}
function f03(x: string) {
x; // string
fail();
x; // Unreachable
}
function f11(x: string | undefined, fail: (message?: string) => never) {
if (x === undefined) fail("undefined argument");
x.length; // string
}
function f12(x: number, fail: (message?: string) => never): number {
if (x >= 0) return x;
fail("negative number");
x; // Unreachable
}
function f13(x: string, fail: (message?: string) => never) {
x; // string
fail();
x; // Unreachable
}
namespace Debug {
export declare function fail(message?: string): never;
}
function f21(x: string | undefined) {
if (x === undefined) Debug.fail("undefined argument");
x.length; // string
}
function f22(x: number): number {
if (x >= 0) return x;
Debug.fail("negative number");
x; // Unreachable
}
function f23(x: string) {
x; // string
Debug.fail();
x; // Unreachable
}
function f24(x: string) {
x; // string
((Debug).fail)();
x; // Unreachable
}
class Test {
fail(message?: string): never {
throw new Error(message);
}
f1(x: string | undefined) {
if (x === undefined) this.fail("undefined argument");
x.length; // string
}
f2(x: number): number {
if (x >= 0) return x;
this.fail("negative number");
x; // Unreachable
}
f3(x: string) {
x; // string
this.fail();
x; // Unreachable
}
}
function f30(x: string | number | undefined) {
if (typeof x === "string") {
fail();
x; // Unreachable
}
else {
x; // number | undefined
if (x !== undefined) {
x; // number
fail();
x; // Unreachable
}
else {
x; // undefined
fail();
x; // Unreachable
}
x; // Unreachable
}
x; // Unreachable
}
function f31(x: { a: string | number }) {
if (typeof x.a === "string") {
fail();
x; // Unreachable
x.a; // Unreachable
}
x; // { a: string | number }
x.a; // number
}
function f40(x: number) {
try {
x;
fail();
x; // Unreachable
}
finally {
x;
fail();
x; // Unreachable
}
x; // Unreachable
}
function f41(x: number) {
try {
x;
}
finally {
x;
fail();
x; // Unreachable
}
x; // Unreachable
}
function f42(x: number) {
try {
x;
fail();
x; // Unreachable
}
finally {
x;
}
x; // Unreachable
}
@@ -0,0 +1,65 @@
// @allowJs: true
// @checkJs: true
// @noEmit: true
// @allowUnreachableCode: false
// @filename: assertionsAndNonReturningFunctions.js
/** @typedef {(check: boolean) => asserts check} AssertFunc */
/** @type {AssertFunc} */
const assert = check => {
if (!check) throw new Error();
}
/** @type {(x: unknown) => asserts x is string } */
function assertIsString(x) {
if (!(typeof x === "string")) throw new Error();
}
/**
* @param {boolean} check
* @returns {asserts check}
*/
function assert2(check) {
if (!check) throw new Error();
}
/**
* @returns {never}
*/
function fail() {
throw new Error();
}
/**
* @param {*} x
*/
function f1(x) {
if (!!true) {
assert(typeof x === "string");
x.length;
}
if (!!true) {
assert2(typeof x === "string");
x.length;
}
if (!!true) {
assertIsString(x);
x.length;
}
if (!!true) {
fail();
x; // Unreachable
}
}
/**
* @param {boolean} b
*/
function f2(b) {
switch (b) {
case true: return 1;
case false: return 0;
}
b; // Unreachable
}