Merge pull request #3763 from tinganho/typePredicateDeclEmit

Fixes emit of type predicate in declaration files
This commit is contained in:
Mohamed Hegazy 2015-07-09 12:34:43 -07:00
commit e336701ba8
13 changed files with 435 additions and 273 deletions

View file

@ -25,12 +25,12 @@ namespace ts {
// Cancellation that controls whether or not we can cancel in the middle of type checking.
// In general cancelling is *not* safe for the type checker. We might be in the middle of
// computing something, and we will leave our internals in an inconsistent state. Callers
// who set the cancellation token should catch if a cancellation exception occurs, and
// who set the cancellation token should catch if a cancellation exception occurs, and
// should throw away and create a new TypeChecker.
//
// Currently we only support setting the cancellation token when getting diagnostics. This
// is because diagnostics can be quite expensive, and we want to allow hosts to bail out if
// they no longer need the information (for example, if the user started editing again).
// they no longer need the information (for example, if the user started editing again).
let cancellationToken: CancellationToken;
let Symbol = objectAllocator.getSymbolConstructor();
@ -117,7 +117,7 @@ namespace ts {
let globals: SymbolTable = {};
let globalESSymbolConstructorSymbol: Symbol;
let getGlobalPromiseConstructorSymbol: () => Symbol;
let globalObjectType: ObjectType;
@ -148,7 +148,7 @@ namespace ts {
let getInstantiatedGlobalPromiseLikeType: () => ObjectType;
let getGlobalPromiseConstructorLikeType: () => ObjectType;
let getGlobalThenableType: () => ObjectType;
let tupleTypes: Map<TupleType> = {};
let unionTypes: Map<UnionType> = {};
let intersectionTypes: Map<IntersectionType> = {};
@ -158,7 +158,7 @@ namespace ts {
let emitParam = false;
let emitAwaiter = false;
let emitGenerator = false;
let resolutionTargets: Object[] = [];
let resolutionResults: boolean[] = [];
@ -406,7 +406,7 @@ namespace ts {
let moduleExports = getSymbolOfNode(location).exports;
if (location.kind === SyntaxKind.SourceFile ||
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
// It's an external module. Because of module/namespace merging, a module's exports are in scope,
// yet we never want to treat an export specifier as putting a member in scope. Therefore,
// if the name we find is purely an export specifier, it is not actually considered in scope.
@ -526,7 +526,7 @@ namespace ts {
}
break;
case SyntaxKind.Decorator:
// Decorators are resolved at the class declaration. Resolving at the parameter
// Decorators are resolved at the class declaration. Resolving at the parameter
// or member would result in looking up locals in the method.
//
// function y() {}
@ -1948,7 +1948,19 @@ namespace ts {
writePunctuation(writer, SyntaxKind.ColonToken);
}
writeSpace(writer);
buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, symbolStack);
let returnType: Type;
if (signature.typePredicate) {
writer.writeParameter(signature.typePredicate.parameterName);
writeSpace(writer);
writeKeyword(writer, SyntaxKind.IsKeyword);
writeSpace(writer);
returnType = signature.typePredicate.type;
}
else {
returnType = getReturnTypeOfSignature(signature);
}
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
}
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
@ -2098,7 +2110,7 @@ namespace ts {
case SyntaxKind.ParenthesizedType:
return isDeclarationVisible(<Declaration>node.parent);
// Default binding, import specifier and namespace import is visible
// Default binding, import specifier and namespace import is visible
// only on demand so by default it is not visible
case SyntaxKind.ImportClause:
case SyntaxKind.NamespaceImport:
@ -3864,7 +3876,7 @@ namespace ts {
function getGlobalType(name: string, arity = 0): ObjectType {
return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
}
function tryGetGlobalType(name: string, arity = 0): ObjectType {
return getTypeOfGlobalSymbol(getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined), arity);
}
@ -3892,7 +3904,7 @@ namespace ts {
? createTypeReference(<GenericType>globalTypedPropertyDescriptorType, [propertyType])
: emptyObjectType;
}
/**
* Instantiates a global type that is generic with some element type, and returns that instantiation.
*/
@ -4117,7 +4129,7 @@ namespace ts {
}
return links.resolvedType;
}
function getTypeFromTypeNode(node: TypeNode): Type {
switch (node.kind) {
case SyntaxKind.AnyKeyword:
@ -6053,7 +6065,7 @@ namespace ts {
error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression);
}
}
if (node.parserContextFlags & ParserContextFlags.Await) {
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
getNodeLinks(node).flags |= NodeCheckFlags.LexicalArguments;
@ -6746,7 +6758,7 @@ namespace ts {
// c is represented in the tree as a spread element in an array literal.
// But c really functions as a rest element, and its purpose is to provide
// a contextual type for the right hand side of the assignment. Therefore,
// instead of calling checkExpression on "...c", which will give an error
// instead of calling checkExpression on "...c", which will give an error
// if c is not iterable/array-like, we need to act as if we are trying to
// get the contextual element type from it. So we do something similar to
// getContextualTypeForElementExpression, which will crucially not error
@ -7399,7 +7411,7 @@ namespace ts {
if (flags & NodeFlags.Abstract) {
// A method cannot be accessed in a super property access if the method is abstract.
// This error could mask a private property access error. But, a member
// This error could mask a private property access error. But, a member
// cannot simultaneously be private and abstract, so this will trigger an
// additional error elsewhere.
@ -7478,7 +7490,7 @@ namespace ts {
}
return unknownType;
}
getNodeLinks(node).resolvedSymbol = prop;
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
@ -7875,7 +7887,7 @@ namespace ts {
let paramType = getTypeAtPosition(signature, i);
let argType = getEffectiveArgumentType(node, i, arg);
// If the effective argument type is 'undefined', there is no synthetic type
// If the effective argument type is 'undefined', there is no synthetic type
// for the argument. In that case, we should check the argument.
if (argType === undefined) {
// For context sensitive arguments we pass the identityMapper, which is a signal to treat all
@ -7947,8 +7959,8 @@ namespace ts {
// Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter)
let paramType = getTypeAtPosition(signature, i);
let argType = getEffectiveArgumentType(node, i, arg);
// If the effective argument type is 'undefined', there is no synthetic type
// If the effective argument type is 'undefined', there is no synthetic type
// for the argument. In that case, we should check the argument.
if (argType === undefined) {
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
@ -8001,18 +8013,18 @@ namespace ts {
return args;
}
/**
* Returns the effective argument count for a node that works like a function invocation.
* If 'node' is a Decorator, the number of arguments is derived from the decoration
* target and the signature:
* If 'node.target' is a class declaration or class expression, the effective argument
* If 'node.target' is a class declaration or class expression, the effective argument
* count is 1.
* If 'node.target' is a parameter declaration, the effective argument count is 3.
* If 'node.target' is a property declaration, the effective argument count is 2.
* If 'node.target' is a method or accessor declaration, the effective argument count
* If 'node.target' is a method or accessor declaration, the effective argument count
* is 3, although it can be 2 if the signature only accepts two arguments, allowing
* us to match a property decorator.
* us to match a property decorator.
* Otherwise, the argument count is the length of the 'args' array.
*/
function getEffectiveArgumentCount(node: CallLikeExpression, args: Expression[], signature: Signature) {
@ -8024,7 +8036,7 @@ namespace ts {
return 1;
case SyntaxKind.PropertyDeclaration:
// A property declaration decorator will have two arguments (see
// A property declaration decorator will have two arguments (see
// `PropertyDecorator` in core.d.ts)
return 2;
@ -8033,12 +8045,12 @@ namespace ts {
case SyntaxKind.SetAccessor:
// A method or accessor declaration decorator will have two or three arguments (see
// `PropertyDecorator` and `MethodDecorator` in core.d.ts)
// If the method decorator signature only accepts a target and a key, we will only
// If the method decorator signature only accepts a target and a key, we will only
// type check those arguments.
return signature.parameters.length >= 3 ? 3 : 2;
case SyntaxKind.Parameter:
// A parameter declaration decorator will have three arguments (see
// A parameter declaration decorator will have three arguments (see
// `ParameterDecorator` in core.d.ts)
return 3;
@ -8048,47 +8060,47 @@ namespace ts {
return args.length;
}
}
/**
* Returns the effective type of the first argument to a decorator.
* If 'node' is a class declaration or class expression, the effective argument type
* is the type of the static side of the class.
* If 'node' is a parameter declaration, the effective argument type is either the type
* of the static or instance side of the class for the parameter's parent method,
* of the static or instance side of the class for the parameter's parent method,
* depending on whether the method is declared static.
* For a constructor, the type is always the type of the static side of the class.
* If 'node' is a property, method, or accessor declaration, the effective argument
* type is the type of the static or instance side of the parent class for class
* element, depending on whether the element is declared static.
* If 'node' is a property, method, or accessor declaration, the effective argument
* type is the type of the static or instance side of the parent class for class
* element, depending on whether the element is declared static.
*/
function getEffectiveDecoratorFirstArgumentType(node: Node): Type {
// The first argument to a decorator is its `target`.
switch (node.kind) {
case SyntaxKind.ClassDeclaration:
case SyntaxKind.ClassExpression:
// For a class decorator, the `target` is the type of the class (e.g. the
// For a class decorator, the `target` is the type of the class (e.g. the
// "static" or "constructor" side of the class)
let classSymbol = getSymbolOfNode(node);
return getTypeOfSymbol(classSymbol);
case SyntaxKind.Parameter:
// For a parameter decorator, the `target` is the parent type of the
// parameter's containing method.
// For a parameter decorator, the `target` is the parent type of the
// parameter's containing method.
node = node.parent;
if (node.kind === SyntaxKind.Constructor) {
let classSymbol = getSymbolOfNode(node);
return getTypeOfSymbol(classSymbol);
}
// fall-through
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
// For a property or method decorator, the `target` is the
// "static"-side type of the parent of the member if the member is
// declared "static"; otherwise, it is the "instance"-side type of the
// declared "static"; otherwise, it is the "instance"-side type of the
// parent of the member.
return getParentTypeOfClassElement(<ClassElement>node);
@ -8097,19 +8109,19 @@ namespace ts {
return unknownType;
}
}
/**
* Returns the effective type for the second argument to a decorator.
* If 'node' is a parameter, its effective argument type is one of the following:
* If 'node.parent' is a constructor, the effective argument type is 'any', as we
* If 'node.parent' is a constructor, the effective argument type is 'any', as we
* will emit `undefined`.
* If 'node.parent' is a member with an identifier, numeric, or string literal name,
* If 'node.parent' is a member with an identifier, numeric, or string literal name,
* the effective argument type will be a string literal type for the member name.
* If 'node.parent' is a computed property name, the effective argument type will
* If 'node.parent' is a computed property name, the effective argument type will
* either be a symbol type or the string type.
* If 'node' is a member with an identifier, numeric, or string literal name, the
* If 'node' is a member with an identifier, numeric, or string literal name, the
* effective argument type will be a string literal type for the member name.
* If 'node' is a computed property name, the effective argument type will either
* If 'node' is a computed property name, the effective argument type will either
* be a symbol type or the string type.
* A class decorator does not have a second argument type.
*/
@ -8126,18 +8138,18 @@ namespace ts {
// For a constructor parameter decorator, the `propertyKey` will be `undefined`.
return anyType;
}
// For a non-constructor parameter decorator, the `propertyKey` will be either
// a string or a symbol, based on the name of the parameter's containing method.
// fall-through
case SyntaxKind.PropertyDeclaration:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
// The `propertyKey` for a property or method decorator will be a
// string literal type if the member name is an identifier, number, or string;
// string literal type if the member name is an identifier, number, or string;
// otherwise, if the member name is a computed property name it will
// be either string or symbol.
let element = <ClassElement>node;
@ -8167,11 +8179,11 @@ namespace ts {
return unknownType;
}
}
/**
* Returns the effective argument type for the third argument to a decorator.
* If 'node' is a parameter, the effective argument type is the number type.
* If 'node' is a method or accessor, the effective argument type is a
* If 'node' is a method or accessor, the effective argument type is a
* `TypedPropertyDescriptor<T>` instantiated with the type of the member.
* Class and property decorators do not have a third effective argument.
*/
@ -8204,7 +8216,7 @@ namespace ts {
return unknownType;
}
}
/**
* Returns the effective argument type for the provided argument to a decorator.
*/
@ -8222,12 +8234,12 @@ namespace ts {
Debug.fail("Decorators should not have a fourth synthetic argument.");
return unknownType;
}
/**
* Gets the effective argument type for an argument in a call expression.
*/
function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number, arg: Expression): Type {
// Decorators provide special arguments, a tagged template expression provides
// Decorators provide special arguments, a tagged template expression provides
// a special first argument, and string literals get string literal types
// unless we're reporting errors
if (node.kind === SyntaxKind.Decorator) {
@ -8238,12 +8250,12 @@ namespace ts {
}
// This is not a synthetic argument, so we return 'undefined'
// to signal that the caller needs to check the argument.
// to signal that the caller needs to check the argument.
return undefined;
}
/**
* Gets the effective argument expression for an argument in a call expression.
* Gets the effective argument expression for an argument in a call expression.
*/
function getEffectiveArgument(node: CallLikeExpression, args: Expression[], argIndex: number) {
// For a decorator or the first argument of a tagged template expression we return undefined.
@ -8309,7 +8321,7 @@ namespace ts {
// For a tagged template, then the first argument be 'undefined' if necessary
// because it represents a TemplateStringsArray.
//
// For a decorator, no arguments are susceptible to contextual typing due to the fact
// For a decorator, no arguments are susceptible to contextual typing due to the fact
// decorators are applied to a declaration by the emitter, and not to an expression.
let excludeArgument: boolean[];
if (!isDecorator) {
@ -8651,7 +8663,7 @@ namespace ts {
return resolveCall(node, callSignatures, candidatesOutArray);
}
/**
* Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression.
*/
@ -8797,7 +8809,7 @@ namespace ts {
links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper);
}
}
function createPromiseType(promisedType: Type): Type {
// creates a `Promise<T>` type where `T` is the promisedType argument
let globalPromiseType = getGlobalPromiseType();
@ -8806,7 +8818,7 @@ namespace ts {
promisedType = getAwaitedType(promisedType);
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
}
return emptyObjectType;
}
@ -8815,15 +8827,15 @@ namespace ts {
if (!func.body) {
return unknownType;
}
let isAsync = isAsyncFunctionLike(func);
let type: Type;
if (func.body.kind !== SyntaxKind.Block) {
type = checkExpressionCached(<Expression>func.body, contextualMapper);
type = checkExpressionCached(<Expression>func.body, contextualMapper);
if (isAsync) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
// return type of the body should be unwrapped to its awaited type, which we will wrap in
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
// return type of the body should be unwrapped to its awaited type, which we will wrap in
// the native Promise<T> type later in this function.
type = checkAwaitedType(type, func, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
}
@ -8852,13 +8864,13 @@ namespace ts {
error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
return unknownType;
}
return promiseType;
}
else {
return voidType;
}
}
}
}
// When yield/return statements are contextually typed we allow the return type to be a union type.
// Otherwise we require the yield/return expressions to have a best common supertype.
@ -8881,19 +8893,19 @@ namespace ts {
if (!contextualSignature) {
reportErrorsFromWidening(func, type);
}
let widenedType = getWidenedType(type);
if (isAsync) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
// return type of the body is awaited type of the body, wrapped in a native Promise<T> type.
let promiseType = createPromiseType(widenedType);
if (promiseType === emptyObjectType) {
error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
return unknownType;
}
return promiseType;
return promiseType;
}
else {
return widenedType;
@ -8928,13 +8940,13 @@ namespace ts {
forEachReturnStatement(body, returnStatement => {
let expr = returnStatement.expression;
if (expr) {
let type = checkExpressionCached(expr, contextualMapper);
let type = checkExpressionCached(expr, contextualMapper);
if (isAsync) {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
// return type of the body should be unwrapped to its awaited type, which should be wrapped in
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
// return type of the body should be unwrapped to its awaited type, which should be wrapped in
// the native Promise<T> type by the caller.
type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
}
if (!contains(aggregatedTypes, type)) {
@ -9006,12 +9018,12 @@ namespace ts {
if (contextualMapper === identityMapper && isContextSensitive(node)) {
return anyFunctionType;
}
let isAsync = isAsyncFunctionLike(node);
if (isAsync) {
emitAwaiter = true;
}
let links = getNodeLinks(node);
let type = getTypeOfSymbol(node.symbol);
// Check if function expression is contextually typed and assign parameter types if so
@ -9048,7 +9060,7 @@ namespace ts {
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
let isAsync = isAsyncFunctionLike(node);
if (isAsync) {
emitAwaiter = true;
@ -9059,7 +9071,7 @@ namespace ts {
if (returnType && isAsync) {
promisedType = checkAsyncFunctionReturnType(node);
}
if (returnType && !node.asteriskToken) {
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
}
@ -9078,10 +9090,10 @@ namespace ts {
checkSourceElement(node.body);
}
else {
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so we
// should not be checking assignability of a promise to the return type. Instead, we need to
// check assignability of the awaited type of the expression body against the promised type of
// From within an async function you can return either a non-promise value or a promise. Any
// Promise/A+ compatible implementation will always assimilate any foreign promise, so we
// should not be checking assignability of a promise to the return type. Instead, we need to
// check assignability of the awaited type of the expression body against the promised type of
// its return type annotation.
let exprType = checkExpression(<Expression>node.body);
if (returnType) {
@ -9093,7 +9105,7 @@ namespace ts {
checkTypeAssignableTo(exprType, returnType, node.body);
}
}
checkFunctionAndClassExpressionBodies(node.body);
}
}
@ -9215,7 +9227,7 @@ namespace ts {
let operandType = checkExpression(node.expression);
return checkAwaitedType(operandType, node);
}
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
let operandType = checkExpression(node.operand);
switch (node.operator) {
@ -9688,7 +9700,7 @@ namespace ts {
node.contextualType = saveContextualType;
return result;
}
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
let links = getNodeLinks(node);
if (!links.resolvedType) {
@ -9895,7 +9907,7 @@ namespace ts {
if (node.questionToken && isBindingPattern(node.name) && func.body) {
error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
}
// Only check rest parameter type if it's not a binding pattern. Since binding patterns are
// not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) {
@ -10113,7 +10125,7 @@ namespace ts {
// Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
checkFunctionLikeDeclaration(node);
// Abstract methods cannot have an implementation.
// Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node.
if(node.flags & NodeFlags.Abstract && node.body) {
@ -10548,7 +10560,7 @@ namespace ts {
}
// Abstract methods can't have an implementation -- in particular, they don't need one.
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) {
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
}
@ -10666,13 +10678,13 @@ namespace ts {
if (!message) {
message = Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member;
}
error(location, message);
}
return unknownType;
}
return type;
}
@ -10690,16 +10702,16 @@ namespace ts {
// ) => any
// ): any;
// }
//
//
if (promise.flags & TypeFlags.Any) {
return undefined;
}
if ((promise.flags & TypeFlags.Reference) && (<GenericType>promise).target === tryGetGlobalPromiseType()) {
return (<GenericType>promise).typeArguments[0];
}
let globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType();
if (globalPromiseLikeType === emptyObjectType || !isTypeAssignableTo(promise, globalPromiseLikeType)) {
return undefined;
@ -10709,58 +10721,58 @@ namespace ts {
if (thenFunction && (thenFunction.flags & TypeFlags.Any)) {
return undefined;
}
let thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, SignatureKind.Call) : emptyArray;
if (thenSignatures.length === 0) {
return undefined;
}
let onfulfilledParameterType = getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature));
if (onfulfilledParameterType.flags & TypeFlags.Any) {
return undefined;
}
let onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call);
if (onfulfilledParameterSignatures.length === 0) {
return undefined;
}
let valueParameterType = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature));
return valueParameterType;
}
function getTypeOfFirstParameterOfSignature(signature: Signature) {
return getTypeAtPosition(signature, 0);
}
/**
* Gets the "awaited type" of a type.
* @param type The type to await.
* @remarks The "awaited type" of an expression is its "promised type" if the expression is a
* @remarks The "awaited type" of an expression is its "promised type" if the expression is a
* Promise-like type; otherwise, it is the type of the expression. This is used to reflect
* The runtime behavior of the `await` keyword.
*/
function getAwaitedType(type: Type) {
return checkAwaitedType(type, /*location*/ undefined, /*message*/ undefined);
}
function checkAwaitedType(type: Type, location?: Node, message?: DiagnosticMessage) {
return checkAwaitedTypeWorker(type);
function checkAwaitedTypeWorker(type: Type): Type {
if (type.flags & TypeFlags.Union) {
let types: Type[] = [];
for (let constituentType of (<UnionType>type).types) {
types.push(checkAwaitedTypeWorker(constituentType));
}
return getUnionType(types);
}
else {
let promisedType = getPromisedType(type);
if (promisedType === undefined) {
// The type was not a PromiseLike, so it could not be unwrapped any further.
// As long as the type does not have a callable "then" property, it is
// As long as the type does not have a callable "then" property, it is
// safe to return the type; otherwise, an error will have been reported in
// the call to checkNonThenableType and we will return unknownType.
//
@ -10771,7 +10783,7 @@ namespace ts {
// The "thenable" does not match the minimal definition for a PromiseLike. When
// a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise
// will never settle. We treat this as an error to help flag an early indicator
// of a runtime problem. If the user wants to return this value from an async
// of a runtime problem. If the user wants to return this value from an async
// function, they would need to wrap it in some other value. If they want it to
// be treated as a promise, they can cast to <any>.
return checkNonThenableType(type, location, message);
@ -10779,70 +10791,70 @@ namespace ts {
else {
if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
// We have a bad actor in the form of a promise whose promised type is
// the same promise type, or a mutually recursive promise. Return the
// unknown type as we cannot guess the shape. If this were the actual
// the same promise type, or a mutually recursive promise. Return the
// unknown type as we cannot guess the shape. If this were the actual
// case in the JavaScript, this Promise would never resolve.
//
// An example of a bad actor with a singly-recursive promise type might
// An example of a bad actor with a singly-recursive promise type might
// be:
//
// interface BadPromise {
// then(
// onfulfilled: (value: BadPromise) => any,
// onfulfilled: (value: BadPromise) => any,
// onrejected: (error: any) => any): BadPromise;
// }
//
// The above interface will pass the PromiseLike check, and return a
// promised type of `BadPromise`. Since this is a self reference, we
// The above interface will pass the PromiseLike check, and return a
// promised type of `BadPromise`. Since this is a self reference, we
// don't want to keep recursing ad infinitum.
//
// An example of a bad actor in the form of a mutually-recursive
// An example of a bad actor in the form of a mutually-recursive
// promise type might be:
//
// interface BadPromiseA {
// then(
// onfulfilled: (value: BadPromiseB) => any,
// onfulfilled: (value: BadPromiseB) => any,
// onrejected: (error: any) => any): BadPromiseB;
// }
//
// interface BadPromiseB {
// then(
// onfulfilled: (value: BadPromiseA) => any,
// onfulfilled: (value: BadPromiseA) => any,
// onrejected: (error: any) => any): BadPromiseA;
// }
//
if (location) {
error(
location,
Diagnostics._0_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method,
location,
Diagnostics._0_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method,
symbolToString(type.symbol));
}
return unknownType;
}
// Keep track of the type we're about to unwrap to avoid bad recursive promise types.
// See the comments above for more information.
awaitedTypeStack.push(type.id);
let awaitedType = checkAwaitedTypeWorker(promisedType);
awaitedTypeStack.pop();
return awaitedType;
return awaitedType;
}
}
}
}
/**
* Checks the return type of an async function to ensure it is a compatible
* Checks the return type of an async function to ensure it is a compatible
* Promise implementation.
* @param node The signature to check
* @param returnType The return type for the function
* @remarks
* This checks that an async function has a valid Promise-compatible return type,
* and returns the *awaited type* of the promise. An async function has a valid
* Promise-compatible return type if the resolved value of the return type has a
* @remarks
* This checks that an async function has a valid Promise-compatible return type,
* and returns the *awaited type* of the promise. An async function has a valid
* Promise-compatible return type if the resolved value of the return type has a
* construct signature that takes in an `initializer` function that in turn supplies
* a `resolve` function as one of its arguments and results in an object with a
* a `resolve` function as one of its arguments and results in an object with a
* callable `then` signature.
*/
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
@ -10855,7 +10867,7 @@ namespace ts {
// As part of our emit for an async function, we will need to emit the entity name of
// the return type annotation as an expression. To meet the necessary runtime semantics
// for __awaiter, we must also check that the type of the declaration (e.g. the static
// for __awaiter, we must also check that the type of the declaration (e.g. the static
// side or "constructor" of the promise type) is compatible `PromiseConstructorLike`.
//
// An example might be (from lib.es6.d.ts):
@ -10863,11 +10875,11 @@ namespace ts {
// interface Promise<T> { ... }
// interface PromiseConstructor {
// new <T>(...): Promise<T>;
// }
// }
// declare var Promise: PromiseConstructor;
//
// When an async function declares a return type annotation of `Promise<T>`, we
// need to get the type of the `Promise` variable declaration above, which would
// When an async function declares a return type annotation of `Promise<T>`, we
// need to get the type of the `Promise` variable declaration above, which would
// be `PromiseConstructor`.
//
// The same case applies to a class:
@ -10879,20 +10891,20 @@ namespace ts {
//
// When we get the type of the `Promise` symbol here, we get the type of the static
// side of the `Promise` class, which would be `{ new <T>(...): Promise<T> }`.
let promiseType = getTypeFromTypeNode(node.type);
if (promiseType === unknownType && compilerOptions.isolatedModules) {
// If we are compiling with isolatedModules, we may not be able to resolve the
// If we are compiling with isolatedModules, we may not be able to resolve the
// type as a value. As such, we will just return unknownType;
return unknownType;
}
let promiseConstructor = getMergedSymbol(promiseType.symbol);
if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeToString(promiseType));
return unknownType
}
// Validate the promise constructor type.
let promiseConstructorType = getTypeOfSymbol(promiseConstructor);
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
@ -10913,7 +10925,7 @@ namespace ts {
// Get and return the awaited type of the return type.
return checkAwaitedType(promiseType, node, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
}
/** Check a decorator */
function checkDecorator(node: Decorator): void {
let signature = getResolvedSignature(node);
@ -10963,11 +10975,11 @@ namespace ts {
headMessage,
errorInfo);
}
/** Checks a type reference node as an expression. */
function checkTypeNodeAsExpression(node: TypeNode) {
// When we are emitting type metadata for decorators, we need to try to check the type
// as if it were an expression so that we can emit the type in a value position when we
// as if it were an expression so that we can emit the type in a value position when we
// serialize the type metadata.
if (node && node.kind === SyntaxKind.TypeReference) {
let type = getTypeFromTypeNode(node);
@ -10982,7 +10994,7 @@ namespace ts {
}
/**
* Checks the type annotation of an accessor declaration or property declaration as
* Checks the type annotation of an accessor declaration or property declaration as
* an expression if it is a type reference to a type with a value declaration.
*/
function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
@ -11004,7 +11016,7 @@ namespace ts {
break;
}
}
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
// ensure all type annotations with a value declaration are checked as an expression
@ -11078,9 +11090,9 @@ namespace ts {
if (!compilerOptions.experimentalAsyncFunctions) {
error(node, Diagnostics.Experimental_support_for_async_functions_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalAsyncFunctions_to_remove_this_warning);
}
emitAwaiter = true;
}
}
// Do not use hasDynamicName here, because that returns false for well known symbols.
// We want to perform checkComputedPropertyName for all computed properties, including
@ -11120,7 +11132,7 @@ namespace ts {
if (isAsync) {
promisedType = checkAsyncFunctionReturnType(node);
}
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
}
@ -11332,7 +11344,7 @@ namespace ts {
}
}
}
// Check that a parameter initializer contains no references to parameters declared to the right of itself
function checkParameterInitializer(node: VariableLikeDeclaration): void {
if (getRootDeclaration(node).kind !== SyntaxKind.Parameter) {
@ -11653,7 +11665,7 @@ namespace ts {
return elementType || anyType;
}
/**
* We want to treat type as an iterable, and get the type it is an iterable of. The iterable
* must have the following structure (annotated with the names of the variables below):
@ -12280,20 +12292,20 @@ namespace ts {
// In order to resolve whether the inherited method was overriden in the base class or not,
// we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated*
// type declaration, derived and base resolve to the same symbol even in the case of generic classes.
if (derived === base) {
if (derived === base) {
// derived class inherits base without override/redeclaration
let derivedClassDecl = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
// It is an error to inherit an abstract member without implementing it or being declared abstract.
// If there is no declaration for the derived class (as in the case of class expressions),
// then the class cannot be declared abstract.
// If there is no declaration for the derived class (as in the case of class expressions),
// then the class cannot be declared abstract.
if ( baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) {
error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
}
}
else {
else {
// derived overrides base.
let derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
if ((baseDeclarationFlags & NodeFlags.Private) || (derivedDeclarationFlags & NodeFlags.Private)) {
@ -12764,7 +12776,7 @@ namespace ts {
}
}
// if the module merges with a class declaration in the same lexical scope,
// if the module merges with a class declaration in the same lexical scope,
// we need to track this to ensure the correct emit.
let mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);
if (mergedClass &&
@ -13298,7 +13310,7 @@ namespace ts {
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
potentialThisCollisions.length = 0;
}
if (emitExtends) {
links.flags |= NodeCheckFlags.EmitExtends;
}
@ -13310,11 +13322,11 @@ namespace ts {
if (emitParam) {
links.flags |= NodeCheckFlags.EmitParam;
}
if (emitAwaiter) {
links.flags |= NodeCheckFlags.EmitAwaiter;
}
if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) {
links.flags |= NodeCheckFlags.EmitGenerator;
}
@ -13713,7 +13725,7 @@ namespace ts {
}
/**
* Gets either the static or instance type of a class element, based on
* Gets either the static or instance type of a class element, based on
* whether the element is declared as "static".
*/
function getParentTypeOfClassElement(node: ClassElement) {
@ -13722,7 +13734,7 @@ namespace ts {
? getTypeOfSymbol(classSymbol)
: getDeclaredTypeOfSymbol(classSymbol);
}
// Return the list of properties of the given type, augmented with properties from Function
// if the type has call or construct signatures
function getAugmentedPropertiesOfType(type: Type): Symbol[] {
@ -14061,7 +14073,7 @@ namespace ts {
// * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
// * The serialized type of any other FunctionLikeDeclaration is "Function".
// * The serialized type of any other node is "void 0".
//
//
// For rules on serializing type annotations, see `serializeTypeNode`.
switch (node.kind) {
case SyntaxKind.ClassDeclaration: return "Function";
@ -14075,14 +14087,14 @@ namespace ts {
}
return "void 0";
}
/** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
function serializeParameterTypesOfNode(node: Node): (string | string[])[] {
// serialization of parameter types uses the following rules:
//
// * If the declaration is a class, the parameters of the first constructor with a body are used.
// * If the declaration is function-like and has a body, the parameters of the function are used.
//
//
// For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
if (node) {
var valueDeclaration: FunctionLikeDeclaration;
@ -14299,21 +14311,21 @@ namespace ts {
anyArrayType = createArrayType(anyType);
}
function createInstantiatedPromiseLikeType(): ObjectType {
let promiseLikeType = getGlobalPromiseLikeType();
if (promiseLikeType !== emptyObjectType) {
return createTypeReference(<GenericType>promiseLikeType, [anyType]);
}
return emptyObjectType;
}
function createThenableType() {
// build the thenable type that is used to verify against a non-promise "thenable" operand to `await`.
let thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then");
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
let thenableType = <ResolvedType>createObjectType(TypeFlags.Anonymous);
thenableType.properties = [thenPropertySymbol];
thenableType.members = createSymbolTable(thenableType.properties);

View file

@ -188,7 +188,7 @@ namespace ts {
if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) {
moduleElementEmitInfo = forEach(asynchronousSubModuleDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined);
}
// If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration
// then we don't need to write it at this point. We will write it when we actually see its declaration
// Eg.
@ -198,7 +198,7 @@ namespace ts {
// we would write alias foo declaration when we visit it since it would now be marked as visible
if (moduleElementEmitInfo) {
if (moduleElementEmitInfo.node.kind === SyntaxKind.ImportDeclaration) {
// we have to create asynchronous output only after we have collected complete information
// we have to create asynchronous output only after we have collected complete information
// because it is possible to enable multiple bindings as asynchronously visible
moduleElementEmitInfo.isVisible = true;
}
@ -353,6 +353,21 @@ namespace ts {
return emitEntityName(<Identifier>type);
case SyntaxKind.QualifiedName:
return emitEntityName(<QualifiedName>type);
case SyntaxKind.TypePredicate:
return emitTypePredicate(<TypePredicateNode>type);
}
function writeEntityName(entityName: EntityName | Expression) {
if (entityName.kind === SyntaxKind.Identifier) {
writeTextOfNode(currentSourceFile, entityName);
}
else {
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
writeEntityName(left);
write(".");
writeTextOfNode(currentSourceFile, right);
}
}
function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
@ -362,19 +377,6 @@ namespace ts {
handleSymbolAccessibilityError(visibilityResult);
writeEntityName(entityName);
function writeEntityName(entityName: EntityName | Expression) {
if (entityName.kind === SyntaxKind.Identifier) {
writeTextOfNode(currentSourceFile, entityName);
}
else {
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
writeEntityName(left);
write(".");
writeTextOfNode(currentSourceFile, right);
}
}
}
function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) {
@ -398,6 +400,12 @@ namespace ts {
}
}
function emitTypePredicate(type: TypePredicateNode) {
writeTextOfNode(currentSourceFile, type.parameterName);
write(" is ");
emitType(type.type);
}
function emitTypeQuery(type: TypeQueryNode) {
write("typeof ");
emitEntityName(type.exprName);
@ -600,7 +608,7 @@ namespace ts {
}
function writeImportEqualsDeclaration(node: ImportEqualsDeclaration) {
// note usage of writer. methods instead of aliases created, just to make sure we are using
// note usage of writer. methods instead of aliases created, just to make sure we are using
// correct writer especially to handle asynchronous alias writing
emitJsDocComments(node);
if (node.flags & NodeFlags.Export) {
@ -642,7 +650,7 @@ namespace ts {
function writeImportDeclaration(node: ImportDeclaration) {
if (!node.importClause && !(node.flags & NodeFlags.Export)) {
// do not write non-exported import declarations that don't have import clauses
// do not write non-exported import declarations that don't have import clauses
return;
}
emitJsDocComments(node);
@ -1517,7 +1525,7 @@ namespace ts {
}
}
}
}
}
}
function emitNode(node: Node) {
@ -1577,7 +1585,7 @@ namespace ts {
referencePathsOutput += "/// <reference path=\"" + declFileName + "\" />" + newLine;
}
}
/* @internal */
export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) {
let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile);

View file

@ -26,6 +26,19 @@ export function fooWithSingleOverload(a: any) {
return a;
}
export function fooWithTypePredicate(a: any): a is number {
return true;
}
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
return true;
}
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
return true;
}
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
return true;
}
/** This comment should appear for nonExportedFoo*/
function nonExportedFoo() {
}
@ -92,6 +105,26 @@ function fooWithSingleOverload(a) {
return a;
}
exports.fooWithSingleOverload = fooWithSingleOverload;
function fooWithTypePredicate(a) {
return true;
}
exports.fooWithTypePredicate = fooWithTypePredicate;
function fooWithTypePredicateAndMulitpleParams(a, b, c) {
return true;
}
exports.fooWithTypePredicateAndMulitpleParams = fooWithTypePredicateAndMulitpleParams;
function fooWithTypeTypePredicateAndGeneric(a) {
return true;
}
exports.fooWithTypeTypePredicateAndGeneric = fooWithTypeTypePredicateAndGeneric;
function fooWithTypeTypePredicateAndRestParam(a) {
var rest = [];
for (var _i = 1; _i < arguments.length; _i++) {
rest[_i - 1] = arguments[_i];
}
return true;
}
exports.fooWithTypeTypePredicateAndRestParam = fooWithTypeTypePredicateAndRestParam;
/** This comment should appear for nonExportedFoo*/
function nonExportedFoo() {
}
@ -144,6 +177,10 @@ export declare function fooWithRestParameters(a: string, ...rests: string[]): st
export declare function fooWithOverloads(a: string): string;
export declare function fooWithOverloads(a: number): number;
export declare function fooWithSingleOverload(a: string): string;
export declare function fooWithTypePredicate(a: any): a is number;
export declare function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number;
export declare function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T;
export declare function fooWithTypeTypePredicateAndRestParam(a: any, ...rest: any[]): a is number;
//// [declFileFunctions_1.d.ts]
/** This comment should appear for foo*/
declare function globalfoo(): void;

View file

@ -57,49 +57,83 @@ export function fooWithSingleOverload(a: any) {
>a : Symbol(a, Decl(declFileFunctions_0.ts, 21, 38))
}
export function fooWithTypePredicate(a: any): a is number {
>fooWithTypePredicate : Symbol(fooWithTypePredicate, Decl(declFileFunctions_0.ts, 23, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 25, 37))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 25, 37))
return true;
}
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
>fooWithTypePredicateAndMulitpleParams : Symbol(fooWithTypePredicateAndMulitpleParams, Decl(declFileFunctions_0.ts, 27, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 28, 54))
>b : Symbol(b, Decl(declFileFunctions_0.ts, 28, 61))
>c : Symbol(c, Decl(declFileFunctions_0.ts, 28, 69))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 28, 54))
return true;
}
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
>fooWithTypeTypePredicateAndGeneric : Symbol(fooWithTypeTypePredicateAndGeneric, Decl(declFileFunctions_0.ts, 30, 1))
>T : Symbol(T, Decl(declFileFunctions_0.ts, 31, 51))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 31, 54))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 31, 54))
>T : Symbol(T, Decl(declFileFunctions_0.ts, 31, 51))
return true;
}
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
>fooWithTypeTypePredicateAndRestParam : Symbol(fooWithTypeTypePredicateAndRestParam, Decl(declFileFunctions_0.ts, 33, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 53))
>rest : Symbol(rest, Decl(declFileFunctions_0.ts, 34, 60))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 53))
return true;
}
/** This comment should appear for nonExportedFoo*/
function nonExportedFoo() {
>nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 23, 1))
>nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 36, 1))
}
/** This is comment for function signature*/
function nonExportedFooWithParameters(/** this is comment about a*/a: string,
>nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 27, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 29, 38))
>nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 40, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 38))
/** this is comment for b*/
b: number) {
>b : Symbol(b, Decl(declFileFunctions_0.ts, 29, 77))
>b : Symbol(b, Decl(declFileFunctions_0.ts, 42, 77))
var d = a;
>d : Symbol(d, Decl(declFileFunctions_0.ts, 32, 7))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 29, 38))
>d : Symbol(d, Decl(declFileFunctions_0.ts, 45, 7))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 38))
}
function nonExportedFooWithRestParameters(a: string, ...rests: string[]) {
>nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 33, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 42))
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 34, 52))
>nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 46, 1))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 47, 42))
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 47, 52))
return a + rests.join("");
>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 42))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 47, 42))
>rests.join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31))
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 34, 52))
>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 47, 52))
>join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31))
}
function nonExportedFooWithOverloads(a: string): string;
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 37))
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 51, 37))
function nonExportedFooWithOverloads(a: number): number;
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 39, 37))
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 52, 37))
function nonExportedFooWithOverloads(a: any): any {
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 40, 37))
>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 53, 37))
return a;
>a : Symbol(a, Decl(declFileFunctions_0.ts, 40, 37))
>a : Symbol(a, Decl(declFileFunctions_0.ts, 53, 37))
}
=== tests/cases/compiler/declFileFunctions_1.ts ===

View file

@ -60,6 +60,44 @@ export function fooWithSingleOverload(a: any) {
>a : any
}
export function fooWithTypePredicate(a: any): a is number {
>fooWithTypePredicate : (a: any) => a is number
>a : any
>a : any
return true;
>true : boolean
}
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
>fooWithTypePredicateAndMulitpleParams : (a: any, b: any, c: any) => a is number
>a : any
>b : any
>c : any
>a : any
return true;
>true : boolean
}
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
>fooWithTypeTypePredicateAndGeneric : <T>(a: any) => a is T
>T : T
>a : any
>a : any
>T : T
return true;
>true : boolean
}
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
>fooWithTypeTypePredicateAndRestParam : (a: any, ...rest: any[]) => a is number
>a : any
>rest : any[]
>a : any
return true;
>true : boolean
}
/** This comment should appear for nonExportedFoo*/
function nonExportedFoo() {
>nonExportedFoo : () => void

View file

@ -5,9 +5,9 @@ var maybeArray: number | number[];
if (Array.isArray(maybeArray)) {
>Array.isArray(maybeArray) : boolean
>Array.isArray : (arg: any) => boolean
>Array.isArray : (arg: any) => arg is any[]
>Array : ArrayConstructor
>isArray : (arg: any) => boolean
>isArray : (arg: any) => arg is any[]
>maybeArray : number | number[]
maybeArray.length; // OK

View file

@ -23,19 +23,19 @@ class C extends A {
}
declare function isA(p1: any): p1 is A;
>isA : (p1: any) => boolean
>isA : (p1: any) => p1 is A
>p1 : any
>p1 : any
>A : A
declare function isB(p1: any): p1 is B;
>isB : (p1: any) => boolean
>isB : (p1: any) => p1 is B
>p1 : any
>p1 : any
>B : B
declare function isC(p1: any): p1 is C;
>isC : (p1: any) => boolean
>isC : (p1: any) => p1 is C
>p1 : any
>p1 : any
>C : C
@ -55,7 +55,7 @@ var b: B;
// Basic
if (isC(a)) {
>isC(a) : boolean
>isC : (p1: any) => boolean
>isC : (p1: any) => p1 is C
>a : A
a.propC;
@ -71,7 +71,7 @@ var subType: C;
if(isA(subType)) {
>isA(subType) : boolean
>isA : (p1: any) => boolean
>isA : (p1: any) => p1 is A
>subType : C
subType.propC;
@ -88,7 +88,7 @@ var union: A | B;
if(isA(union)) {
>isA(union) : boolean
>isA : (p1: any) => boolean
>isA : (p1: any) => p1 is A
>union : A | B
union.propA;
@ -111,7 +111,7 @@ interface I1 {
// The parameter index and argument index for the type guard target is matching.
// The type predicate type is assignable to the parameter type.
declare function isC_multipleParams(p1, p2): p1 is C;
>isC_multipleParams : (p1: any, p2: any) => boolean
>isC_multipleParams : (p1: any, p2: any) => p1 is C
>p1 : any
>p2 : any
>p1 : any
@ -119,7 +119,7 @@ declare function isC_multipleParams(p1, p2): p1 is C;
if (isC_multipleParams(a, 0)) {
>isC_multipleParams(a, 0) : boolean
>isC_multipleParams : (p1: any, p2: any) => boolean
>isC_multipleParams : (p1: any, p2: any) => p1 is C
>a : A
>0 : number
@ -131,10 +131,10 @@ if (isC_multipleParams(a, 0)) {
// Methods
var obj: {
>obj : { func1(p1: A): boolean; }
>obj : { func1(p1: A): p1 is C; }
func1(p1: A): p1 is C;
>func1 : (p1: A) => boolean
>func1 : (p1: A) => p1 is C
>p1 : A
>A : A
>p1 : any
@ -144,7 +144,7 @@ class D {
>D : D
method1(p1: A): p1 is C {
>method1 : (p1: A) => boolean
>method1 : (p1: A) => p1 is C
>p1 : A
>A : A
>p1 : any
@ -157,8 +157,8 @@ class D {
// Arrow function
let f1 = (p1: A): p1 is C => false;
>f1 : (p1: A) => boolean
>(p1: A): p1 is C => false : (p1: A) => boolean
>f1 : (p1: A) => p1 is C
>(p1: A): p1 is C => false : (p1: A) => p1 is C
>p1 : A
>A : A
>p1 : any
@ -167,8 +167,8 @@ let f1 = (p1: A): p1 is C => false;
// Function type
declare function f2(p1: (p1: A) => p1 is C);
>f2 : (p1: (p1: A) => boolean) => any
>p1 : (p1: A) => boolean
>f2 : (p1: (p1: A) => p1 is C) => any
>p1 : (p1: A) => p1 is C
>p1 : A
>A : A
>p1 : any
@ -177,8 +177,8 @@ declare function f2(p1: (p1: A) => p1 is C);
// Function expressions
f2(function(p1: A): p1 is C {
>f2(function(p1: A): p1 is C { return true;}) : any
>f2 : (p1: (p1: A) => boolean) => any
>function(p1: A): p1 is C { return true;} : (p1: A) => boolean
>f2 : (p1: (p1: A) => p1 is C) => any
>function(p1: A): p1 is C { return true;} : (p1: A) => p1 is C
>p1 : A
>A : A
>p1 : any
@ -198,21 +198,21 @@ acceptingBoolean(isA(a));
>acceptingBoolean(isA(a)) : any
>acceptingBoolean : (a: boolean) => any
>isA(a) : boolean
>isA : (p1: any) => boolean
>isA : (p1: any) => p1 is A
>a : A
// Type predicates with different parameter name.
declare function acceptingTypeGuardFunction(p1: (item) => item is A);
>acceptingTypeGuardFunction : (p1: (item: any) => boolean) => any
>p1 : (item: any) => boolean
>acceptingTypeGuardFunction : (p1: (item: any) => item is A) => any
>p1 : (item: any) => item is A
>item : any
>item : any
>A : A
acceptingTypeGuardFunction(isA);
>acceptingTypeGuardFunction(isA) : any
>acceptingTypeGuardFunction : (p1: (item: any) => boolean) => any
>isA : (p1: any) => boolean
>acceptingTypeGuardFunction : (p1: (item: any) => item is A) => any
>isA : (p1: any) => p1 is A
// Binary expressions
let union2: C | B;
@ -225,7 +225,7 @@ let union3: boolean | B = isA(union2) || union2;
>B : B
>isA(union2) || union2 : boolean | B
>isA(union2) : boolean
>isA : (p1: any) => boolean
>isA : (p1: any) => p1 is A
>union2 : B | C
>union2 : B

View file

@ -12,15 +12,15 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(46,56)
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(60,7): error TS2339: Property 'propB' does not exist on type 'A'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(65,7): error TS2339: Property 'propB' does not exist on type 'A'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(70,7): error TS2339: Property 'propB' does not exist on type 'A'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,46): error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,46): error TS2345: Argument of type '(p1: any) => p1 is C' is not assignable to parameter of type '(p1: any) => p1 is B'.
Type predicate 'p1 is C' is not assignable to 'p1 is B'.
Type 'C' is not assignable to type 'B'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(79,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(79,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => p1 is A'.
Signature '(p1: any, p2: any): boolean' must have a type predicate.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(85,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(85,1): error TS2322: Type '(p1: any, p2: any) => p2 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'.
Type predicate 'p2 is A' is not assignable to 'p1 is A'.
Parameter 'p2' is not in the same position as parameter 'p1'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1): error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1): error TS2322: Type '(p1: any, p2: any, p3: any) => p1 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,9): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,16): error TS1228: A type predicate is only allowed in return type position for functions and methods.
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(98,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
@ -141,7 +141,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
declare function acceptingDifferentSignatureTypeGuardFunction(p1: (p1) => p1 is B);
acceptingDifferentSignatureTypeGuardFunction(isC);
~~~
!!! error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'.
!!! error TS2345: Argument of type '(p1: any) => p1 is C' is not assignable to parameter of type '(p1: any) => p1 is B'.
!!! error TS2345: Type predicate 'p1 is C' is not assignable to 'p1 is B'.
!!! error TS2345: Type 'C' is not assignable to type 'B'.
@ -149,7 +149,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
var assign1: (p1, p2) => p1 is A;
assign1 = function(p1, p2): boolean {
~~~~~~~
!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => p1 is A'.
!!! error TS2322: Signature '(p1: any, p2: any): boolean' must have a type predicate.
return true;
};
@ -158,7 +158,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
var assign2: (p1, p2) => p1 is A;
assign2 = function(p1, p2): p2 is A {
~~~~~~~
!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
!!! error TS2322: Type '(p1: any, p2: any) => p2 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'.
!!! error TS2322: Type predicate 'p2 is A' is not assignable to 'p1 is A'.
!!! error TS2322: Parameter 'p2' is not in the same position as parameter 'p1'.
return true;
@ -168,7 +168,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
var assign3: (p1, p2) => p1 is A;
assign3 = function(p1, p2, p3): p1 is A {
~~~~~~~
!!! error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
!!! error TS2322: Type '(p1: any, p2: any, p3: any) => p1 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'.
return true;
};

View file

@ -23,13 +23,13 @@ class C extends A {
}
declare function isB(p1): p1 is B;
>isB : (p1: any) => boolean
>isB : (p1: any) => p1 is B
>p1 : any
>p1 : any
>B : B
declare function isC(p1): p1 is C;
>isC : (p1: any) => boolean
>isC : (p1: any) => p1 is C
>p1 : any
>p1 : any
>C : C
@ -48,7 +48,7 @@ declare function funA<T>(p1: (p1) => T): T;
>T : T
declare function funB<T>(p1: (p1) => T, p2: any): p2 is T;
>funB : <T>(p1: (p1: any) => T, p2: any) => boolean
>funB : <T>(p1: (p1: any) => T, p2: any) => p2 is T
>T : T
>p1 : (p1: any) => T
>p1 : any
@ -58,18 +58,18 @@ declare function funB<T>(p1: (p1) => T, p2: any): p2 is T;
>T : T
declare function funC<T>(p1: (p1) => p1 is T): T;
>funC : <T>(p1: (p1: any) => boolean) => T
>funC : <T>(p1: (p1: any) => p1 is T) => T
>T : T
>p1 : (p1: any) => boolean
>p1 : (p1: any) => p1 is T
>p1 : any
>p1 : any
>T : T
>T : T
declare function funD<T>(p1: (p1) => p1 is T, p2: any): p2 is T;
>funD : <T>(p1: (p1: any) => boolean, p2: any) => boolean
>funD : <T>(p1: (p1: any) => p1 is T, p2: any) => p2 is T
>T : T
>p1 : (p1: any) => boolean
>p1 : (p1: any) => p1 is T
>p1 : any
>p1 : any
>T : T
@ -78,10 +78,10 @@ declare function funD<T>(p1: (p1) => p1 is T, p2: any): p2 is T;
>T : T
declare function funE<T, U>(p1: (p1) => p1 is T, p2: U): T;
>funE : <T, U>(p1: (p1: any) => boolean, p2: U) => T
>funE : <T, U>(p1: (p1: any) => p1 is T, p2: U) => T
>T : T
>U : U
>p1 : (p1: any) => boolean
>p1 : (p1: any) => p1 is T
>p1 : any
>p1 : any
>T : T
@ -97,11 +97,11 @@ let test1: boolean = funA(isB);
>test1 : boolean
>funA(isB) : boolean
>funA : <T>(p1: (p1: any) => T) => T
>isB : (p1: any) => boolean
>isB : (p1: any) => p1 is B
if (funB(retC, a)) {
>funB(retC, a) : boolean
>funB : <T>(p1: (p1: any) => T, p2: any) => boolean
>funB : <T>(p1: (p1: any) => T, p2: any) => p2 is T
>retC : (x: any) => C
>a : A
@ -114,13 +114,13 @@ let test2: B = funC(isB);
>test2 : B
>B : B
>funC(isB) : B
>funC : <T>(p1: (p1: any) => boolean) => T
>isB : (p1: any) => boolean
>funC : <T>(p1: (p1: any) => p1 is T) => T
>isB : (p1: any) => p1 is B
if (funD(isC, a)) {
>funD(isC, a) : boolean
>funD : <T>(p1: (p1: any) => boolean, p2: any) => boolean
>isC : (p1: any) => boolean
>funD : <T>(p1: (p1: any) => p1 is T, p2: any) => p2 is T
>isC : (p1: any) => p1 is C
>a : A
a.propC;
@ -132,7 +132,7 @@ let test3: B = funE(isB, 1);
>test3 : B
>B : B
>funE(isB, 1) : B
>funE : <T, U>(p1: (p1: any) => boolean, p2: U) => T
>isB : (p1: any) => boolean
>funE : <T, U>(p1: (p1: any) => p1 is T, p2: U) => T
>isB : (p1: any) => p1 is B
>1 : number

View file

@ -29,7 +29,7 @@ var strOrNum: string | number;
>strOrNum : string | number
function isC1(x: any): x is C1 {
>isC1 : (x: any) => boolean
>isC1 : (x: any) => x is C1
>x : any
>x : any
>C1 : C1
@ -39,7 +39,7 @@ function isC1(x: any): x is C1 {
}
function isC2(x: any): x is C2 {
>isC2 : (x: any) => boolean
>isC2 : (x: any) => x is C2
>x : any
>x : any
>C2 : C2
@ -49,7 +49,7 @@ function isC2(x: any): x is C2 {
}
function isD1(x: any): x is D1 {
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>x : any
>x : any
>D1 : D1
@ -68,7 +68,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1
>str : string
>isC1(c1Orc2) && c1Orc2.p1 : string
>isC1(c1Orc2) : boolean
>isC1 : (x: any) => boolean
>isC1 : (x: any) => x is C1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
>c1Orc2 : C1
@ -79,7 +79,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2
>num : number
>isC2(c1Orc2) && c1Orc2.p2 : number
>isC2(c1Orc2) : boolean
>isC2 : (x: any) => boolean
>isC2 : (x: any) => x is C2
>c1Orc2 : C1 | C2
>c1Orc2.p2 : number
>c1Orc2 : C2
@ -90,7 +90,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1
>str : string
>isD1(c1Orc2) && c1Orc2.p1 : string
>isD1(c1Orc2) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
>c1Orc2 : D1
@ -101,7 +101,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1
>num : number
>isD1(c1Orc2) && c1Orc2.p3 : number
>isD1(c1Orc2) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p3 : number
>c1Orc2 : D1
@ -117,7 +117,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2
>num : number
>isC2(c2Ord1) && c2Ord1.p2 : number
>isC2(c2Ord1) : boolean
>isC2 : (x: any) => boolean
>isC2 : (x: any) => x is C2
>c2Ord1 : C2 | D1
>c2Ord1.p2 : number
>c2Ord1 : C2
@ -128,7 +128,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1
>num : number
>isD1(c2Ord1) && c2Ord1.p3 : number
>isD1(c2Ord1) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p3 : number
>c2Ord1 : D1
@ -139,7 +139,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1
>str : string
>isD1(c2Ord1) && c2Ord1.p1 : string
>isD1(c2Ord1) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p1 : string
>c2Ord1 : D1
@ -151,7 +151,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1
>D1 : D1
>isC1(c2Ord1) && c2Ord1 : D1
>isC1(c2Ord1) : boolean
>isC1 : (x: any) => boolean
>isC1 : (x: any) => x is C1
>c2Ord1 : C2 | D1
>c2Ord1 : D1

View file

@ -48,7 +48,7 @@ var strOrNum: string | number;
function isC1(x: any): x is C1 {
>isC1 : (x: any) => boolean
>isC1 : (x: any) => x is C1
>x : any
>x : any
>C1 : C1
@ -58,7 +58,7 @@ function isC1(x: any): x is C1 {
}
function isC2(x: any): x is C2 {
>isC2 : (x: any) => boolean
>isC2 : (x: any) => x is C2
>x : any
>x : any
>C2 : C2
@ -68,7 +68,7 @@ function isC2(x: any): x is C2 {
}
function isD1(x: any): x is D1 {
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>x : any
>x : any
>D1 : D1
@ -99,7 +99,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1
>str : string
>isC1(c1Orc2) && c1Orc2.p1 : string
>isC1(c1Orc2) : boolean
>isC1 : (x: any) => boolean
>isC1 : (x: any) => x is C1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
>c1Orc2 : C1
@ -110,7 +110,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2
>num : number
>isC2(c1Orc2) && c1Orc2.p2 : number
>isC2(c1Orc2) : boolean
>isC2 : (x: any) => boolean
>isC2 : (x: any) => x is C2
>c1Orc2 : C1 | C2
>c1Orc2.p2 : number
>c1Orc2 : C2
@ -121,7 +121,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1
>str : string
>isD1(c1Orc2) && c1Orc2.p1 : string
>isD1(c1Orc2) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p1 : string
>c1Orc2 : D1
@ -132,7 +132,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1
>num : number
>isD1(c1Orc2) && c1Orc2.p3 : number
>isD1(c1Orc2) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c1Orc2 : C1 | C2
>c1Orc2.p3 : number
>c1Orc2 : D1
@ -148,7 +148,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2
>num : number
>isC2(c2Ord1) && c2Ord1.p2 : number
>isC2(c2Ord1) : boolean
>isC2 : (x: any) => boolean
>isC2 : (x: any) => x is C2
>c2Ord1 : C2 | D1
>c2Ord1.p2 : number
>c2Ord1 : C2
@ -159,7 +159,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1
>num : number
>isD1(c2Ord1) && c2Ord1.p3 : number
>isD1(c2Ord1) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p3 : number
>c2Ord1 : D1
@ -170,7 +170,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1
>str : string
>isD1(c2Ord1) && c2Ord1.p1 : string
>isD1(c2Ord1) : boolean
>isD1 : (x: any) => boolean
>isD1 : (x: any) => x is D1
>c2Ord1 : C2 | D1
>c2Ord1.p1 : string
>c2Ord1 : D1
@ -182,7 +182,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1
>D1 : D1
>isC1(c2Ord1) && c2Ord1 : D1
>isC1(c2Ord1) : boolean
>isC1 : (x: any) => boolean
>isC1 : (x: any) => x is C1
>c2Ord1 : C2 | D1
>c2Ord1 : D1

View file

@ -28,6 +28,19 @@ export function fooWithSingleOverload(a: any) {
return a;
}
export function fooWithTypePredicate(a: any): a is number {
return true;
}
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
return true;
}
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
return true;
}
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
return true;
}
/** This comment should appear for nonExportedFoo*/
function nonExportedFoo() {
}

View file

@ -0,0 +1,20 @@
/// <reference path="fourslash.ts" />
//// function f1(a: any): a is number {}
//// function f2<T>(a: any): a is T {}
//// function f3(a: any, ...b): a is number {}
//// f1(/*1*/)
//// f2(/*2*/)
//// f3(/*3*/)
goTo.marker("1");
verify.signatureHelpCountIs(1);
verify.currentSignatureHelpIs("f1(a: any): a is number");
goTo.marker("2");
verify.signatureHelpCountIs(1);
verify.currentSignatureHelpIs("f2<T>(a: any): a is T");
goTo.marker("3");
verify.signatureHelpCountIs(1);
verify.currentSignatureHelpIs("f3(a: any, ...b: any[]): a is number");