-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow type predicates as return types only #5992
Changes from 6 commits
af7df83
fd311d4
1b63040
47d267c
3306ee8
a4e21d7
f9846ff
7882fd3
9ab9940
9b13a0c
a9f2cb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -908,17 +908,19 @@ namespace ts { | |
return result; | ||
} | ||
|
||
// Invokes the provided callback then unconditionally restores the parser to the state it | ||
// was in immediately prior to invoking the callback. The result of invoking the callback | ||
// is returned from this function. | ||
/** Invokes the provided callback then unconditionally restores the parser to the state it | ||
* was in immediately prior to invoking the callback. The result of invoking the callback | ||
* is returned from this function. | ||
*/ | ||
function lookAhead<T>(callback: () => T): T { | ||
return speculationHelper(callback, /*isLookAhead*/ true); | ||
} | ||
|
||
// Invokes the provided callback. If the callback returns something falsy, then it restores | ||
// the parser to the state it was in immediately prior to invoking the callback. If the | ||
// callback returns something truthy, then the parser state is not rolled back. The result | ||
// of invoking the callback is returned from this function. | ||
/** Invokes the provided callback. If the callback returns something falsy, then it restores | ||
* the parser to the state it was in immediately prior to invoking the callback. If the | ||
* callback returns something truthy, then the parser state is not rolled back. The result | ||
* of invoking the callback is returned from this function. | ||
*/ | ||
function tryParse<T>(callback: () => T): T { | ||
return speculationHelper(callback, /*isLookAhead*/ false); | ||
} | ||
|
@@ -1960,15 +1962,8 @@ namespace ts { | |
|
||
// TYPES | ||
|
||
function parseTypeReferenceOrTypePredicate(): TypeReferenceNode | TypePredicateNode { | ||
function parseTypeReference(): TypeReferenceNode { | ||
const typeName = parseEntityName(/*allowReservedWords*/ false, Diagnostics.Type_expected); | ||
if (typeName.kind === SyntaxKind.Identifier && token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { | ||
nextToken(); | ||
const node = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, typeName.pos); | ||
node.parameterName = <Identifier>typeName; | ||
node.type = parseType(); | ||
return finishNode(node); | ||
} | ||
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference, typeName.pos); | ||
node.typeName = typeName; | ||
if (!scanner.hasPrecedingLineBreak() && token === SyntaxKind.LessThanToken) { | ||
|
@@ -2100,10 +2095,10 @@ namespace ts { | |
|
||
if (returnTokenRequired) { | ||
parseExpected(returnToken); | ||
signature.type = parseType(); | ||
signature.type = parseTypeOrTypePredicate(); | ||
} | ||
else if (parseOptional(returnToken)) { | ||
signature.type = parseType(); | ||
signature.type = parseTypeOrTypePredicate(); | ||
} | ||
} | ||
|
||
|
@@ -2419,7 +2414,7 @@ namespace ts { | |
case SyntaxKind.SymbolKeyword: | ||
// If these are followed by a dot, then parse these out as a dotted type reference instead. | ||
const node = tryParse(parseKeywordAndNoDot); | ||
return node || parseTypeReferenceOrTypePredicate(); | ||
return node || parseTypeReference(); | ||
case SyntaxKind.StringLiteral: | ||
return parseStringLiteralTypeNode(); | ||
case SyntaxKind.VoidKeyword: | ||
|
@@ -2435,7 +2430,7 @@ namespace ts { | |
case SyntaxKind.OpenParenToken: | ||
return parseParenthesizedType(); | ||
default: | ||
return parseTypeReferenceOrTypePredicate(); | ||
return parseTypeReference(); | ||
} | ||
} | ||
|
||
|
@@ -2542,6 +2537,26 @@ namespace ts { | |
return false; | ||
} | ||
|
||
function parseTypeOrTypePredicate(): TypeNode { | ||
const typePredicateVariable = tryParse(() => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only call |
||
const id = parseIdentifier(); | ||
if (token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { | ||
nextToken(); | ||
return id; | ||
} | ||
}); | ||
const type = parseType(); | ||
if (typePredicateVariable) { | ||
const node = <TypePredicateNode>createNode(SyntaxKind.TypePredicate, typePredicateVariable.pos); | ||
node.parameterName = typePredicateVariable; | ||
node.type = type; | ||
return finishNode(node); | ||
} | ||
else { | ||
return type; | ||
} | ||
} | ||
|
||
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. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider
checkIfTypePredicateVariableIsDeclaredInBindingPattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about
isTypePredicateVariableDeclaredInBindingPattern
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I considered that, but it also reports errors. I think that would still be fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, I forgot about that --
check*
is a better prefix. (This is just a move of the code, so I hadn't looked too closely at the contents.)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done