mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-19 20:37:00 -05:00
first pass at this type predicates
This commit is contained in:
@@ -2058,7 +2058,12 @@ namespace ts {
|
||||
|
||||
let returnType: Type;
|
||||
if (signature.typePredicate) {
|
||||
writer.writeParameter(signature.typePredicate.parameterName);
|
||||
if (signature.typePredicate.kind === TypePredicateKind.Identifier) {
|
||||
writer.writeParameter((signature.typePredicate as IdentifierTypePredicate).parameterName);
|
||||
}
|
||||
else {
|
||||
writeKeyword(writer, SyntaxKind.ThisKeyword);
|
||||
}
|
||||
writeSpace(writer);
|
||||
writeKeyword(writer, SyntaxKind.IsKeyword);
|
||||
writeSpace(writer);
|
||||
@@ -3356,7 +3361,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[],
|
||||
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
|
||||
resolvedReturnType: Type, typePredicate: IdentifierTypePredicate | ThisTypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
|
||||
const sig = new Signature(checker);
|
||||
sig.declaration = declaration;
|
||||
sig.typeParameters = typeParameters;
|
||||
@@ -3884,19 +3889,29 @@ namespace ts {
|
||||
}
|
||||
|
||||
let returnType: Type;
|
||||
let typePredicate: TypePredicate;
|
||||
let typePredicate: IdentifierTypePredicate | ThisTypePredicate;
|
||||
if (classType) {
|
||||
returnType = classType;
|
||||
}
|
||||
else if (declaration.type) {
|
||||
returnType = getTypeFromTypeNode(declaration.type);
|
||||
if (declaration.type.kind === SyntaxKind.TypePredicate) {
|
||||
const typePredicateNode = <TypePredicateNode>declaration.type;
|
||||
typePredicate = {
|
||||
parameterName: typePredicateNode.parameterName ? typePredicateNode.parameterName.text : undefined,
|
||||
parameterIndex: typePredicateNode.parameterName ? getTypePredicateParameterIndex(declaration.parameters, typePredicateNode.parameterName) : undefined,
|
||||
type: getTypeFromTypeNode(typePredicateNode.type)
|
||||
};
|
||||
const typePredicateNode = declaration.type as TypePredicateNode;
|
||||
if (typePredicateNode.parameterName.kind === SyntaxKind.Identifier) {
|
||||
const parameterName = typePredicateNode.parameterName as Identifier;
|
||||
typePredicate = {
|
||||
kind: TypePredicateKind.Identifier,
|
||||
parameterName: parameterName ? parameterName.text : undefined,
|
||||
parameterIndex: parameterName ? getTypePredicateParameterIndex(declaration.parameters, parameterName) : undefined,
|
||||
type: getTypeFromTypeNode(typePredicateNode.type)
|
||||
};
|
||||
}
|
||||
else {
|
||||
typePredicate = {
|
||||
kind: TypePredicateKind.This,
|
||||
type: getTypeFromTypeNode(typePredicateNode.type)
|
||||
} as ThisTypePredicate;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -4716,19 +4731,33 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function cloneTypePredicate(predicate: TypePredicate, mapper: TypeMapper): ThisTypePredicate | IdentifierTypePredicate {
|
||||
if (predicate.kind === TypePredicateKind.Identifier) {
|
||||
const identifierPredicate = predicate as IdentifierTypePredicate;
|
||||
return {
|
||||
kind: TypePredicateKind.Identifier,
|
||||
parameterName: identifierPredicate.parameterName,
|
||||
parameterIndex: identifierPredicate.parameterIndex,
|
||||
type: instantiateType(predicate.type, mapper)
|
||||
} as IdentifierTypePredicate;
|
||||
}
|
||||
else {
|
||||
return {
|
||||
kind: TypePredicateKind.This,
|
||||
type: instantiateType(predicate.type, mapper)
|
||||
} as ThisTypePredicate;
|
||||
}
|
||||
}
|
||||
|
||||
function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature {
|
||||
let freshTypeParameters: TypeParameter[];
|
||||
let freshTypePredicate: TypePredicate;
|
||||
let freshTypePredicate: ThisTypePredicate | IdentifierTypePredicate;
|
||||
if (signature.typeParameters && !eraseTypeParameters) {
|
||||
freshTypeParameters = instantiateList(signature.typeParameters, mapper, instantiateTypeParameter);
|
||||
mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
|
||||
}
|
||||
if (signature.typePredicate) {
|
||||
freshTypePredicate = {
|
||||
parameterName: signature.typePredicate.parameterName,
|
||||
parameterIndex: signature.typePredicate.parameterIndex,
|
||||
type: instantiateType(signature.typePredicate.type, mapper)
|
||||
};
|
||||
freshTypePredicate = cloneTypePredicate(signature.typePredicate, mapper);
|
||||
}
|
||||
const result = createSignature(signature.declaration, freshTypeParameters,
|
||||
instantiateList(signature.parameters, mapper, instantiateSymbol),
|
||||
@@ -5548,33 +5577,55 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (source.typePredicate && target.typePredicate) {
|
||||
const hasDifferentParameterIndex = source.typePredicate.parameterIndex !== target.typePredicate.parameterIndex;
|
||||
let hasDifferentTypes: boolean;
|
||||
if (hasDifferentParameterIndex ||
|
||||
(hasDifferentTypes = !isTypeIdenticalTo(source.typePredicate.type, target.typePredicate.type))) {
|
||||
|
||||
if (source.typePredicate.kind !== target.typePredicate.kind) {
|
||||
if (reportErrors) {
|
||||
const sourceParamText = source.typePredicate.parameterName;
|
||||
const targetParamText = target.typePredicate.parameterName;
|
||||
const sourceTypeText = typeToString(source.typePredicate.type);
|
||||
const targetTypeText = typeToString(target.typePredicate.type);
|
||||
|
||||
if (hasDifferentParameterIndex) {
|
||||
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1,
|
||||
sourceParamText,
|
||||
targetParamText);
|
||||
}
|
||||
else if (hasDifferentTypes) {
|
||||
reportError(Diagnostics.A_this_based_type_guard_is_not_assignable_to_a_parameter_based_type_guard);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
if (source.typePredicate.kind === TypePredicateKind.This) {
|
||||
if (!isTypeIdenticalTo(source.typePredicate.type, target.typePredicate.type)) {
|
||||
if (reportErrors) {
|
||||
const sourceTypeText = typeToString(source.typePredicate.type);
|
||||
const targetTypeText = typeToString(target.typePredicate.type);
|
||||
reportError(Diagnostics.Type_0_is_not_assignable_to_type_1,
|
||||
sourceTypeText,
|
||||
targetTypeText);
|
||||
}
|
||||
|
||||
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1,
|
||||
`${sourceParamText} is ${sourceTypeText}`,
|
||||
`${targetParamText} is ${targetTypeText}`);
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const sourcePredicate = source.typePredicate as IdentifierTypePredicate;
|
||||
const targetPredicate = target.typePredicate as IdentifierTypePredicate;
|
||||
const hasDifferentParameterIndex = sourcePredicate.parameterIndex !== targetPredicate.parameterIndex;
|
||||
let hasDifferentTypes: boolean;
|
||||
if (hasDifferentParameterIndex ||
|
||||
(hasDifferentTypes = !isTypeIdenticalTo(sourcePredicate.type, targetPredicate.type))) {
|
||||
|
||||
if (reportErrors) {
|
||||
const sourceParamText = sourcePredicate.parameterName;
|
||||
const targetParamText = targetPredicate.parameterName;
|
||||
const sourceTypeText = typeToString(sourcePredicate.type);
|
||||
const targetTypeText = typeToString(targetPredicate.type);
|
||||
|
||||
if (hasDifferentParameterIndex) {
|
||||
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1,
|
||||
sourceParamText,
|
||||
targetParamText);
|
||||
}
|
||||
else if (hasDifferentTypes) {
|
||||
reportError(Diagnostics.Type_0_is_not_assignable_to_type_1,
|
||||
sourceTypeText,
|
||||
targetTypeText);
|
||||
}
|
||||
|
||||
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1,
|
||||
`${sourceParamText} is ${sourceTypeText}`,
|
||||
`${targetParamText} is ${targetTypeText}`);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (!source.typePredicate && target.typePredicate) {
|
||||
@@ -6235,11 +6286,15 @@ namespace ts {
|
||||
function inferFromSignature(source: Signature, target: Signature) {
|
||||
forEachMatchingParameterType(source, target, inferFromTypes);
|
||||
if (source.typePredicate && target.typePredicate) {
|
||||
if (target.typePredicate.parameterIndex === source.typePredicate.parameterIndex) {
|
||||
// Return types from type predicates are treated as booleans. In order to infer types
|
||||
// from type predicates we would need to infer using the type within the type predicate
|
||||
// (i.e. 'Foo' from 'x is Foo').
|
||||
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
|
||||
if (target.typePredicate.kind === source.typePredicate.kind) {
|
||||
if ((target.typePredicate.kind === TypePredicateKind.Identifier
|
||||
&& (target.typePredicate as IdentifierTypePredicate).parameterIndex === (source.typePredicate as IdentifierTypePredicate).parameterIndex)
|
||||
|| target.typePredicate.kind === TypePredicateKind.This) {
|
||||
// Return types from type predicates are treated as booleans. In order to infer types
|
||||
// from type predicates we would need to infer using the type within the type predicate
|
||||
// (i.e. 'Foo' from 'x is Foo').
|
||||
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -6654,20 +6709,20 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (targetType) {
|
||||
if (!assumeTrue) {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, targetType)));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
return getNarrowedType(type, targetType);
|
||||
return getNarrowedType(type, targetType, assumeTrue);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
function getNarrowedType(originalType: Type, narrowedTypeCandidate: Type) {
|
||||
function getNarrowedType(originalType: Type, narrowedTypeCandidate: Type, assumeTrue: boolean) {
|
||||
if (!assumeTrue) {
|
||||
if (originalType.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>originalType).types, t => !isTypeSubtypeOf(t, narrowedTypeCandidate)));
|
||||
}
|
||||
return originalType;
|
||||
}
|
||||
|
||||
// If the current type is a union type, remove all constituents that aren't assignable to target. If that produces
|
||||
// 0 candidates, fall back to the assignability check
|
||||
if (originalType.flags & TypeFlags.Union) {
|
||||
@@ -6691,19 +6746,35 @@ namespace ts {
|
||||
}
|
||||
const signature = getResolvedSignature(expr);
|
||||
|
||||
if (signature.typePredicate &&
|
||||
expr.arguments[signature.typePredicate.parameterIndex] &&
|
||||
getSymbolAtLocation(expr.arguments[signature.typePredicate.parameterIndex]) === symbol) {
|
||||
|
||||
if (!assumeTrue) {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, signature.typePredicate.type)));
|
||||
}
|
||||
return type;
|
||||
if (!signature.typePredicate) {
|
||||
return type;
|
||||
}
|
||||
const predicate = signature.typePredicate;
|
||||
if (isIdentifierTypePredicate(predicate)) {
|
||||
if (expr.arguments[predicate.parameterIndex] &&
|
||||
getSymbolAtLocation(expr.arguments[predicate.parameterIndex]) === symbol) {
|
||||
return getNarrowedType(type, predicate.type, assumeTrue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const expression = skipParenthesizedNodes(expr.expression);
|
||||
|
||||
if (expression.kind === SyntaxKind.ElementAccessExpression || expression.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
const accessExpression = expression as ElementAccessExpression | PropertyAccessExpression;
|
||||
const possibleIdentifier = skipParenthesizedNodes(accessExpression.expression);
|
||||
if (possibleIdentifier.kind === SyntaxKind.Identifier && getSymbolAtLocation(possibleIdentifier) === symbol) {
|
||||
return getNarrowedType(type, predicate.type, assumeTrue);
|
||||
}
|
||||
}
|
||||
return getNarrowedType(type, signature.typePredicate.type);
|
||||
}
|
||||
return type;
|
||||
|
||||
function skipParenthesizedNodes(expression: Expression): Expression {
|
||||
while (expression.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
expression = (expression as ParenthesizedExpression).expression;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
}
|
||||
|
||||
// Narrow the given type based on the given expression having the assumed boolean value. The returned type
|
||||
@@ -10962,51 +11033,57 @@ namespace ts {
|
||||
const typePredicate = getSignatureFromDeclaration(node).typePredicate;
|
||||
const typePredicateNode = <TypePredicateNode>node.type;
|
||||
if (isInLegalTypePredicatePosition(typePredicateNode)) {
|
||||
if (typePredicate.parameterIndex >= 0) {
|
||||
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
|
||||
error(typePredicateNode.parameterName,
|
||||
Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
|
||||
if (isIdentifierTypePredicate(typePredicate)) {
|
||||
if (typePredicate.parameterIndex >= 0) {
|
||||
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
|
||||
error(typePredicateNode.parameterName,
|
||||
Diagnostics.A_type_predicate_cannot_reference_a_rest_parameter);
|
||||
}
|
||||
else {
|
||||
checkTypeAssignableTo(typePredicate.type,
|
||||
getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
|
||||
typePredicateNode.type);
|
||||
}
|
||||
}
|
||||
else {
|
||||
checkTypeAssignableTo(typePredicate.type,
|
||||
getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
|
||||
typePredicateNode.type);
|
||||
else if (typePredicateNode.parameterName) {
|
||||
let hasReportedError = false;
|
||||
for (var param of node.parameters) {
|
||||
if (hasReportedError) {
|
||||
break;
|
||||
}
|
||||
if (param.name.kind === SyntaxKind.ObjectBindingPattern ||
|
||||
param.name.kind === SyntaxKind.ArrayBindingPattern) {
|
||||
|
||||
(function checkBindingPattern(pattern: BindingPattern) {
|
||||
for (const element of pattern.elements) {
|
||||
if (element.name.kind === SyntaxKind.Identifier &&
|
||||
(<Identifier>element.name).text === typePredicate.parameterName) {
|
||||
|
||||
error(typePredicateNode.parameterName,
|
||||
Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
|
||||
typePredicate.parameterName);
|
||||
hasReportedError = true;
|
||||
break;
|
||||
}
|
||||
else if (element.name.kind === SyntaxKind.ArrayBindingPattern ||
|
||||
element.name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
|
||||
checkBindingPattern(<BindingPattern>element.name);
|
||||
}
|
||||
}
|
||||
})(<BindingPattern>param.name);
|
||||
}
|
||||
}
|
||||
if (!hasReportedError) {
|
||||
error(typePredicateNode.parameterName,
|
||||
Diagnostics.Cannot_find_parameter_0,
|
||||
typePredicate.parameterName);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (typePredicateNode.parameterName) {
|
||||
let hasReportedError = false;
|
||||
for (var param of node.parameters) {
|
||||
if (hasReportedError) {
|
||||
break;
|
||||
}
|
||||
if (param.name.kind === SyntaxKind.ObjectBindingPattern ||
|
||||
param.name.kind === SyntaxKind.ArrayBindingPattern) {
|
||||
|
||||
(function checkBindingPattern(pattern: BindingPattern) {
|
||||
for (const element of pattern.elements) {
|
||||
if (element.name.kind === SyntaxKind.Identifier &&
|
||||
(<Identifier>element.name).text === typePredicate.parameterName) {
|
||||
|
||||
error(typePredicateNode.parameterName,
|
||||
Diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern,
|
||||
typePredicate.parameterName);
|
||||
hasReportedError = true;
|
||||
break;
|
||||
}
|
||||
else if (element.name.kind === SyntaxKind.ArrayBindingPattern ||
|
||||
element.name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
|
||||
checkBindingPattern(<BindingPattern>element.name);
|
||||
}
|
||||
}
|
||||
})(<BindingPattern>param.name);
|
||||
}
|
||||
}
|
||||
if (!hasReportedError) {
|
||||
error(typePredicateNode.parameterName,
|
||||
Diagnostics.Cannot_find_parameter_0,
|
||||
typePredicate.parameterName);
|
||||
}
|
||||
else {
|
||||
// Reuse this type diagnostics on the this type node to determine if a this type predicate is valid
|
||||
getTypeFromThisTypeNode(typePredicateNode.parameterName as ThisTypeNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1632,6 +1632,10 @@
|
||||
"category": "Error",
|
||||
"code": 2517
|
||||
},
|
||||
"A this based type guard is not assignable to a parameter based type guard": {
|
||||
"category": "Error",
|
||||
"code": 2518
|
||||
},
|
||||
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
|
||||
"category": "Error",
|
||||
"code": 2520
|
||||
|
||||
@@ -1959,11 +1959,7 @@ namespace ts {
|
||||
function parseTypeReferenceOrTypePredicate(): TypeReferenceNode | TypePredicateNode {
|
||||
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);
|
||||
return parseTypePredicate(typeName as Identifier);
|
||||
}
|
||||
const node = <TypeReferenceNode>createNode(SyntaxKind.TypeReference, typeName.pos);
|
||||
node.typeName = typeName;
|
||||
@@ -1973,8 +1969,16 @@ namespace ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseThisTypeNode(): TypeNode {
|
||||
const node = <TypeNode>createNode(SyntaxKind.ThisType);
|
||||
function parseTypePredicate(lhs: Identifier | ThisTypeNode): TypePredicateNode {
|
||||
nextToken();
|
||||
const node = createNode(SyntaxKind.TypePredicate, lhs.pos) as TypePredicateNode;
|
||||
node.parameterName = lhs;
|
||||
node.type = parseType();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseThisTypeNode(): ThisTypeNode {
|
||||
const node = createNode(SyntaxKind.ThisType) as ThisTypeNode;
|
||||
nextToken();
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -2420,8 +2424,15 @@ namespace ts {
|
||||
return parseStringLiteralTypeNode();
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return parseTokenNode<TypeNode>();
|
||||
case SyntaxKind.ThisKeyword:
|
||||
return parseThisTypeNode();
|
||||
case SyntaxKind.ThisKeyword: {
|
||||
const thisKeyword = parseThisTypeNode();
|
||||
if (token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
|
||||
return parseTypePredicate(thisKeyword);
|
||||
}
|
||||
else {
|
||||
return thisKeyword;
|
||||
}
|
||||
}
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
return parseTypeQuery();
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
|
||||
@@ -733,11 +733,15 @@ namespace ts {
|
||||
// @kind(SyntaxKind.StringKeyword)
|
||||
// @kind(SyntaxKind.SymbolKeyword)
|
||||
// @kind(SyntaxKind.VoidKeyword)
|
||||
// @kind(SyntaxKind.ThisType)
|
||||
export interface TypeNode extends Node {
|
||||
_typeNodeBrand: any;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.ThisType)
|
||||
export interface ThisTypeNode extends TypeNode {
|
||||
_thisTypeNodeBrand: any;
|
||||
}
|
||||
|
||||
export interface FunctionOrConstructorTypeNode extends TypeNode, SignatureDeclaration {
|
||||
_functionOrConstructorTypeNodeBrand: any;
|
||||
}
|
||||
@@ -756,7 +760,7 @@ namespace ts {
|
||||
|
||||
// @kind(SyntaxKind.TypePredicate)
|
||||
export interface TypePredicateNode extends TypeNode {
|
||||
parameterName: Identifier;
|
||||
parameterName: Identifier | ThisTypeNode;
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
@@ -1820,10 +1824,26 @@ namespace ts {
|
||||
CannotBeNamed
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export const enum TypePredicateKind {
|
||||
This,
|
||||
Identifier
|
||||
}
|
||||
|
||||
export interface TypePredicate {
|
||||
kind: TypePredicateKind;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
// @kind (TypePredicateKind.This)
|
||||
export interface ThisTypePredicate extends TypePredicate {
|
||||
_thisTypePredicateBrand: any;
|
||||
}
|
||||
|
||||
// @kind (TypePredicateKind.Identifier)
|
||||
export interface IdentifierTypePredicate extends TypePredicate {
|
||||
parameterName: string;
|
||||
parameterIndex: number;
|
||||
type: Type;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@@ -2237,7 +2257,7 @@ namespace ts {
|
||||
declaration: SignatureDeclaration; // Originating declaration
|
||||
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
|
||||
parameters: Symbol[]; // Parameters
|
||||
typePredicate?: TypePredicate; // Type predicate
|
||||
typePredicate?: ThisTypePredicate | IdentifierTypePredicate; // Type predicate
|
||||
/* @internal */
|
||||
resolvedReturnType: Type; // Resolved return type
|
||||
/* @internal */
|
||||
|
||||
@@ -692,6 +692,10 @@ namespace ts {
|
||||
return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression;
|
||||
}
|
||||
|
||||
export function isIdentifierTypePredicate(predicate: TypePredicate): predicate is IdentifierTypePredicate {
|
||||
return predicate.kind === TypePredicateKind.Identifier;
|
||||
}
|
||||
|
||||
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
|
||||
Reference in New Issue
Block a user