mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge pull request #5906 from weswigham/this-type-guards
This type predicates for type guards
This commit is contained in:
+13
-1
@@ -1189,7 +1189,8 @@ namespace ts {
|
||||
case SyntaxKind.ThisType:
|
||||
seenThisKeyword = true;
|
||||
return;
|
||||
|
||||
case SyntaxKind.TypePredicate:
|
||||
return checkTypePredicate(node as TypePredicateNode);
|
||||
case SyntaxKind.TypeParameter:
|
||||
return declareSymbolAndAddToSymbolTable(<Declaration>node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes);
|
||||
case SyntaxKind.Parameter:
|
||||
@@ -1275,6 +1276,17 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkTypePredicate(node: TypePredicateNode) {
|
||||
const { parameterName, type } = node;
|
||||
if (parameterName && parameterName.kind === SyntaxKind.Identifier) {
|
||||
checkStrictModeIdentifier(parameterName as Identifier);
|
||||
}
|
||||
if (parameterName && parameterName.kind === SyntaxKind.ThisType) {
|
||||
seenThisKeyword = true;
|
||||
}
|
||||
bind(type);
|
||||
}
|
||||
|
||||
function bindSourceFileIfExternalModule() {
|
||||
setExportContextFlag(file);
|
||||
if (isExternalModule(file)) {
|
||||
|
||||
+241
-121
@@ -124,8 +124,8 @@ namespace ts {
|
||||
|
||||
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
|
||||
|
||||
const anySignature = createSignature(undefined, undefined, emptyArray, anyType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
|
||||
const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
|
||||
const anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
|
||||
const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
|
||||
|
||||
const globals: SymbolTable = {};
|
||||
|
||||
@@ -1743,10 +1743,16 @@ namespace ts {
|
||||
function writeType(type: Type, flags: TypeFormatFlags) {
|
||||
// Write undefined/null type as any
|
||||
if (type.flags & TypeFlags.Intrinsic) {
|
||||
// Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
|
||||
writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type)
|
||||
? "any"
|
||||
: (<IntrinsicType>type).intrinsicName);
|
||||
if (type.flags & TypeFlags.PredicateType) {
|
||||
buildTypePredicateDisplay(writer, (type as PredicateType).predicate);
|
||||
buildTypeDisplay((type as PredicateType).predicate.type, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
else {
|
||||
// Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
|
||||
writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type)
|
||||
? "any"
|
||||
: (<IntrinsicType>type).intrinsicName);
|
||||
}
|
||||
}
|
||||
else if (type.flags & TypeFlags.ThisType) {
|
||||
if (inObjectTypeLiteral) {
|
||||
@@ -2116,6 +2122,18 @@ namespace ts {
|
||||
writePunctuation(writer, SyntaxKind.CloseParenToken);
|
||||
}
|
||||
|
||||
function buildTypePredicateDisplay(writer: SymbolWriter, predicate: TypePredicate) {
|
||||
if (isIdentifierTypePredicate(predicate)) {
|
||||
writer.writeParameter(predicate.parameterName);
|
||||
}
|
||||
else {
|
||||
writeKeyword(writer, SyntaxKind.ThisKeyword);
|
||||
}
|
||||
writeSpace(writer);
|
||||
writeKeyword(writer, SyntaxKind.IsKeyword);
|
||||
writeSpace(writer);
|
||||
}
|
||||
|
||||
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
|
||||
writeSpace(writer);
|
||||
@@ -2126,17 +2144,7 @@ namespace ts {
|
||||
}
|
||||
writeSpace(writer);
|
||||
|
||||
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);
|
||||
}
|
||||
const returnType = getReturnTypeOfSignature(signature);
|
||||
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
|
||||
}
|
||||
|
||||
@@ -2693,7 +2701,13 @@ namespace ts {
|
||||
// During a normal type check we'll never get to here with a property assignment (the check of the containing
|
||||
// object literal uses a different path). We exclude widening only so that language services and type verification
|
||||
// tools see the actual type.
|
||||
return declaration.kind !== SyntaxKind.PropertyAssignment ? getWidenedType(type) : type;
|
||||
if (declaration.kind === SyntaxKind.PropertyAssignment) {
|
||||
return type;
|
||||
}
|
||||
if (type.flags & TypeFlags.PredicateType && (declaration.kind === SyntaxKind.PropertyDeclaration || declaration.kind === SyntaxKind.PropertySignature)) {
|
||||
return type;
|
||||
}
|
||||
return getWidenedType(type);
|
||||
}
|
||||
|
||||
// Rest parameters default to type any[], other parameters default to type any
|
||||
@@ -3427,13 +3441,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[],
|
||||
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
|
||||
resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
|
||||
const sig = new Signature(checker);
|
||||
sig.declaration = declaration;
|
||||
sig.typeParameters = typeParameters;
|
||||
sig.parameters = parameters;
|
||||
sig.resolvedReturnType = resolvedReturnType;
|
||||
sig.typePredicate = typePredicate;
|
||||
sig.minArgumentCount = minArgumentCount;
|
||||
sig.hasRestParameter = hasRestParameter;
|
||||
sig.hasStringLiterals = hasStringLiterals;
|
||||
@@ -3441,7 +3454,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function cloneSignature(sig: Signature): Signature {
|
||||
return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType, sig.typePredicate,
|
||||
return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType,
|
||||
sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
|
||||
}
|
||||
|
||||
@@ -3449,7 +3462,7 @@ namespace ts {
|
||||
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
|
||||
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
|
||||
if (baseSignatures.length === 0) {
|
||||
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
|
||||
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
|
||||
}
|
||||
const baseTypeNode = getBaseTypeNodeOfClass(classType);
|
||||
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
|
||||
@@ -3915,6 +3928,24 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function createTypePredicateFromTypePredicateNode(node: TypePredicateNode): IdentifierTypePredicate | ThisTypePredicate {
|
||||
if (node.parameterName.kind === SyntaxKind.Identifier) {
|
||||
const parameterName = node.parameterName as Identifier;
|
||||
return {
|
||||
kind: TypePredicateKind.Identifier,
|
||||
parameterName: parameterName ? parameterName.text : undefined,
|
||||
parameterIndex: parameterName ? getTypePredicateParameterIndex((node.parent as SignatureDeclaration).parameters, parameterName) : undefined,
|
||||
type: getTypeFromTypeNode(node.type)
|
||||
} as IdentifierTypePredicate;
|
||||
}
|
||||
else {
|
||||
return {
|
||||
kind: TypePredicateKind.This,
|
||||
type: getTypeFromTypeNode(node.type)
|
||||
} as ThisTypePredicate;
|
||||
}
|
||||
}
|
||||
|
||||
function getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature {
|
||||
const links = getNodeLinks(declaration);
|
||||
if (!links.resolvedSignature) {
|
||||
@@ -3955,20 +3986,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
let returnType: Type;
|
||||
let typePredicate: TypePredicate;
|
||||
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)
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
// TypeScript 1.0 spec (April 2014):
|
||||
@@ -3983,8 +4005,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, typePredicate,
|
||||
minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
|
||||
links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
|
||||
}
|
||||
return links.resolvedSignature;
|
||||
}
|
||||
@@ -4643,6 +4664,25 @@ namespace ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getPredicateType(node: TypePredicateNode): Type {
|
||||
return createPredicateType(getSymbolOfNode(node), createTypePredicateFromTypePredicateNode(node));
|
||||
}
|
||||
|
||||
function createPredicateType(symbol: Symbol, predicate: ThisTypePredicate | IdentifierTypePredicate) {
|
||||
const type = createType(TypeFlags.Boolean | TypeFlags.PredicateType) as PredicateType;
|
||||
type.symbol = symbol;
|
||||
type.predicate = predicate;
|
||||
return type;
|
||||
}
|
||||
|
||||
function getTypeFromPredicateTypeNode(node: TypePredicateNode): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = getPredicateType(node);
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getTypeFromTypeNode(node: TypeNode): Type {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
@@ -4664,7 +4704,7 @@ namespace ts {
|
||||
case SyntaxKind.TypeReference:
|
||||
return getTypeFromTypeReference(<TypeReferenceNode>node);
|
||||
case SyntaxKind.TypePredicate:
|
||||
return booleanType;
|
||||
return getTypeFromPredicateTypeNode(<TypePredicateNode>node);
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
return getTypeFromTypeReference(<ExpressionWithTypeArguments>node);
|
||||
case SyntaxKind.TypeQuery:
|
||||
@@ -4787,24 +4827,32 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function cloneTypePredicate(predicate: TypePredicate, mapper: TypeMapper): ThisTypePredicate | IdentifierTypePredicate {
|
||||
if (isIdentifierTypePredicate(predicate)) {
|
||||
return {
|
||||
kind: TypePredicateKind.Identifier,
|
||||
parameterName: predicate.parameterName,
|
||||
parameterIndex: predicate.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;
|
||||
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)
|
||||
};
|
||||
}
|
||||
const result = createSignature(signature.declaration, freshTypeParameters,
|
||||
instantiateList(signature.parameters, mapper, instantiateSymbol),
|
||||
instantiateType(signature.resolvedReturnType, mapper),
|
||||
freshTypePredicate,
|
||||
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
|
||||
result.target = signature;
|
||||
result.mapper = mapper;
|
||||
@@ -4874,6 +4922,10 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType));
|
||||
}
|
||||
if (type.flags & TypeFlags.PredicateType) {
|
||||
const predicate = (type as PredicateType).predicate;
|
||||
return createPredicateType(type.symbol, cloneTypePredicate(predicate, mapper));
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@@ -5045,6 +5097,36 @@ namespace ts {
|
||||
if (isTypeAny(source)) return Ternary.True;
|
||||
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
|
||||
}
|
||||
if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) {
|
||||
if (source.flags & TypeFlags.PredicateType && target.flags & TypeFlags.PredicateType) {
|
||||
const sourcePredicate = source as PredicateType;
|
||||
const targetPredicate = target as PredicateType;
|
||||
if (sourcePredicate.predicate.kind !== targetPredicate.predicate.kind) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard);
|
||||
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
if (sourcePredicate.predicate.kind === TypePredicateKind.Identifier) {
|
||||
const sourceIdentifierPredicate = sourcePredicate.predicate as IdentifierTypePredicate;
|
||||
const targetIdentifierPredicate = targetPredicate.predicate as IdentifierTypePredicate;
|
||||
if (sourceIdentifierPredicate.parameterIndex !== targetIdentifierPredicate.parameterIndex) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourceIdentifierPredicate.parameterName, targetIdentifierPredicate.parameterName);
|
||||
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
const related = isRelatedTo(sourcePredicate.predicate.type, targetPredicate.predicate.type, reportErrors, headMessage);
|
||||
if (related === Ternary.False && reportErrors) {
|
||||
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
|
||||
}
|
||||
return related;
|
||||
}
|
||||
return Ternary.True;
|
||||
}
|
||||
|
||||
if (source.flags & TypeFlags.FreshObjectLiteral) {
|
||||
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
|
||||
@@ -5610,46 +5692,19 @@ namespace ts {
|
||||
result &= related;
|
||||
}
|
||||
|
||||
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))) {
|
||||
const targetReturnType = getReturnTypeOfSignature(target);
|
||||
if (targetReturnType === voidType) return result;
|
||||
const sourceReturnType = getReturnTypeOfSignature(source);
|
||||
|
||||
// The follow block preserves old behavior forbidding boolean returning functions from being assignable to type guard returning functions
|
||||
if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) {
|
||||
if (!(sourceReturnType.flags & TypeFlags.PredicateType)) {
|
||||
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.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}`);
|
||||
reportError(Diagnostics.Signature_0_must_have_a_type_predicate, signatureToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
else if (!source.typePredicate && target.typePredicate) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Signature_0_must_have_a_type_predicate, signatureToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
const targetReturnType = getReturnTypeOfSignature(target);
|
||||
if (targetReturnType === voidType) return result;
|
||||
const sourceReturnType = getReturnTypeOfSignature(source);
|
||||
|
||||
return result & isRelatedTo(sourceReturnType, targetReturnType, reportErrors);
|
||||
}
|
||||
@@ -5986,6 +6041,9 @@ namespace ts {
|
||||
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
|
||||
return anyType;
|
||||
}
|
||||
if (type.flags & TypeFlags.PredicateType) {
|
||||
return booleanType;
|
||||
}
|
||||
if (type.flags & TypeFlags.ObjectLiteral) {
|
||||
return getWidenedTypeOfObjectLiteral(type);
|
||||
}
|
||||
@@ -6209,6 +6267,11 @@ namespace ts {
|
||||
inferFromTypes(sourceTypes[i], targetTypes[i]);
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.PredicateType && target.flags & TypeFlags.PredicateType) {
|
||||
if ((source as PredicateType).predicate.kind === (target as PredicateType).predicate.kind) {
|
||||
inferFromTypes((source as PredicateType).predicate.type, (target as PredicateType).predicate.type);
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.Tuple && target.flags & TypeFlags.Tuple && (<TupleType>source).elementTypes.length === (<TupleType>target).elementTypes.length) {
|
||||
// If source and target are tuples of the same size, infer from element types
|
||||
const sourceTypes = (<TupleType>source).elementTypes;
|
||||
@@ -6304,17 +6367,7 @@ 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);
|
||||
}
|
||||
}
|
||||
else {
|
||||
inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
|
||||
}
|
||||
inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
|
||||
}
|
||||
|
||||
function inferFromIndexTypes(source: Type, target: Type, sourceKind: IndexKind, targetKind: IndexKind) {
|
||||
@@ -6453,10 +6506,7 @@ namespace ts {
|
||||
|
||||
function isAssignedInBinaryExpression(node: BinaryExpression) {
|
||||
if (node.operatorToken.kind >= SyntaxKind.FirstAssignment && node.operatorToken.kind <= SyntaxKind.LastAssignment) {
|
||||
let n = node.left;
|
||||
while (n.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
n = (<ParenthesizedExpression>n).expression;
|
||||
}
|
||||
const n = skipParenthesizedNodes(node.left);
|
||||
if (n.kind === SyntaxKind.Identifier && getResolvedSymbol(<Identifier>n) === symbol) {
|
||||
return true;
|
||||
}
|
||||
@@ -6712,20 +6762,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) {
|
||||
@@ -6748,22 +6798,59 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
const signature = getResolvedSignature(expr);
|
||||
const predicateType = getReturnTypeOfSignature(signature);
|
||||
|
||||
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 (!predicateType || !(predicateType.flags & TypeFlags.PredicateType)) {
|
||||
return type;
|
||||
}
|
||||
const predicate = (predicateType as PredicateType).predicate;
|
||||
if (isIdentifierTypePredicate(predicate)) {
|
||||
const callExpression = expr as CallExpression;
|
||||
if (callExpression.arguments[predicate.parameterIndex] &&
|
||||
getSymbolAtTypePredicatePosition(callExpression.arguments[predicate.parameterIndex]) === symbol) {
|
||||
return getNarrowedType(type, predicate.type, assumeTrue);
|
||||
}
|
||||
return getNarrowedType(type, signature.typePredicate.type);
|
||||
}
|
||||
else {
|
||||
const expression = skipParenthesizedNodes(expr.expression);
|
||||
return narrowTypeByThisTypePredicate(type, predicate, expression, assumeTrue);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function narrowTypeByTypePredicateMember(type: Type, expr: ElementAccessExpression | PropertyAccessExpression, assumeTrue: boolean): Type {
|
||||
if (type.flags & TypeFlags.Any) {
|
||||
return type;
|
||||
}
|
||||
const memberType = getTypeOfExpression(expr);
|
||||
if (!(memberType.flags & TypeFlags.PredicateType)) {
|
||||
return type;
|
||||
}
|
||||
|
||||
return narrowTypeByThisTypePredicate(type, (memberType as PredicateType).predicate as ThisTypePredicate, expr, assumeTrue);
|
||||
}
|
||||
|
||||
function narrowTypeByThisTypePredicate(type: Type, predicate: ThisTypePredicate, expression: Expression, assumeTrue: boolean): Type {
|
||||
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 && getSymbolAtTypePredicatePosition(possibleIdentifier) === symbol) {
|
||||
return getNarrowedType(type, predicate.type, assumeTrue);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getSymbolAtTypePredicatePosition(expr: Expression): Symbol {
|
||||
expr = skipParenthesizedNodes(expr);
|
||||
switch (expr.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.QualifiedName:
|
||||
return getSymbolOfEntityNameOrPropertyAccessExpression(expr as Node as (EntityName | PropertyAccessExpression));
|
||||
}
|
||||
}
|
||||
|
||||
// Narrow the given type based on the given expression having the assumed boolean value. The returned type
|
||||
// will be a subtype or the same type as the argument.
|
||||
function narrowType(type: Type, expr: Expression, assumeTrue: boolean): Type {
|
||||
@@ -6792,11 +6879,21 @@ namespace ts {
|
||||
return narrowType(type, (<PrefixUnaryExpression>expr).operand, !assumeTrue);
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return narrowTypeByTypePredicateMember(type, expr as (ElementAccessExpression | PropertyAccessExpression), assumeTrue);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
function skipParenthesizedNodes(expression: Expression): Expression {
|
||||
while (expression.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
expression = (expression as ParenthesizedExpression).expression;
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
function checkIdentifier(node: Identifier): Type {
|
||||
const symbol = getResolvedSymbol(node);
|
||||
|
||||
@@ -10985,7 +11082,7 @@ namespace ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
function isInLegalTypePredicatePosition(node: Node): boolean {
|
||||
function isInLegalParameterTypePredicatePosition(node: Node): boolean {
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.CallSignature:
|
||||
@@ -10999,6 +11096,19 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function isInLegalThisTypePredicatePosition(node: Node): boolean {
|
||||
if (isInLegalParameterTypePredicatePosition(node)) {
|
||||
return true;
|
||||
}
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.GetAccessor:
|
||||
return node === (node.parent as (PropertyDeclaration | GetAccessorDeclaration | PropertySignature)).type;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkSignatureDeclaration(node: SignatureDeclaration) {
|
||||
// Grammar checking
|
||||
if (node.kind === SyntaxKind.IndexSignature) {
|
||||
@@ -11017,9 +11127,14 @@ namespace ts {
|
||||
|
||||
if (node.type) {
|
||||
if (node.type.kind === SyntaxKind.TypePredicate) {
|
||||
const typePredicate = getSignatureFromDeclaration(node).typePredicate;
|
||||
const typePredicateNode = <TypePredicateNode>node.type;
|
||||
if (isInLegalTypePredicatePosition(typePredicateNode)) {
|
||||
const returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(node));
|
||||
if (!returnType || !(returnType.flags & TypeFlags.PredicateType)) {
|
||||
return;
|
||||
}
|
||||
const typePredicate = (returnType as PredicateType).predicate;
|
||||
const typePredicateNode = node.type as TypePredicateNode;
|
||||
checkSourceElement(typePredicateNode);
|
||||
if (isIdentifierTypePredicate(typePredicate)) {
|
||||
if (typePredicate.parameterIndex >= 0) {
|
||||
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
|
||||
error(typePredicateNode.parameterName,
|
||||
@@ -11067,10 +11182,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
error(typePredicateNode,
|
||||
Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
|
||||
}
|
||||
}
|
||||
else {
|
||||
checkSourceElement(node.type);
|
||||
@@ -13027,7 +13138,7 @@ namespace ts {
|
||||
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
|
||||
}
|
||||
}
|
||||
else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func) || signature.typePredicate) {
|
||||
else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func) || returnType.flags & TypeFlags.PredicateType) {
|
||||
if (isAsyncFunctionLike(func)) {
|
||||
const promisedType = getPromisedType(returnType);
|
||||
const awaitedType = checkAwaitedType(exprType, node.expression, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
|
||||
@@ -14218,9 +14329,18 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkTypePredicate(node: TypePredicateNode) {
|
||||
if (!isInLegalTypePredicatePosition(node)) {
|
||||
const { parameterName } = node;
|
||||
if (parameterName.kind === SyntaxKind.Identifier && !isInLegalParameterTypePredicatePosition(node)) {
|
||||
error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
|
||||
}
|
||||
else if (parameterName.kind === SyntaxKind.ThisType) {
|
||||
if (!isInLegalThisTypePredicatePosition(node)) {
|
||||
error(node, Diagnostics.A_this_based_type_predicate_is_only_allowed_within_a_class_or_interface_s_members_get_accessors_or_return_type_positions_for_functions_and_methods);
|
||||
}
|
||||
else {
|
||||
getTypeFromThisTypeNode(parameterName as ThisTypeNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkSourceElement(node: Node): void {
|
||||
|
||||
@@ -1647,6 +1647,14 @@
|
||||
"category": "Error",
|
||||
"code": 2517
|
||||
},
|
||||
"A 'this'-based type guard is not compatible with a parameter-based type guard.": {
|
||||
"category": "Error",
|
||||
"code": 2518
|
||||
},
|
||||
"A 'this'-based type predicate is only allowed within a class or interface's members, get accessors, or return type positions for functions and methods.": {
|
||||
"category": "Error",
|
||||
"code": 2519
|
||||
},
|
||||
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
|
||||
"category": "Error",
|
||||
"code": 2520
|
||||
|
||||
+20
-9
@@ -1963,11 +1963,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;
|
||||
@@ -1977,8 +1973,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);
|
||||
}
|
||||
@@ -2424,8 +2428,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:
|
||||
|
||||
+29
-5
@@ -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,25 @@ namespace ts {
|
||||
CannotBeNamed
|
||||
}
|
||||
|
||||
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 */
|
||||
@@ -2091,6 +2110,7 @@ namespace ts {
|
||||
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
|
||||
ThisType = 0x02000000, // This type
|
||||
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
|
||||
PredicateType = 0x08000000, // Predicate types are also Boolean types, but should not be considered Intrinsics - there's no way to capture this with flags
|
||||
|
||||
/* @internal */
|
||||
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
|
||||
@@ -2102,7 +2122,7 @@ namespace ts {
|
||||
UnionOrIntersection = Union | Intersection,
|
||||
StructuredType = ObjectType | Union | Intersection,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral | PredicateType,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
}
|
||||
@@ -2123,6 +2143,11 @@ namespace ts {
|
||||
intrinsicName: string; // Name of intrinsic type
|
||||
}
|
||||
|
||||
// Predicate types (TypeFlags.Predicate)
|
||||
export interface PredicateType extends Type {
|
||||
predicate: ThisTypePredicate | IdentifierTypePredicate;
|
||||
}
|
||||
|
||||
// String literal types (TypeFlags.StringLiteral)
|
||||
export interface StringLiteralType extends Type {
|
||||
text: string; // Text of string literal
|
||||
@@ -2239,7 +2264,6 @@ namespace ts {
|
||||
declaration: SignatureDeclaration; // Originating declaration
|
||||
typeParameters: TypeParameter[]; // Type parameters (undefined if non-generic)
|
||||
parameters: Symbol[]; // Parameters
|
||||
typePredicate?: TypePredicate; // Type predicate
|
||||
/* @internal */
|
||||
resolvedReturnType: Type; // Resolved return type
|
||||
/* @internal */
|
||||
|
||||
@@ -693,6 +693,10 @@ namespace ts {
|
||||
return node && node.kind === SyntaxKind.MethodDeclaration && node.parent.kind === SyntaxKind.ObjectLiteralExpression;
|
||||
}
|
||||
|
||||
export function isIdentifierTypePredicate(predicate: TypePredicate): predicate is IdentifierTypePredicate {
|
||||
return predicate && predicate.kind === TypePredicateKind.Identifier;
|
||||
}
|
||||
|
||||
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
|
||||
while (true) {
|
||||
node = node.parent;
|
||||
|
||||
@@ -4,7 +4,7 @@ var obj: Object;
|
||||
>Object : Object
|
||||
|
||||
if (ArrayBuffer.isView(obj)) {
|
||||
>ArrayBuffer.isView(obj) : boolean
|
||||
>ArrayBuffer.isView(obj) : arg is ArrayBufferView
|
||||
>ArrayBuffer.isView : (arg: any) => arg is ArrayBufferView
|
||||
>ArrayBuffer : ArrayBufferConstructor
|
||||
>isView : (arg: any) => arg is ArrayBufferView
|
||||
|
||||
@@ -4,7 +4,7 @@ var maybeArray: number | number[];
|
||||
|
||||
|
||||
if (Array.isArray(maybeArray)) {
|
||||
>Array.isArray(maybeArray) : boolean
|
||||
>Array.isArray(maybeArray) : arg is any[]
|
||||
>Array.isArray : (arg: any) => arg is any[]
|
||||
>Array : ArrayConstructor
|
||||
>isArray : (arg: any) => arg is any[]
|
||||
|
||||
@@ -31,7 +31,7 @@ function f(foo: T) {
|
||||
>T : ("a" | "b")[] | "a" | "b"
|
||||
|
||||
if (isS(foo)) {
|
||||
>isS(foo) : boolean
|
||||
>isS(foo) : t is "a" | "b"
|
||||
>isS : (t: ("a" | "b")[] | "a" | "b") => t is "a" | "b"
|
||||
>foo : ("a" | "b")[] | "a" | "b"
|
||||
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(18,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
|
||||
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(19,10): error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
|
||||
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(20,10): error TS2394: Overload signature is not compatible with function implementation.
|
||||
tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(22,21): error TS2304: Cannot find name 'is'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts (4 errors) ====
|
||||
==== tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts (2 errors) ====
|
||||
|
||||
type Kind = "A" | "B"
|
||||
|
||||
@@ -23,11 +21,7 @@ tests/cases/conformance/types/stringLiteral/stringLiteralTypesAsTags01.ts(22,21)
|
||||
}
|
||||
|
||||
function hasKind(entity: Entity, kind: "A"): entity is A;
|
||||
~~~~~~~
|
||||
!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
|
||||
function hasKind(entity: Entity, kind: "B"): entity is B;
|
||||
~~~~~~~
|
||||
!!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature.
|
||||
function hasKind(entity: Entity, kind: Kind): entity is Entity;
|
||||
~~~~~~~
|
||||
!!! error TS2394: Overload signature is not compatible with function implementation.
|
||||
|
||||
@@ -54,7 +54,7 @@ var b: B;
|
||||
|
||||
// Basic
|
||||
if (isC(a)) {
|
||||
>isC(a) : boolean
|
||||
>isC(a) : p1 is C
|
||||
>isC : (p1: any) => p1 is C
|
||||
>a : A
|
||||
|
||||
@@ -70,7 +70,7 @@ var subType: C;
|
||||
>C : C
|
||||
|
||||
if(isA(subType)) {
|
||||
>isA(subType) : boolean
|
||||
>isA(subType) : p1 is A
|
||||
>isA : (p1: any) => p1 is A
|
||||
>subType : C
|
||||
|
||||
@@ -87,7 +87,7 @@ var union: A | B;
|
||||
>B : B
|
||||
|
||||
if(isA(union)) {
|
||||
>isA(union) : boolean
|
||||
>isA(union) : p1 is A
|
||||
>isA : (p1: any) => p1 is A
|
||||
>union : A | B
|
||||
|
||||
@@ -118,7 +118,7 @@ declare function isC_multipleParams(p1, p2): p1 is C;
|
||||
>C : C
|
||||
|
||||
if (isC_multipleParams(a, 0)) {
|
||||
>isC_multipleParams(a, 0) : boolean
|
||||
>isC_multipleParams(a, 0) : p1 is C
|
||||
>isC_multipleParams : (p1: any, p2: any) => p1 is C
|
||||
>a : A
|
||||
>0 : number
|
||||
@@ -197,7 +197,7 @@ declare function acceptingBoolean(a: boolean);
|
||||
acceptingBoolean(isA(a));
|
||||
>acceptingBoolean(isA(a)) : any
|
||||
>acceptingBoolean : (a: boolean) => any
|
||||
>isA(a) : boolean
|
||||
>isA(a) : p1 is A
|
||||
>isA : (p1: any) => p1 is A
|
||||
>a : A
|
||||
|
||||
@@ -223,8 +223,8 @@ let union2: C | B;
|
||||
let union3: boolean | B = isA(union2) || union2;
|
||||
>union3 : boolean | B
|
||||
>B : B
|
||||
>isA(union2) || union2 : boolean | B
|
||||
>isA(union2) : boolean
|
||||
>isA(union2) || union2 : p1 is A | B
|
||||
>isA(union2) : p1 is A
|
||||
>isA : (p1: any) => p1 is A
|
||||
>union2 : C | B
|
||||
>union2 : B
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS2322: Type 'string' is not assignable to type 'x is A'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(22,33): error TS2304: Cannot find name 'x'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(26,33): error TS1225: Cannot find parameter 'x'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(30,10): error TS2391: Function implementation is missing or not immediately following the declaration.
|
||||
@@ -16,6 +16,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(70,7):
|
||||
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'.
|
||||
Property 'propB' is missing in type 'C'.
|
||||
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) => p2 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'.
|
||||
@@ -25,7 +26,6 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1):
|
||||
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.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(104,25): error TS1228: A type predicate is only allowed in return type position for functions and methods.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2322: Type 'boolean' is not assignable to type 'D'.
|
||||
Property 'm1' is missing in type 'Boolean'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(105,16): error TS2409: Return type of constructor signature must be assignable to the instance type of the class
|
||||
@@ -33,6 +33,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(107,20
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(110,20): error TS1228: A type predicate is only allowed in return type position for functions and methods.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(111,16): error TS2408: Setters cannot return a value.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(116,18): error TS1228: A type predicate is only allowed in return type position for functions and methods.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(120,22): error TS1225: Cannot find parameter 'p1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(120,22): error TS1228: A type predicate is only allowed in return type position for functions and methods.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(124,20): error TS1229: A type predicate cannot reference a rest parameter.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(129,34): error TS1230: A type predicate cannot reference element 'p1' in a binding pattern.
|
||||
@@ -57,7 +58,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
|
||||
function hasANonBooleanReturnStatement(x): x is A {
|
||||
return '';
|
||||
~~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'x is A'.
|
||||
}
|
||||
|
||||
function hasTypeGuardTypeInsideTypeGuardType(x): x is x is A {
|
||||
@@ -149,6 +150,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
|
||||
!!! 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'.
|
||||
!!! error TS2345: Property 'propB' is missing in type 'C'.
|
||||
|
||||
// Boolean not assignable to type guard
|
||||
var assign1: (p1, p2) => p1 is A;
|
||||
@@ -193,8 +195,6 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
|
||||
// Non-compatiable type predicate positions for signature declarations
|
||||
class D {
|
||||
constructor(p1: A): p1 is C {
|
||||
~~~~~~~
|
||||
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
|
||||
return true;
|
||||
~~~~
|
||||
!!! error TS2322: Type 'boolean' is not assignable to type 'D'.
|
||||
@@ -224,6 +224,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39
|
||||
|
||||
interface I2 {
|
||||
[index: number]: p1 is C;
|
||||
~~
|
||||
!!! error TS1225: Cannot find parameter 'p1'.
|
||||
~~~~~~~
|
||||
!!! error TS1228: A type predicate is only allowed in return type position for functions and methods.
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ let test1: boolean = funA(isB);
|
||||
>isB : (p1: any) => p1 is B
|
||||
|
||||
if (funB(retC, a)) {
|
||||
>funB(retC, a) : boolean
|
||||
>funB(retC, a) : p2 is C
|
||||
>funB : <T>(p1: (p1: any) => T, p2: any) => p2 is T
|
||||
>retC : (x: any) => C
|
||||
>a : A
|
||||
@@ -118,7 +118,7 @@ let test2: B = funC(isB);
|
||||
>isB : (p1: any) => p1 is B
|
||||
|
||||
if (funD(isC, a)) {
|
||||
>funD(isC, a) : boolean
|
||||
>funD(isC, a) : p2 is C
|
||||
>funD : <T>(p1: (p1: any) => p1 is T, p2: any) => p2 is T
|
||||
>isC : (p1: any) => p1 is C
|
||||
>a : A
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
//// [typeGuardFunctionOfFormThis.ts]
|
||||
class RoyalGuard {
|
||||
isLeader(): this is LeadGuard {
|
||||
return this instanceof LeadGuard;
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
return this instanceof FollowerGuard;
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
lead(): void {};
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
follow(): void {};
|
||||
}
|
||||
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
if (a.isLeader()) {
|
||||
a.lead();
|
||||
}
|
||||
else if (a.isFollower()) {
|
||||
a.follow();
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
|
||||
let b: GuardInterface;
|
||||
if (b.isLeader()) {
|
||||
b.lead();
|
||||
}
|
||||
else if (b.isFollower()) {
|
||||
b.follow();
|
||||
}
|
||||
|
||||
if (((a.isLeader)())) {
|
||||
a.lead();
|
||||
}
|
||||
else if (((a).isFollower())) {
|
||||
a.follow();
|
||||
}
|
||||
|
||||
if (((a["isLeader"])())) {
|
||||
a.lead();
|
||||
}
|
||||
else if (((a)["isFollower"]())) {
|
||||
a.follow();
|
||||
}
|
||||
|
||||
var holder2 = {a};
|
||||
|
||||
if (holder2.a.isLeader()) {
|
||||
holder2.a;
|
||||
}
|
||||
else {
|
||||
holder2.a;
|
||||
}
|
||||
|
||||
class ArrowGuard {
|
||||
isElite = (): this is ArrowElite => {
|
||||
return this instanceof ArrowElite;
|
||||
}
|
||||
isMedic = (): this is ArrowMedic => {
|
||||
return this instanceof ArrowMedic;
|
||||
}
|
||||
}
|
||||
|
||||
class ArrowElite extends ArrowGuard {
|
||||
defend(): void {}
|
||||
}
|
||||
|
||||
class ArrowMedic extends ArrowGuard {
|
||||
heal(): void {}
|
||||
}
|
||||
|
||||
let guard = new ArrowGuard();
|
||||
if (guard.isElite()) {
|
||||
guard.defend();
|
||||
}
|
||||
else if (guard.isMedic()) {
|
||||
guard.heal();
|
||||
}
|
||||
|
||||
interface Supplies {
|
||||
spoiled: boolean;
|
||||
}
|
||||
|
||||
interface Sundries {
|
||||
broken: boolean;
|
||||
}
|
||||
|
||||
interface Crate<T> {
|
||||
contents: T;
|
||||
volume: number;
|
||||
isSupplies(): this is Crate<Supplies>;
|
||||
isSundries(): this is Crate<Sundries>;
|
||||
}
|
||||
|
||||
let crate: Crate<{}>;
|
||||
|
||||
if (crate.isSundries()) {
|
||||
crate.contents.broken = true;
|
||||
}
|
||||
else if (crate.isSupplies()) {
|
||||
crate.contents.spoiled = true;
|
||||
}
|
||||
|
||||
// Matching guards should be assignable
|
||||
|
||||
a.isFollower = b.isFollower;
|
||||
a.isLeader = b.isLeader;
|
||||
|
||||
class MimicGuard {
|
||||
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
|
||||
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
|
||||
}
|
||||
|
||||
class MimicLeader extends MimicGuard {
|
||||
lead(): void {}
|
||||
}
|
||||
|
||||
class MimicFollower extends MimicGuard {
|
||||
follow(): void {}
|
||||
}
|
||||
|
||||
let mimic = new MimicGuard();
|
||||
|
||||
a.isLeader = mimic.isLeader;
|
||||
a.isFollower = mimic.isFollower;
|
||||
|
||||
if (mimic.isFollower()) {
|
||||
mimic.follow();
|
||||
mimic.isFollower = a.isFollower;
|
||||
}
|
||||
|
||||
|
||||
interface MimicGuardInterface {
|
||||
isLeader(): this is LeadGuard;
|
||||
isFollower(): this is FollowerGuard;
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardFunctionOfFormThis.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var RoyalGuard = (function () {
|
||||
function RoyalGuard() {
|
||||
}
|
||||
RoyalGuard.prototype.isLeader = function () {
|
||||
return this instanceof LeadGuard;
|
||||
};
|
||||
RoyalGuard.prototype.isFollower = function () {
|
||||
return this instanceof FollowerGuard;
|
||||
};
|
||||
return RoyalGuard;
|
||||
}());
|
||||
var LeadGuard = (function (_super) {
|
||||
__extends(LeadGuard, _super);
|
||||
function LeadGuard() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
LeadGuard.prototype.lead = function () { };
|
||||
;
|
||||
return LeadGuard;
|
||||
}(RoyalGuard));
|
||||
var FollowerGuard = (function (_super) {
|
||||
__extends(FollowerGuard, _super);
|
||||
function FollowerGuard() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
FollowerGuard.prototype.follow = function () { };
|
||||
;
|
||||
return FollowerGuard;
|
||||
}(RoyalGuard));
|
||||
var a = new FollowerGuard();
|
||||
if (a.isLeader()) {
|
||||
a.lead();
|
||||
}
|
||||
else if (a.isFollower()) {
|
||||
a.follow();
|
||||
}
|
||||
var b;
|
||||
if (b.isLeader()) {
|
||||
b.lead();
|
||||
}
|
||||
else if (b.isFollower()) {
|
||||
b.follow();
|
||||
}
|
||||
if (((a.isLeader)())) {
|
||||
a.lead();
|
||||
}
|
||||
else if (((a).isFollower())) {
|
||||
a.follow();
|
||||
}
|
||||
if (((a["isLeader"])())) {
|
||||
a.lead();
|
||||
}
|
||||
else if (((a)["isFollower"]())) {
|
||||
a.follow();
|
||||
}
|
||||
var holder2 = { a: a };
|
||||
if (holder2.a.isLeader()) {
|
||||
holder2.a;
|
||||
}
|
||||
else {
|
||||
holder2.a;
|
||||
}
|
||||
var ArrowGuard = (function () {
|
||||
function ArrowGuard() {
|
||||
var _this = this;
|
||||
this.isElite = function () {
|
||||
return _this instanceof ArrowElite;
|
||||
};
|
||||
this.isMedic = function () {
|
||||
return _this instanceof ArrowMedic;
|
||||
};
|
||||
}
|
||||
return ArrowGuard;
|
||||
}());
|
||||
var ArrowElite = (function (_super) {
|
||||
__extends(ArrowElite, _super);
|
||||
function ArrowElite() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
ArrowElite.prototype.defend = function () { };
|
||||
return ArrowElite;
|
||||
}(ArrowGuard));
|
||||
var ArrowMedic = (function (_super) {
|
||||
__extends(ArrowMedic, _super);
|
||||
function ArrowMedic() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
ArrowMedic.prototype.heal = function () { };
|
||||
return ArrowMedic;
|
||||
}(ArrowGuard));
|
||||
var guard = new ArrowGuard();
|
||||
if (guard.isElite()) {
|
||||
guard.defend();
|
||||
}
|
||||
else if (guard.isMedic()) {
|
||||
guard.heal();
|
||||
}
|
||||
var crate;
|
||||
if (crate.isSundries()) {
|
||||
crate.contents.broken = true;
|
||||
}
|
||||
else if (crate.isSupplies()) {
|
||||
crate.contents.spoiled = true;
|
||||
}
|
||||
// Matching guards should be assignable
|
||||
a.isFollower = b.isFollower;
|
||||
a.isLeader = b.isLeader;
|
||||
var MimicGuard = (function () {
|
||||
function MimicGuard() {
|
||||
}
|
||||
MimicGuard.prototype.isLeader = function () { return this instanceof MimicLeader; };
|
||||
;
|
||||
MimicGuard.prototype.isFollower = function () { return this instanceof MimicFollower; };
|
||||
;
|
||||
return MimicGuard;
|
||||
}());
|
||||
var MimicLeader = (function (_super) {
|
||||
__extends(MimicLeader, _super);
|
||||
function MimicLeader() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
MimicLeader.prototype.lead = function () { };
|
||||
return MimicLeader;
|
||||
}(MimicGuard));
|
||||
var MimicFollower = (function (_super) {
|
||||
__extends(MimicFollower, _super);
|
||||
function MimicFollower() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
MimicFollower.prototype.follow = function () { };
|
||||
return MimicFollower;
|
||||
}(MimicGuard));
|
||||
var mimic = new MimicGuard();
|
||||
a.isLeader = mimic.isLeader;
|
||||
a.isFollower = mimic.isFollower;
|
||||
if (mimic.isFollower()) {
|
||||
mimic.follow();
|
||||
mimic.isFollower = a.isFollower;
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardFunctionOfFormThis.d.ts]
|
||||
declare class RoyalGuard {
|
||||
isLeader(): this is LeadGuard;
|
||||
isFollower(): this is FollowerGuard;
|
||||
}
|
||||
declare class LeadGuard extends RoyalGuard {
|
||||
lead(): void;
|
||||
}
|
||||
declare class FollowerGuard extends RoyalGuard {
|
||||
follow(): void;
|
||||
}
|
||||
declare let a: RoyalGuard;
|
||||
interface GuardInterface extends RoyalGuard {
|
||||
}
|
||||
declare let b: GuardInterface;
|
||||
declare var holder2: {
|
||||
a: RoyalGuard;
|
||||
};
|
||||
declare class ArrowGuard {
|
||||
isElite: () => this is ArrowElite;
|
||||
isMedic: () => this is ArrowMedic;
|
||||
}
|
||||
declare class ArrowElite extends ArrowGuard {
|
||||
defend(): void;
|
||||
}
|
||||
declare class ArrowMedic extends ArrowGuard {
|
||||
heal(): void;
|
||||
}
|
||||
declare let guard: ArrowGuard;
|
||||
interface Supplies {
|
||||
spoiled: boolean;
|
||||
}
|
||||
interface Sundries {
|
||||
broken: boolean;
|
||||
}
|
||||
interface Crate<T> {
|
||||
contents: T;
|
||||
volume: number;
|
||||
isSupplies(): this is Crate<Supplies>;
|
||||
isSundries(): this is Crate<Sundries>;
|
||||
}
|
||||
declare let crate: Crate<{}>;
|
||||
declare class MimicGuard {
|
||||
isLeader(): this is MimicLeader;
|
||||
isFollower(): this is MimicFollower;
|
||||
}
|
||||
declare class MimicLeader extends MimicGuard {
|
||||
lead(): void;
|
||||
}
|
||||
declare class MimicFollower extends MimicGuard {
|
||||
follow(): void;
|
||||
}
|
||||
declare let mimic: MimicGuard;
|
||||
interface MimicGuardInterface {
|
||||
isLeader(): this is LeadGuard;
|
||||
isFollower(): this is FollowerGuard;
|
||||
}
|
||||
@@ -0,0 +1,385 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThis.ts ===
|
||||
class RoyalGuard {
|
||||
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
|
||||
isLeader(): this is LeadGuard {
|
||||
>isLeader : Symbol(isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
|
||||
|
||||
return this instanceof LeadGuard;
|
||||
>this : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
>isFollower : Symbol(isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
|
||||
|
||||
return this instanceof FollowerGuard;
|
||||
>this : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
|
||||
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
|
||||
lead(): void {};
|
||||
>lead : Symbol(lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
|
||||
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
|
||||
follow(): void {};
|
||||
>follow : Symbol(follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
}
|
||||
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
|
||||
|
||||
if (a.isLeader()) {
|
||||
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
|
||||
a.lead();
|
||||
>a.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
}
|
||||
else if (a.isFollower()) {
|
||||
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
|
||||
a.follow();
|
||||
>a.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
>GuardInterface : Symbol(GuardInterface, Decl(typeGuardFunctionOfFormThis.ts, 23, 1))
|
||||
>RoyalGuard : Symbol(RoyalGuard, Decl(typeGuardFunctionOfFormThis.ts, 0, 0))
|
||||
|
||||
let b: GuardInterface;
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>GuardInterface : Symbol(GuardInterface, Decl(typeGuardFunctionOfFormThis.ts, 23, 1))
|
||||
|
||||
if (b.isLeader()) {
|
||||
>b.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
|
||||
b.lead();
|
||||
>b.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
}
|
||||
else if (b.isFollower()) {
|
||||
>b.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
|
||||
b.follow();
|
||||
>b.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
}
|
||||
|
||||
if (((a.isLeader)())) {
|
||||
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
|
||||
a.lead();
|
||||
>a.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
}
|
||||
else if (((a).isFollower())) {
|
||||
>(a).isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
|
||||
a.follow();
|
||||
>a.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
}
|
||||
|
||||
if (((a["isLeader"])())) {
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>"isLeader" : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
|
||||
a.lead();
|
||||
>a.lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>lead : Symbol(LeadGuard.lead, Decl(typeGuardFunctionOfFormThis.ts, 9, 36))
|
||||
}
|
||||
else if (((a)["isFollower"]())) {
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>"isFollower" : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
|
||||
a.follow();
|
||||
>a.follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>follow : Symbol(FollowerGuard.follow, Decl(typeGuardFunctionOfFormThis.ts, 13, 40))
|
||||
}
|
||||
|
||||
var holder2 = {a};
|
||||
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
|
||||
if (holder2.a.isLeader()) {
|
||||
>holder2.a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>holder2.a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
|
||||
holder2.a;
|
||||
>holder2.a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
}
|
||||
else {
|
||||
holder2.a;
|
||||
>holder2.a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
>holder2 : Symbol(holder2, Decl(typeGuardFunctionOfFormThis.ts, 49, 3))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 49, 15))
|
||||
}
|
||||
|
||||
class ArrowGuard {
|
||||
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
|
||||
|
||||
isElite = (): this is ArrowElite => {
|
||||
>isElite : Symbol(isElite, Decl(typeGuardFunctionOfFormThis.ts, 58, 18))
|
||||
>ArrowElite : Symbol(ArrowElite, Decl(typeGuardFunctionOfFormThis.ts, 65, 1))
|
||||
|
||||
return this instanceof ArrowElite;
|
||||
>this : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
|
||||
>ArrowElite : Symbol(ArrowElite, Decl(typeGuardFunctionOfFormThis.ts, 65, 1))
|
||||
}
|
||||
isMedic = (): this is ArrowMedic => {
|
||||
>isMedic : Symbol(isMedic, Decl(typeGuardFunctionOfFormThis.ts, 61, 5))
|
||||
>ArrowMedic : Symbol(ArrowMedic, Decl(typeGuardFunctionOfFormThis.ts, 69, 1))
|
||||
|
||||
return this instanceof ArrowMedic;
|
||||
>this : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
|
||||
>ArrowMedic : Symbol(ArrowMedic, Decl(typeGuardFunctionOfFormThis.ts, 69, 1))
|
||||
}
|
||||
}
|
||||
|
||||
class ArrowElite extends ArrowGuard {
|
||||
>ArrowElite : Symbol(ArrowElite, Decl(typeGuardFunctionOfFormThis.ts, 65, 1))
|
||||
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
|
||||
|
||||
defend(): void {}
|
||||
>defend : Symbol(defend, Decl(typeGuardFunctionOfFormThis.ts, 67, 37))
|
||||
}
|
||||
|
||||
class ArrowMedic extends ArrowGuard {
|
||||
>ArrowMedic : Symbol(ArrowMedic, Decl(typeGuardFunctionOfFormThis.ts, 69, 1))
|
||||
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
|
||||
|
||||
heal(): void {}
|
||||
>heal : Symbol(heal, Decl(typeGuardFunctionOfFormThis.ts, 71, 37))
|
||||
}
|
||||
|
||||
let guard = new ArrowGuard();
|
||||
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
|
||||
>ArrowGuard : Symbol(ArrowGuard, Decl(typeGuardFunctionOfFormThis.ts, 56, 1))
|
||||
|
||||
if (guard.isElite()) {
|
||||
>guard.isElite : Symbol(ArrowGuard.isElite, Decl(typeGuardFunctionOfFormThis.ts, 58, 18))
|
||||
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
|
||||
>isElite : Symbol(ArrowGuard.isElite, Decl(typeGuardFunctionOfFormThis.ts, 58, 18))
|
||||
|
||||
guard.defend();
|
||||
>guard.defend : Symbol(ArrowElite.defend, Decl(typeGuardFunctionOfFormThis.ts, 67, 37))
|
||||
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
|
||||
>defend : Symbol(ArrowElite.defend, Decl(typeGuardFunctionOfFormThis.ts, 67, 37))
|
||||
}
|
||||
else if (guard.isMedic()) {
|
||||
>guard.isMedic : Symbol(ArrowGuard.isMedic, Decl(typeGuardFunctionOfFormThis.ts, 61, 5))
|
||||
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
|
||||
>isMedic : Symbol(ArrowGuard.isMedic, Decl(typeGuardFunctionOfFormThis.ts, 61, 5))
|
||||
|
||||
guard.heal();
|
||||
>guard.heal : Symbol(ArrowMedic.heal, Decl(typeGuardFunctionOfFormThis.ts, 71, 37))
|
||||
>guard : Symbol(guard, Decl(typeGuardFunctionOfFormThis.ts, 75, 3))
|
||||
>heal : Symbol(ArrowMedic.heal, Decl(typeGuardFunctionOfFormThis.ts, 71, 37))
|
||||
}
|
||||
|
||||
interface Supplies {
|
||||
>Supplies : Symbol(Supplies, Decl(typeGuardFunctionOfFormThis.ts, 81, 1))
|
||||
|
||||
spoiled: boolean;
|
||||
>spoiled : Symbol(spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20))
|
||||
}
|
||||
|
||||
interface Sundries {
|
||||
>Sundries : Symbol(Sundries, Decl(typeGuardFunctionOfFormThis.ts, 85, 1))
|
||||
|
||||
broken: boolean;
|
||||
>broken : Symbol(broken, Decl(typeGuardFunctionOfFormThis.ts, 87, 20))
|
||||
}
|
||||
|
||||
interface Crate<T> {
|
||||
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
|
||||
>T : Symbol(T, Decl(typeGuardFunctionOfFormThis.ts, 91, 16))
|
||||
|
||||
contents: T;
|
||||
>contents : Symbol(contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
|
||||
>T : Symbol(T, Decl(typeGuardFunctionOfFormThis.ts, 91, 16))
|
||||
|
||||
volume: number;
|
||||
>volume : Symbol(volume, Decl(typeGuardFunctionOfFormThis.ts, 92, 16))
|
||||
|
||||
isSupplies(): this is Crate<Supplies>;
|
||||
>isSupplies : Symbol(isSupplies, Decl(typeGuardFunctionOfFormThis.ts, 93, 19))
|
||||
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
|
||||
>Supplies : Symbol(Supplies, Decl(typeGuardFunctionOfFormThis.ts, 81, 1))
|
||||
|
||||
isSundries(): this is Crate<Sundries>;
|
||||
>isSundries : Symbol(isSundries, Decl(typeGuardFunctionOfFormThis.ts, 94, 42))
|
||||
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
|
||||
>Sundries : Symbol(Sundries, Decl(typeGuardFunctionOfFormThis.ts, 85, 1))
|
||||
}
|
||||
|
||||
let crate: Crate<{}>;
|
||||
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
|
||||
>Crate : Symbol(Crate, Decl(typeGuardFunctionOfFormThis.ts, 89, 1))
|
||||
|
||||
if (crate.isSundries()) {
|
||||
>crate.isSundries : Symbol(Crate.isSundries, Decl(typeGuardFunctionOfFormThis.ts, 94, 42))
|
||||
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
|
||||
>isSundries : Symbol(Crate.isSundries, Decl(typeGuardFunctionOfFormThis.ts, 94, 42))
|
||||
|
||||
crate.contents.broken = true;
|
||||
>crate.contents.broken : Symbol(Sundries.broken, Decl(typeGuardFunctionOfFormThis.ts, 87, 20))
|
||||
>crate.contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
|
||||
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
|
||||
>contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
|
||||
>broken : Symbol(Sundries.broken, Decl(typeGuardFunctionOfFormThis.ts, 87, 20))
|
||||
}
|
||||
else if (crate.isSupplies()) {
|
||||
>crate.isSupplies : Symbol(Crate.isSupplies, Decl(typeGuardFunctionOfFormThis.ts, 93, 19))
|
||||
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
|
||||
>isSupplies : Symbol(Crate.isSupplies, Decl(typeGuardFunctionOfFormThis.ts, 93, 19))
|
||||
|
||||
crate.contents.spoiled = true;
|
||||
>crate.contents.spoiled : Symbol(Supplies.spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20))
|
||||
>crate.contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
|
||||
>crate : Symbol(crate, Decl(typeGuardFunctionOfFormThis.ts, 98, 3))
|
||||
>contents : Symbol(Crate.contents, Decl(typeGuardFunctionOfFormThis.ts, 91, 20))
|
||||
>spoiled : Symbol(Supplies.spoiled, Decl(typeGuardFunctionOfFormThis.ts, 83, 20))
|
||||
}
|
||||
|
||||
// Matching guards should be assignable
|
||||
|
||||
a.isFollower = b.isFollower;
|
||||
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>b.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
|
||||
a.isLeader = b.isLeader;
|
||||
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>b.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>b : Symbol(b, Decl(typeGuardFunctionOfFormThis.ts, 27, 3))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
|
||||
class MimicGuard {
|
||||
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
|
||||
|
||||
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
|
||||
>isLeader : Symbol(isLeader, Decl(typeGuardFunctionOfFormThis.ts, 112, 18))
|
||||
>MimicLeader : Symbol(MimicLeader, Decl(typeGuardFunctionOfFormThis.ts, 115, 1))
|
||||
>this : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
|
||||
>MimicLeader : Symbol(MimicLeader, Decl(typeGuardFunctionOfFormThis.ts, 115, 1))
|
||||
|
||||
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
|
||||
>isFollower : Symbol(isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
>MimicFollower : Symbol(MimicFollower, Decl(typeGuardFunctionOfFormThis.ts, 119, 1))
|
||||
>this : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
|
||||
>MimicFollower : Symbol(MimicFollower, Decl(typeGuardFunctionOfFormThis.ts, 119, 1))
|
||||
}
|
||||
|
||||
class MimicLeader extends MimicGuard {
|
||||
>MimicLeader : Symbol(MimicLeader, Decl(typeGuardFunctionOfFormThis.ts, 115, 1))
|
||||
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
|
||||
|
||||
lead(): void {}
|
||||
>lead : Symbol(lead, Decl(typeGuardFunctionOfFormThis.ts, 117, 38))
|
||||
}
|
||||
|
||||
class MimicFollower extends MimicGuard {
|
||||
>MimicFollower : Symbol(MimicFollower, Decl(typeGuardFunctionOfFormThis.ts, 119, 1))
|
||||
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
|
||||
|
||||
follow(): void {}
|
||||
>follow : Symbol(follow, Decl(typeGuardFunctionOfFormThis.ts, 121, 40))
|
||||
}
|
||||
|
||||
let mimic = new MimicGuard();
|
||||
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
|
||||
>MimicGuard : Symbol(MimicGuard, Decl(typeGuardFunctionOfFormThis.ts, 110, 24))
|
||||
|
||||
a.isLeader = mimic.isLeader;
|
||||
>a.isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isLeader : Symbol(RoyalGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 0, 18))
|
||||
>mimic.isLeader : Symbol(MimicGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 112, 18))
|
||||
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
|
||||
>isLeader : Symbol(MimicGuard.isLeader, Decl(typeGuardFunctionOfFormThis.ts, 112, 18))
|
||||
|
||||
a.isFollower = mimic.isFollower;
|
||||
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>mimic.isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
|
||||
>isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
|
||||
if (mimic.isFollower()) {
|
||||
>mimic.isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
|
||||
>isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
|
||||
mimic.follow();
|
||||
>mimic.follow : Symbol(MimicFollower.follow, Decl(typeGuardFunctionOfFormThis.ts, 121, 40))
|
||||
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
|
||||
>follow : Symbol(MimicFollower.follow, Decl(typeGuardFunctionOfFormThis.ts, 121, 40))
|
||||
|
||||
mimic.isFollower = a.isFollower;
|
||||
>mimic.isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
>mimic : Symbol(mimic, Decl(typeGuardFunctionOfFormThis.ts, 125, 3))
|
||||
>isFollower : Symbol(MimicGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 113, 76))
|
||||
>a.isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
|
||||
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
|
||||
}
|
||||
|
||||
|
||||
interface MimicGuardInterface {
|
||||
>MimicGuardInterface : Symbol(MimicGuardInterface, Decl(typeGuardFunctionOfFormThis.ts, 133, 1))
|
||||
|
||||
isLeader(): this is LeadGuard;
|
||||
>isLeader : Symbol(isLeader, Decl(typeGuardFunctionOfFormThis.ts, 136, 31))
|
||||
>LeadGuard : Symbol(LeadGuard, Decl(typeGuardFunctionOfFormThis.ts, 7, 1))
|
||||
|
||||
isFollower(): this is FollowerGuard;
|
||||
>isFollower : Symbol(isFollower, Decl(typeGuardFunctionOfFormThis.ts, 137, 34))
|
||||
>FollowerGuard : Symbol(FollowerGuard, Decl(typeGuardFunctionOfFormThis.ts, 11, 1))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,441 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThis.ts ===
|
||||
class RoyalGuard {
|
||||
>RoyalGuard : RoyalGuard
|
||||
|
||||
isLeader(): this is LeadGuard {
|
||||
>isLeader : () => this is LeadGuard
|
||||
>LeadGuard : LeadGuard
|
||||
|
||||
return this instanceof LeadGuard;
|
||||
>this instanceof LeadGuard : boolean
|
||||
>this : this
|
||||
>LeadGuard : typeof LeadGuard
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
>isFollower : () => this is FollowerGuard
|
||||
>FollowerGuard : FollowerGuard
|
||||
|
||||
return this instanceof FollowerGuard;
|
||||
>this instanceof FollowerGuard : boolean
|
||||
>this : this
|
||||
>FollowerGuard : typeof FollowerGuard
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
>LeadGuard : LeadGuard
|
||||
>RoyalGuard : RoyalGuard
|
||||
|
||||
lead(): void {};
|
||||
>lead : () => void
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
>FollowerGuard : FollowerGuard
|
||||
>RoyalGuard : RoyalGuard
|
||||
|
||||
follow(): void {};
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
>a : RoyalGuard
|
||||
>RoyalGuard : RoyalGuard
|
||||
>new FollowerGuard() : FollowerGuard
|
||||
>FollowerGuard : typeof FollowerGuard
|
||||
|
||||
if (a.isLeader()) {
|
||||
>a.isLeader() : this is LeadGuard
|
||||
>a.isLeader : () => this is LeadGuard
|
||||
>a : RoyalGuard
|
||||
>isLeader : () => this is LeadGuard
|
||||
|
||||
a.lead();
|
||||
>a.lead() : void
|
||||
>a.lead : () => void
|
||||
>a : LeadGuard
|
||||
>lead : () => void
|
||||
}
|
||||
else if (a.isFollower()) {
|
||||
>a.isFollower() : this is FollowerGuard
|
||||
>a.isFollower : () => this is FollowerGuard
|
||||
>a : RoyalGuard
|
||||
>isFollower : () => this is FollowerGuard
|
||||
|
||||
a.follow();
|
||||
>a.follow() : void
|
||||
>a.follow : () => void
|
||||
>a : FollowerGuard
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
>GuardInterface : GuardInterface
|
||||
>RoyalGuard : RoyalGuard
|
||||
|
||||
let b: GuardInterface;
|
||||
>b : GuardInterface
|
||||
>GuardInterface : GuardInterface
|
||||
|
||||
if (b.isLeader()) {
|
||||
>b.isLeader() : this is LeadGuard
|
||||
>b.isLeader : () => this is LeadGuard
|
||||
>b : GuardInterface
|
||||
>isLeader : () => this is LeadGuard
|
||||
|
||||
b.lead();
|
||||
>b.lead() : void
|
||||
>b.lead : () => void
|
||||
>b : LeadGuard
|
||||
>lead : () => void
|
||||
}
|
||||
else if (b.isFollower()) {
|
||||
>b.isFollower() : this is FollowerGuard
|
||||
>b.isFollower : () => this is FollowerGuard
|
||||
>b : GuardInterface
|
||||
>isFollower : () => this is FollowerGuard
|
||||
|
||||
b.follow();
|
||||
>b.follow() : void
|
||||
>b.follow : () => void
|
||||
>b : FollowerGuard
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
if (((a.isLeader)())) {
|
||||
>((a.isLeader)()) : this is LeadGuard
|
||||
>(a.isLeader)() : this is LeadGuard
|
||||
>(a.isLeader) : () => this is LeadGuard
|
||||
>a.isLeader : () => this is LeadGuard
|
||||
>a : RoyalGuard
|
||||
>isLeader : () => this is LeadGuard
|
||||
|
||||
a.lead();
|
||||
>a.lead() : void
|
||||
>a.lead : () => void
|
||||
>a : LeadGuard
|
||||
>lead : () => void
|
||||
}
|
||||
else if (((a).isFollower())) {
|
||||
>((a).isFollower()) : this is FollowerGuard
|
||||
>(a).isFollower() : this is FollowerGuard
|
||||
>(a).isFollower : () => this is FollowerGuard
|
||||
>(a) : RoyalGuard
|
||||
>a : RoyalGuard
|
||||
>isFollower : () => this is FollowerGuard
|
||||
|
||||
a.follow();
|
||||
>a.follow() : void
|
||||
>a.follow : () => void
|
||||
>a : FollowerGuard
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
if (((a["isLeader"])())) {
|
||||
>((a["isLeader"])()) : this is LeadGuard
|
||||
>(a["isLeader"])() : this is LeadGuard
|
||||
>(a["isLeader"]) : () => this is LeadGuard
|
||||
>a["isLeader"] : () => this is LeadGuard
|
||||
>a : RoyalGuard
|
||||
>"isLeader" : string
|
||||
|
||||
a.lead();
|
||||
>a.lead() : void
|
||||
>a.lead : () => void
|
||||
>a : LeadGuard
|
||||
>lead : () => void
|
||||
}
|
||||
else if (((a)["isFollower"]())) {
|
||||
>((a)["isFollower"]()) : this is FollowerGuard
|
||||
>(a)["isFollower"]() : this is FollowerGuard
|
||||
>(a)["isFollower"] : () => this is FollowerGuard
|
||||
>(a) : RoyalGuard
|
||||
>a : RoyalGuard
|
||||
>"isFollower" : string
|
||||
|
||||
a.follow();
|
||||
>a.follow() : void
|
||||
>a.follow : () => void
|
||||
>a : FollowerGuard
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
var holder2 = {a};
|
||||
>holder2 : { a: RoyalGuard; }
|
||||
>{a} : { a: RoyalGuard; }
|
||||
>a : RoyalGuard
|
||||
|
||||
if (holder2.a.isLeader()) {
|
||||
>holder2.a.isLeader() : this is LeadGuard
|
||||
>holder2.a.isLeader : () => this is LeadGuard
|
||||
>holder2.a : RoyalGuard
|
||||
>holder2 : { a: RoyalGuard; }
|
||||
>a : RoyalGuard
|
||||
>isLeader : () => this is LeadGuard
|
||||
|
||||
holder2.a;
|
||||
>holder2.a : RoyalGuard
|
||||
>holder2 : { a: RoyalGuard; }
|
||||
>a : RoyalGuard
|
||||
}
|
||||
else {
|
||||
holder2.a;
|
||||
>holder2.a : RoyalGuard
|
||||
>holder2 : { a: RoyalGuard; }
|
||||
>a : RoyalGuard
|
||||
}
|
||||
|
||||
class ArrowGuard {
|
||||
>ArrowGuard : ArrowGuard
|
||||
|
||||
isElite = (): this is ArrowElite => {
|
||||
>isElite : () => this is ArrowElite
|
||||
>(): this is ArrowElite => { return this instanceof ArrowElite; } : () => this is ArrowElite
|
||||
>ArrowElite : ArrowElite
|
||||
|
||||
return this instanceof ArrowElite;
|
||||
>this instanceof ArrowElite : boolean
|
||||
>this : this
|
||||
>ArrowElite : typeof ArrowElite
|
||||
}
|
||||
isMedic = (): this is ArrowMedic => {
|
||||
>isMedic : () => this is ArrowMedic
|
||||
>(): this is ArrowMedic => { return this instanceof ArrowMedic; } : () => this is ArrowMedic
|
||||
>ArrowMedic : ArrowMedic
|
||||
|
||||
return this instanceof ArrowMedic;
|
||||
>this instanceof ArrowMedic : boolean
|
||||
>this : this
|
||||
>ArrowMedic : typeof ArrowMedic
|
||||
}
|
||||
}
|
||||
|
||||
class ArrowElite extends ArrowGuard {
|
||||
>ArrowElite : ArrowElite
|
||||
>ArrowGuard : ArrowGuard
|
||||
|
||||
defend(): void {}
|
||||
>defend : () => void
|
||||
}
|
||||
|
||||
class ArrowMedic extends ArrowGuard {
|
||||
>ArrowMedic : ArrowMedic
|
||||
>ArrowGuard : ArrowGuard
|
||||
|
||||
heal(): void {}
|
||||
>heal : () => void
|
||||
}
|
||||
|
||||
let guard = new ArrowGuard();
|
||||
>guard : ArrowGuard
|
||||
>new ArrowGuard() : ArrowGuard
|
||||
>ArrowGuard : typeof ArrowGuard
|
||||
|
||||
if (guard.isElite()) {
|
||||
>guard.isElite() : this is ArrowElite
|
||||
>guard.isElite : () => this is ArrowElite
|
||||
>guard : ArrowGuard
|
||||
>isElite : () => this is ArrowElite
|
||||
|
||||
guard.defend();
|
||||
>guard.defend() : void
|
||||
>guard.defend : () => void
|
||||
>guard : ArrowElite
|
||||
>defend : () => void
|
||||
}
|
||||
else if (guard.isMedic()) {
|
||||
>guard.isMedic() : this is ArrowMedic
|
||||
>guard.isMedic : () => this is ArrowMedic
|
||||
>guard : ArrowGuard
|
||||
>isMedic : () => this is ArrowMedic
|
||||
|
||||
guard.heal();
|
||||
>guard.heal() : void
|
||||
>guard.heal : () => void
|
||||
>guard : ArrowMedic
|
||||
>heal : () => void
|
||||
}
|
||||
|
||||
interface Supplies {
|
||||
>Supplies : Supplies
|
||||
|
||||
spoiled: boolean;
|
||||
>spoiled : boolean
|
||||
}
|
||||
|
||||
interface Sundries {
|
||||
>Sundries : Sundries
|
||||
|
||||
broken: boolean;
|
||||
>broken : boolean
|
||||
}
|
||||
|
||||
interface Crate<T> {
|
||||
>Crate : Crate<T>
|
||||
>T : T
|
||||
|
||||
contents: T;
|
||||
>contents : T
|
||||
>T : T
|
||||
|
||||
volume: number;
|
||||
>volume : number
|
||||
|
||||
isSupplies(): this is Crate<Supplies>;
|
||||
>isSupplies : () => this is Crate<Supplies>
|
||||
>Crate : Crate<T>
|
||||
>Supplies : Supplies
|
||||
|
||||
isSundries(): this is Crate<Sundries>;
|
||||
>isSundries : () => this is Crate<Sundries>
|
||||
>Crate : Crate<T>
|
||||
>Sundries : Sundries
|
||||
}
|
||||
|
||||
let crate: Crate<{}>;
|
||||
>crate : Crate<{}>
|
||||
>Crate : Crate<T>
|
||||
|
||||
if (crate.isSundries()) {
|
||||
>crate.isSundries() : this is Crate<Sundries>
|
||||
>crate.isSundries : () => this is Crate<Sundries>
|
||||
>crate : Crate<{}>
|
||||
>isSundries : () => this is Crate<Sundries>
|
||||
|
||||
crate.contents.broken = true;
|
||||
>crate.contents.broken = true : boolean
|
||||
>crate.contents.broken : boolean
|
||||
>crate.contents : Sundries
|
||||
>crate : Crate<Sundries>
|
||||
>contents : Sundries
|
||||
>broken : boolean
|
||||
>true : boolean
|
||||
}
|
||||
else if (crate.isSupplies()) {
|
||||
>crate.isSupplies() : this is Crate<Supplies>
|
||||
>crate.isSupplies : () => this is Crate<Supplies>
|
||||
>crate : Crate<{}>
|
||||
>isSupplies : () => this is Crate<Supplies>
|
||||
|
||||
crate.contents.spoiled = true;
|
||||
>crate.contents.spoiled = true : boolean
|
||||
>crate.contents.spoiled : boolean
|
||||
>crate.contents : Supplies
|
||||
>crate : Crate<Supplies>
|
||||
>contents : Supplies
|
||||
>spoiled : boolean
|
||||
>true : boolean
|
||||
}
|
||||
|
||||
// Matching guards should be assignable
|
||||
|
||||
a.isFollower = b.isFollower;
|
||||
>a.isFollower = b.isFollower : () => this is FollowerGuard
|
||||
>a.isFollower : () => this is FollowerGuard
|
||||
>a : RoyalGuard
|
||||
>isFollower : () => this is FollowerGuard
|
||||
>b.isFollower : () => this is FollowerGuard
|
||||
>b : GuardInterface
|
||||
>isFollower : () => this is FollowerGuard
|
||||
|
||||
a.isLeader = b.isLeader;
|
||||
>a.isLeader = b.isLeader : () => this is LeadGuard
|
||||
>a.isLeader : () => this is LeadGuard
|
||||
>a : RoyalGuard
|
||||
>isLeader : () => this is LeadGuard
|
||||
>b.isLeader : () => this is LeadGuard
|
||||
>b : GuardInterface
|
||||
>isLeader : () => this is LeadGuard
|
||||
|
||||
class MimicGuard {
|
||||
>MimicGuard : MimicGuard
|
||||
|
||||
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
|
||||
>isLeader : () => this is MimicLeader
|
||||
>MimicLeader : MimicLeader
|
||||
>this instanceof MimicLeader : boolean
|
||||
>this : this
|
||||
>MimicLeader : typeof MimicLeader
|
||||
|
||||
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
|
||||
>isFollower : () => this is MimicFollower
|
||||
>MimicFollower : MimicFollower
|
||||
>this instanceof MimicFollower : boolean
|
||||
>this : this
|
||||
>MimicFollower : typeof MimicFollower
|
||||
}
|
||||
|
||||
class MimicLeader extends MimicGuard {
|
||||
>MimicLeader : MimicLeader
|
||||
>MimicGuard : MimicGuard
|
||||
|
||||
lead(): void {}
|
||||
>lead : () => void
|
||||
}
|
||||
|
||||
class MimicFollower extends MimicGuard {
|
||||
>MimicFollower : MimicFollower
|
||||
>MimicGuard : MimicGuard
|
||||
|
||||
follow(): void {}
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
let mimic = new MimicGuard();
|
||||
>mimic : MimicGuard
|
||||
>new MimicGuard() : MimicGuard
|
||||
>MimicGuard : typeof MimicGuard
|
||||
|
||||
a.isLeader = mimic.isLeader;
|
||||
>a.isLeader = mimic.isLeader : () => this is MimicLeader
|
||||
>a.isLeader : () => this is LeadGuard
|
||||
>a : RoyalGuard
|
||||
>isLeader : () => this is LeadGuard
|
||||
>mimic.isLeader : () => this is MimicLeader
|
||||
>mimic : MimicGuard
|
||||
>isLeader : () => this is MimicLeader
|
||||
|
||||
a.isFollower = mimic.isFollower;
|
||||
>a.isFollower = mimic.isFollower : () => this is MimicFollower
|
||||
>a.isFollower : () => this is FollowerGuard
|
||||
>a : RoyalGuard
|
||||
>isFollower : () => this is FollowerGuard
|
||||
>mimic.isFollower : () => this is MimicFollower
|
||||
>mimic : MimicGuard
|
||||
>isFollower : () => this is MimicFollower
|
||||
|
||||
if (mimic.isFollower()) {
|
||||
>mimic.isFollower() : this is MimicFollower
|
||||
>mimic.isFollower : () => this is MimicFollower
|
||||
>mimic : MimicGuard
|
||||
>isFollower : () => this is MimicFollower
|
||||
|
||||
mimic.follow();
|
||||
>mimic.follow() : void
|
||||
>mimic.follow : () => void
|
||||
>mimic : MimicFollower
|
||||
>follow : () => void
|
||||
|
||||
mimic.isFollower = a.isFollower;
|
||||
>mimic.isFollower = a.isFollower : () => this is FollowerGuard
|
||||
>mimic.isFollower : () => this is MimicFollower
|
||||
>mimic : MimicFollower
|
||||
>isFollower : () => this is MimicFollower
|
||||
>a.isFollower : () => this is FollowerGuard
|
||||
>a : RoyalGuard
|
||||
>isFollower : () => this is FollowerGuard
|
||||
}
|
||||
|
||||
|
||||
interface MimicGuardInterface {
|
||||
>MimicGuardInterface : MimicGuardInterface
|
||||
|
||||
isLeader(): this is LeadGuard;
|
||||
>isLeader : () => this is LeadGuard
|
||||
>LeadGuard : LeadGuard
|
||||
|
||||
isFollower(): this is FollowerGuard;
|
||||
>isFollower : () => this is FollowerGuard
|
||||
>FollowerGuard : FollowerGuard
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(23,1): error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
|
||||
Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
|
||||
Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
|
||||
Property 'follow' is missing in type 'LeadGuard'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(24,1): error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
|
||||
Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
|
||||
Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
|
||||
Property 'lead' is missing in type 'FollowerGuard'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(26,1): error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
|
||||
Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
|
||||
Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(27,1): error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
|
||||
Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
|
||||
Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(29,32): error TS2526: A 'this' type is available only in a non-static member of a class or interface.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(55,7): error TS2339: Property 'follow' does not exist on type 'RoyalGuard'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(58,7): error TS2339: Property 'lead' does not exist on type 'RoyalGuard'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts (7 errors) ====
|
||||
class RoyalGuard {
|
||||
isLeader(): this is LeadGuard {
|
||||
return this instanceof LeadGuard;
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
return this instanceof FollowerGuard;
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
lead(): void {};
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
follow(): void {};
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
let b: GuardInterface = new LeadGuard();
|
||||
|
||||
// Mismatched guards shouldn't be assignable
|
||||
b.isFollower = b.isLeader;
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
|
||||
!!! error TS2322: Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
|
||||
!!! error TS2322: Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
|
||||
!!! error TS2322: Property 'follow' is missing in type 'LeadGuard'.
|
||||
b.isLeader = b.isFollower;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
|
||||
!!! error TS2322: Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
|
||||
!!! error TS2322: Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
|
||||
!!! error TS2322: Property 'lead' is missing in type 'FollowerGuard'.
|
||||
|
||||
a.isFollower = a.isLeader;
|
||||
~~~~~~~~~~~~
|
||||
!!! error TS2322: Type '() => this is LeadGuard' is not assignable to type '() => this is FollowerGuard'.
|
||||
!!! error TS2322: Type predicate 'this is LeadGuard' is not assignable to 'this is FollowerGuard'.
|
||||
!!! error TS2322: Type 'LeadGuard' is not assignable to type 'FollowerGuard'.
|
||||
a.isLeader = a.isFollower;
|
||||
~~~~~~~~~~
|
||||
!!! error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => this is LeadGuard'.
|
||||
!!! error TS2322: Type predicate 'this is FollowerGuard' is not assignable to 'this is LeadGuard'.
|
||||
!!! error TS2322: Type 'FollowerGuard' is not assignable to type 'LeadGuard'.
|
||||
|
||||
function invalidGuard(c: any): this is number {
|
||||
~~~~
|
||||
!!! error TS2526: A 'this' type is available only in a non-static member of a class or interface.
|
||||
return false;
|
||||
}
|
||||
|
||||
let c: number | number[];
|
||||
if (invalidGuard(c)) {
|
||||
c;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
}
|
||||
|
||||
let holder = {invalidGuard};
|
||||
|
||||
if (holder.invalidGuard(c)) {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
|
||||
let detached = a.isFollower;
|
||||
|
||||
if (detached()) {
|
||||
a.follow();
|
||||
~~~~~~
|
||||
!!! error TS2339: Property 'follow' does not exist on type 'RoyalGuard'.
|
||||
}
|
||||
else {
|
||||
a.lead();
|
||||
~~~~
|
||||
!!! error TS2339: Property 'lead' does not exist on type 'RoyalGuard'.
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
//// [typeGuardFunctionOfFormThisErrors.ts]
|
||||
class RoyalGuard {
|
||||
isLeader(): this is LeadGuard {
|
||||
return this instanceof LeadGuard;
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
return this instanceof FollowerGuard;
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
lead(): void {};
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
follow(): void {};
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
let b: GuardInterface = new LeadGuard();
|
||||
|
||||
// Mismatched guards shouldn't be assignable
|
||||
b.isFollower = b.isLeader;
|
||||
b.isLeader = b.isFollower;
|
||||
|
||||
a.isFollower = a.isLeader;
|
||||
a.isLeader = a.isFollower;
|
||||
|
||||
function invalidGuard(c: any): this is number {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c: number | number[];
|
||||
if (invalidGuard(c)) {
|
||||
c;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
}
|
||||
|
||||
let holder = {invalidGuard};
|
||||
|
||||
if (holder.invalidGuard(c)) {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
|
||||
let detached = a.isFollower;
|
||||
|
||||
if (detached()) {
|
||||
a.follow();
|
||||
}
|
||||
else {
|
||||
a.lead();
|
||||
}
|
||||
|
||||
//// [typeGuardFunctionOfFormThisErrors.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
var RoyalGuard = (function () {
|
||||
function RoyalGuard() {
|
||||
}
|
||||
RoyalGuard.prototype.isLeader = function () {
|
||||
return this instanceof LeadGuard;
|
||||
};
|
||||
RoyalGuard.prototype.isFollower = function () {
|
||||
return this instanceof FollowerGuard;
|
||||
};
|
||||
return RoyalGuard;
|
||||
}());
|
||||
var LeadGuard = (function (_super) {
|
||||
__extends(LeadGuard, _super);
|
||||
function LeadGuard() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
LeadGuard.prototype.lead = function () { };
|
||||
;
|
||||
return LeadGuard;
|
||||
}(RoyalGuard));
|
||||
var FollowerGuard = (function (_super) {
|
||||
__extends(FollowerGuard, _super);
|
||||
function FollowerGuard() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
FollowerGuard.prototype.follow = function () { };
|
||||
;
|
||||
return FollowerGuard;
|
||||
}(RoyalGuard));
|
||||
var a = new FollowerGuard();
|
||||
var b = new LeadGuard();
|
||||
// Mismatched guards shouldn't be assignable
|
||||
b.isFollower = b.isLeader;
|
||||
b.isLeader = b.isFollower;
|
||||
a.isFollower = a.isLeader;
|
||||
a.isLeader = a.isFollower;
|
||||
function invalidGuard(c) {
|
||||
return false;
|
||||
}
|
||||
var c;
|
||||
if (invalidGuard(c)) {
|
||||
c;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
}
|
||||
var holder = { invalidGuard: invalidGuard };
|
||||
if (holder.invalidGuard(c)) {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
var detached = a.isFollower;
|
||||
if (detached()) {
|
||||
a.follow();
|
||||
}
|
||||
else {
|
||||
a.lead();
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardFunctionOfFormThisErrors.d.ts]
|
||||
declare class RoyalGuard {
|
||||
isLeader(): this is LeadGuard;
|
||||
isFollower(): this is FollowerGuard;
|
||||
}
|
||||
declare class LeadGuard extends RoyalGuard {
|
||||
lead(): void;
|
||||
}
|
||||
declare class FollowerGuard extends RoyalGuard {
|
||||
follow(): void;
|
||||
}
|
||||
interface GuardInterface extends RoyalGuard {
|
||||
}
|
||||
declare let a: RoyalGuard;
|
||||
declare let b: GuardInterface;
|
||||
declare function invalidGuard(c: any): this is number;
|
||||
declare let c: number | number[];
|
||||
declare let holder: {
|
||||
invalidGuard: (c: any) => this is number;
|
||||
};
|
||||
declare let detached: () => this is FollowerGuard;
|
||||
@@ -67,7 +67,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1
|
||||
>str = isC1(c1Orc2) && c1Orc2.p1 : string
|
||||
>str : string
|
||||
>isC1(c1Orc2) && c1Orc2.p1 : string
|
||||
>isC1(c1Orc2) : boolean
|
||||
>isC1(c1Orc2) : x is C1
|
||||
>isC1 : (x: any) => x is C1
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p1 : string
|
||||
@@ -78,7 +78,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2
|
||||
>num = isC2(c1Orc2) && c1Orc2.p2 : number
|
||||
>num : number
|
||||
>isC2(c1Orc2) && c1Orc2.p2 : number
|
||||
>isC2(c1Orc2) : boolean
|
||||
>isC2(c1Orc2) : x is C2
|
||||
>isC2 : (x: any) => x is C2
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p2 : number
|
||||
@@ -89,7 +89,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1
|
||||
>str = isD1(c1Orc2) && c1Orc2.p1 : string
|
||||
>str : string
|
||||
>isD1(c1Orc2) && c1Orc2.p1 : string
|
||||
>isD1(c1Orc2) : boolean
|
||||
>isD1(c1Orc2) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p1 : string
|
||||
@@ -100,7 +100,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1
|
||||
>num = isD1(c1Orc2) && c1Orc2.p3 : number
|
||||
>num : number
|
||||
>isD1(c1Orc2) && c1Orc2.p3 : number
|
||||
>isD1(c1Orc2) : boolean
|
||||
>isD1(c1Orc2) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p3 : number
|
||||
@@ -116,7 +116,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2
|
||||
>num = isC2(c2Ord1) && c2Ord1.p2 : number
|
||||
>num : number
|
||||
>isC2(c2Ord1) && c2Ord1.p2 : number
|
||||
>isC2(c2Ord1) : boolean
|
||||
>isC2(c2Ord1) : x is C2
|
||||
>isC2 : (x: any) => x is C2
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1.p2 : number
|
||||
@@ -127,7 +127,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1
|
||||
>num = isD1(c2Ord1) && c2Ord1.p3 : number
|
||||
>num : number
|
||||
>isD1(c2Ord1) && c2Ord1.p3 : number
|
||||
>isD1(c2Ord1) : boolean
|
||||
>isD1(c2Ord1) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1.p3 : number
|
||||
@@ -138,7 +138,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1
|
||||
>str = isD1(c2Ord1) && c2Ord1.p1 : string
|
||||
>str : string
|
||||
>isD1(c2Ord1) && c2Ord1.p1 : string
|
||||
>isD1(c2Ord1) : boolean
|
||||
>isD1(c2Ord1) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1.p1 : string
|
||||
@@ -150,7 +150,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1
|
||||
>C2 : C2
|
||||
>D1 : D1
|
||||
>isC1(c2Ord1) && c2Ord1 : D1
|
||||
>isC1(c2Ord1) : boolean
|
||||
>isC1(c2Ord1) : x is C1
|
||||
>isC1 : (x: any) => x is C1
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1 : D1
|
||||
|
||||
@@ -98,7 +98,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1
|
||||
>str = isC1(c1Orc2) && c1Orc2.p1 : string
|
||||
>str : string
|
||||
>isC1(c1Orc2) && c1Orc2.p1 : string
|
||||
>isC1(c1Orc2) : boolean
|
||||
>isC1(c1Orc2) : x is C1
|
||||
>isC1 : (x: any) => x is C1
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p1 : string
|
||||
@@ -109,7 +109,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2
|
||||
>num = isC2(c1Orc2) && c1Orc2.p2 : number
|
||||
>num : number
|
||||
>isC2(c1Orc2) && c1Orc2.p2 : number
|
||||
>isC2(c1Orc2) : boolean
|
||||
>isC2(c1Orc2) : x is C2
|
||||
>isC2 : (x: any) => x is C2
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p2 : number
|
||||
@@ -120,7 +120,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1
|
||||
>str = isD1(c1Orc2) && c1Orc2.p1 : string
|
||||
>str : string
|
||||
>isD1(c1Orc2) && c1Orc2.p1 : string
|
||||
>isD1(c1Orc2) : boolean
|
||||
>isD1(c1Orc2) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p1 : string
|
||||
@@ -131,7 +131,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1
|
||||
>num = isD1(c1Orc2) && c1Orc2.p3 : number
|
||||
>num : number
|
||||
>isD1(c1Orc2) && c1Orc2.p3 : number
|
||||
>isD1(c1Orc2) : boolean
|
||||
>isD1(c1Orc2) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c1Orc2 : C1 | C2
|
||||
>c1Orc2.p3 : number
|
||||
@@ -147,7 +147,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2
|
||||
>num = isC2(c2Ord1) && c2Ord1.p2 : number
|
||||
>num : number
|
||||
>isC2(c2Ord1) && c2Ord1.p2 : number
|
||||
>isC2(c2Ord1) : boolean
|
||||
>isC2(c2Ord1) : x is C2
|
||||
>isC2 : (x: any) => x is C2
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1.p2 : number
|
||||
@@ -158,7 +158,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1
|
||||
>num = isD1(c2Ord1) && c2Ord1.p3 : number
|
||||
>num : number
|
||||
>isD1(c2Ord1) && c2Ord1.p3 : number
|
||||
>isD1(c2Ord1) : boolean
|
||||
>isD1(c2Ord1) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1.p3 : number
|
||||
@@ -169,7 +169,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1
|
||||
>str = isD1(c2Ord1) && c2Ord1.p1 : string
|
||||
>str : string
|
||||
>isD1(c2Ord1) && c2Ord1.p1 : string
|
||||
>isD1(c2Ord1) : boolean
|
||||
>isD1(c2Ord1) : x is D1
|
||||
>isD1 : (x: any) => x is D1
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1.p1 : string
|
||||
@@ -181,7 +181,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1
|
||||
>C2 : C2
|
||||
>D1 : D1
|
||||
>isC1(c2Ord1) && c2Ord1 : D1
|
||||
>isC1(c2Ord1) : boolean
|
||||
>isC1(c2Ord1) : x is C1
|
||||
>isC1 : (x: any) => x is C1
|
||||
>c2Ord1 : C2 | D1
|
||||
>c2Ord1 : D1
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
//// [typeGuardOfFormThisMember.ts]
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
export class FileSystemObject {
|
||||
isFSO: this is FileSystemObject;
|
||||
get isFile(): this is File {
|
||||
return this instanceof File;
|
||||
}
|
||||
set isFile(param) {
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
return this instanceof Directory;
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(public path: string) {}
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
export interface Networked {
|
||||
host: string;
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = false;
|
||||
file.isFSO = file.isFile;
|
||||
file.isFile = true;
|
||||
let x = file.isFile;
|
||||
if (file.isFile) {
|
||||
file.content;
|
||||
if (file.isNetworked) {
|
||||
file.host;
|
||||
file.content;
|
||||
}
|
||||
}
|
||||
else if (file.isDirectory) {
|
||||
file.children;
|
||||
}
|
||||
else if (file.isNetworked) {
|
||||
file.host;
|
||||
}
|
||||
|
||||
interface GenericLeadGuard<T> extends GenericGuard<T> {
|
||||
lead(): void;
|
||||
}
|
||||
|
||||
interface GenericFollowerGuard<T> extends GenericGuard<T> {
|
||||
follow(): void;
|
||||
}
|
||||
|
||||
interface GenericGuard<T> {
|
||||
target: T;
|
||||
isLeader: this is (GenericLeadGuard<T>);
|
||||
isFollower: this is GenericFollowerGuard<T>;
|
||||
}
|
||||
|
||||
let guard: GenericGuard<File>;
|
||||
if (guard.isLeader) {
|
||||
guard.lead();
|
||||
}
|
||||
else if (guard.isFollower) {
|
||||
guard.follow();
|
||||
}
|
||||
|
||||
interface SpecificGuard {
|
||||
isMoreSpecific: this is MoreSpecificGuard;
|
||||
}
|
||||
|
||||
interface MoreSpecificGuard extends SpecificGuard {
|
||||
do(): void;
|
||||
}
|
||||
|
||||
let general: SpecificGuard;
|
||||
if (general.isMoreSpecific) {
|
||||
general.do();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [typeGuardOfFormThisMember.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
var Test;
|
||||
(function (Test) {
|
||||
var FileSystemObject = (function () {
|
||||
function FileSystemObject(path) {
|
||||
this.path = path;
|
||||
}
|
||||
Object.defineProperty(FileSystemObject.prototype, "isFile", {
|
||||
get: function () {
|
||||
return this instanceof File;
|
||||
},
|
||||
set: function (param) {
|
||||
// noop
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(FileSystemObject.prototype, "isDirectory", {
|
||||
get: function () {
|
||||
return this instanceof Directory;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return FileSystemObject;
|
||||
}());
|
||||
Test.FileSystemObject = FileSystemObject;
|
||||
var File = (function (_super) {
|
||||
__extends(File, _super);
|
||||
function File(path, content) {
|
||||
_super.call(this, path);
|
||||
this.content = content;
|
||||
}
|
||||
return File;
|
||||
}(FileSystemObject));
|
||||
Test.File = File;
|
||||
var Directory = (function (_super) {
|
||||
__extends(Directory, _super);
|
||||
function Directory() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return Directory;
|
||||
}(FileSystemObject));
|
||||
Test.Directory = Directory;
|
||||
var file = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = false;
|
||||
file.isFSO = file.isFile;
|
||||
file.isFile = true;
|
||||
var x = file.isFile;
|
||||
if (file.isFile) {
|
||||
file.content;
|
||||
if (file.isNetworked) {
|
||||
file.host;
|
||||
file.content;
|
||||
}
|
||||
}
|
||||
else if (file.isDirectory) {
|
||||
file.children;
|
||||
}
|
||||
else if (file.isNetworked) {
|
||||
file.host;
|
||||
}
|
||||
var guard;
|
||||
if (guard.isLeader) {
|
||||
guard.lead();
|
||||
}
|
||||
else if (guard.isFollower) {
|
||||
guard.follow();
|
||||
}
|
||||
var general;
|
||||
if (general.isMoreSpecific) {
|
||||
general.do();
|
||||
}
|
||||
})(Test || (Test = {}));
|
||||
|
||||
|
||||
//// [typeGuardOfFormThisMember.d.ts]
|
||||
declare namespace Test {
|
||||
class FileSystemObject {
|
||||
path: string;
|
||||
isFSO: this is FileSystemObject;
|
||||
isFile: this is File;
|
||||
isDirectory: this is Directory;
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(path: string);
|
||||
}
|
||||
class File extends FileSystemObject {
|
||||
content: string;
|
||||
constructor(path: string, content: string);
|
||||
}
|
||||
class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
interface Networked {
|
||||
host: string;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMember.ts ===
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
>Test : Symbol(Test, Decl(typeGuardOfFormThisMember.ts, 0, 0))
|
||||
|
||||
export class FileSystemObject {
|
||||
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
|
||||
isFSO: this is FileSystemObject;
|
||||
>isFSO : Symbol(isFSO, Decl(typeGuardOfFormThisMember.ts, 2, 32))
|
||||
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
|
||||
get isFile(): this is File {
|
||||
>isFile : Symbol(isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
|
||||
|
||||
return this instanceof File;
|
||||
>this : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
|
||||
}
|
||||
set isFile(param) {
|
||||
>isFile : Symbol(isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
>param : Symbol(param, Decl(typeGuardOfFormThisMember.ts, 7, 13))
|
||||
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
>isDirectory : Symbol(isDirectory, Decl(typeGuardOfFormThisMember.ts, 9, 3))
|
||||
>Directory : Symbol(Directory, Decl(typeGuardOfFormThisMember.ts, 19, 2))
|
||||
|
||||
return this instanceof Directory;
|
||||
>this : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
>Directory : Symbol(Directory, Decl(typeGuardOfFormThisMember.ts, 19, 2))
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
>isNetworked : Symbol(isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
>Networked : Symbol(Networked, Decl(typeGuardOfFormThisMember.ts, 22, 2))
|
||||
|
||||
constructor(public path: string) {}
|
||||
>path : Symbol(path, Decl(typeGuardOfFormThisMember.ts, 14, 14))
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
|
||||
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
>path : Symbol(path, Decl(typeGuardOfFormThisMember.ts, 18, 14))
|
||||
>content : Symbol(content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
|
||||
>super : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
>path : Symbol(path, Decl(typeGuardOfFormThisMember.ts, 18, 14))
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
>Directory : Symbol(Directory, Decl(typeGuardOfFormThisMember.ts, 19, 2))
|
||||
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
|
||||
children: FileSystemObject[];
|
||||
>children : Symbol(children, Decl(typeGuardOfFormThisMember.ts, 20, 50))
|
||||
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
}
|
||||
export interface Networked {
|
||||
>Networked : Symbol(Networked, Decl(typeGuardOfFormThisMember.ts, 22, 2))
|
||||
|
||||
host: string;
|
||||
>host : Symbol(host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>FileSystemObject : Symbol(FileSystemObject, Decl(typeGuardOfFormThisMember.ts, 1, 16))
|
||||
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
|
||||
|
||||
file.isNetworked = false;
|
||||
>file.isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
|
||||
file.isFSO = file.isFile;
|
||||
>file.isFSO : Symbol(FileSystemObject.isFSO, Decl(typeGuardOfFormThisMember.ts, 2, 32))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isFSO : Symbol(FileSystemObject.isFSO, Decl(typeGuardOfFormThisMember.ts, 2, 32))
|
||||
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
|
||||
file.isFile = true;
|
||||
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
|
||||
let x = file.isFile;
|
||||
>x : Symbol(x, Decl(typeGuardOfFormThisMember.ts, 31, 4))
|
||||
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
|
||||
if (file.isFile) {
|
||||
>file.isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isFile : Symbol(FileSystemObject.isFile, Decl(typeGuardOfFormThisMember.ts, 3, 34), Decl(typeGuardOfFormThisMember.ts, 6, 3))
|
||||
|
||||
file.content;
|
||||
>file.content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
|
||||
|
||||
if (file.isNetworked) {
|
||||
>file.isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
|
||||
file.host;
|
||||
>file.host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
|
||||
|
||||
file.content;
|
||||
>file.content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>content : Symbol(File.content, Decl(typeGuardOfFormThisMember.ts, 18, 27))
|
||||
}
|
||||
}
|
||||
else if (file.isDirectory) {
|
||||
>file.isDirectory : Symbol(FileSystemObject.isDirectory, Decl(typeGuardOfFormThisMember.ts, 9, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isDirectory : Symbol(FileSystemObject.isDirectory, Decl(typeGuardOfFormThisMember.ts, 9, 3))
|
||||
|
||||
file.children;
|
||||
>file.children : Symbol(Directory.children, Decl(typeGuardOfFormThisMember.ts, 20, 50))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>children : Symbol(Directory.children, Decl(typeGuardOfFormThisMember.ts, 20, 50))
|
||||
}
|
||||
else if (file.isNetworked) {
|
||||
>file.isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>isNetworked : Symbol(FileSystemObject.isNetworked, Decl(typeGuardOfFormThisMember.ts, 12, 3))
|
||||
|
||||
file.host;
|
||||
>file.host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
|
||||
>file : Symbol(file, Decl(typeGuardOfFormThisMember.ts, 27, 4))
|
||||
>host : Symbol(Networked.host, Decl(typeGuardOfFormThisMember.ts, 23, 29))
|
||||
}
|
||||
|
||||
interface GenericLeadGuard<T> extends GenericGuard<T> {
|
||||
>GenericLeadGuard : Symbol(GenericLeadGuard, Decl(typeGuardOfFormThisMember.ts, 44, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 46, 28))
|
||||
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 46, 28))
|
||||
|
||||
lead(): void;
|
||||
>lead : Symbol(lead, Decl(typeGuardOfFormThisMember.ts, 46, 56))
|
||||
}
|
||||
|
||||
interface GenericFollowerGuard<T> extends GenericGuard<T> {
|
||||
>GenericFollowerGuard : Symbol(GenericFollowerGuard, Decl(typeGuardOfFormThisMember.ts, 48, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 50, 32))
|
||||
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 50, 32))
|
||||
|
||||
follow(): void;
|
||||
>follow : Symbol(follow, Decl(typeGuardOfFormThisMember.ts, 50, 60))
|
||||
}
|
||||
|
||||
interface GenericGuard<T> {
|
||||
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
|
||||
|
||||
target: T;
|
||||
>target : Symbol(target, Decl(typeGuardOfFormThisMember.ts, 54, 28))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
|
||||
|
||||
isLeader: this is (GenericLeadGuard<T>);
|
||||
>isLeader : Symbol(isLeader, Decl(typeGuardOfFormThisMember.ts, 55, 12))
|
||||
>GenericLeadGuard : Symbol(GenericLeadGuard, Decl(typeGuardOfFormThisMember.ts, 44, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
|
||||
|
||||
isFollower: this is GenericFollowerGuard<T>;
|
||||
>isFollower : Symbol(isFollower, Decl(typeGuardOfFormThisMember.ts, 56, 42))
|
||||
>GenericFollowerGuard : Symbol(GenericFollowerGuard, Decl(typeGuardOfFormThisMember.ts, 48, 2))
|
||||
>T : Symbol(T, Decl(typeGuardOfFormThisMember.ts, 54, 24))
|
||||
}
|
||||
|
||||
let guard: GenericGuard<File>;
|
||||
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
|
||||
>GenericGuard : Symbol(GenericGuard, Decl(typeGuardOfFormThisMember.ts, 52, 2))
|
||||
>File : Symbol(File, Decl(typeGuardOfFormThisMember.ts, 15, 2))
|
||||
|
||||
if (guard.isLeader) {
|
||||
>guard.isLeader : Symbol(GenericGuard.isLeader, Decl(typeGuardOfFormThisMember.ts, 55, 12))
|
||||
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
|
||||
>isLeader : Symbol(GenericGuard.isLeader, Decl(typeGuardOfFormThisMember.ts, 55, 12))
|
||||
|
||||
guard.lead();
|
||||
>guard.lead : Symbol(GenericLeadGuard.lead, Decl(typeGuardOfFormThisMember.ts, 46, 56))
|
||||
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
|
||||
>lead : Symbol(GenericLeadGuard.lead, Decl(typeGuardOfFormThisMember.ts, 46, 56))
|
||||
}
|
||||
else if (guard.isFollower) {
|
||||
>guard.isFollower : Symbol(GenericGuard.isFollower, Decl(typeGuardOfFormThisMember.ts, 56, 42))
|
||||
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
|
||||
>isFollower : Symbol(GenericGuard.isFollower, Decl(typeGuardOfFormThisMember.ts, 56, 42))
|
||||
|
||||
guard.follow();
|
||||
>guard.follow : Symbol(GenericFollowerGuard.follow, Decl(typeGuardOfFormThisMember.ts, 50, 60))
|
||||
>guard : Symbol(guard, Decl(typeGuardOfFormThisMember.ts, 60, 4))
|
||||
>follow : Symbol(GenericFollowerGuard.follow, Decl(typeGuardOfFormThisMember.ts, 50, 60))
|
||||
}
|
||||
|
||||
interface SpecificGuard {
|
||||
>SpecificGuard : Symbol(SpecificGuard, Decl(typeGuardOfFormThisMember.ts, 66, 2))
|
||||
|
||||
isMoreSpecific: this is MoreSpecificGuard;
|
||||
>isMoreSpecific : Symbol(isMoreSpecific, Decl(typeGuardOfFormThisMember.ts, 68, 26))
|
||||
>MoreSpecificGuard : Symbol(MoreSpecificGuard, Decl(typeGuardOfFormThisMember.ts, 70, 2))
|
||||
}
|
||||
|
||||
interface MoreSpecificGuard extends SpecificGuard {
|
||||
>MoreSpecificGuard : Symbol(MoreSpecificGuard, Decl(typeGuardOfFormThisMember.ts, 70, 2))
|
||||
>SpecificGuard : Symbol(SpecificGuard, Decl(typeGuardOfFormThisMember.ts, 66, 2))
|
||||
|
||||
do(): void;
|
||||
>do : Symbol(do, Decl(typeGuardOfFormThisMember.ts, 72, 52))
|
||||
}
|
||||
|
||||
let general: SpecificGuard;
|
||||
>general : Symbol(general, Decl(typeGuardOfFormThisMember.ts, 76, 4))
|
||||
>SpecificGuard : Symbol(SpecificGuard, Decl(typeGuardOfFormThisMember.ts, 66, 2))
|
||||
|
||||
if (general.isMoreSpecific) {
|
||||
>general.isMoreSpecific : Symbol(SpecificGuard.isMoreSpecific, Decl(typeGuardOfFormThisMember.ts, 68, 26))
|
||||
>general : Symbol(general, Decl(typeGuardOfFormThisMember.ts, 76, 4))
|
||||
>isMoreSpecific : Symbol(SpecificGuard.isMoreSpecific, Decl(typeGuardOfFormThisMember.ts, 68, 26))
|
||||
|
||||
general.do();
|
||||
>general.do : Symbol(MoreSpecificGuard.do, Decl(typeGuardOfFormThisMember.ts, 72, 52))
|
||||
>general : Symbol(general, Decl(typeGuardOfFormThisMember.ts, 76, 4))
|
||||
>do : Symbol(MoreSpecificGuard.do, Decl(typeGuardOfFormThisMember.ts, 72, 52))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMember.ts ===
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
>Test : typeof Test
|
||||
|
||||
export class FileSystemObject {
|
||||
>FileSystemObject : FileSystemObject
|
||||
|
||||
isFSO: this is FileSystemObject;
|
||||
>isFSO : this is FileSystemObject
|
||||
>FileSystemObject : FileSystemObject
|
||||
|
||||
get isFile(): this is File {
|
||||
>isFile : this is File
|
||||
>File : File
|
||||
|
||||
return this instanceof File;
|
||||
>this instanceof File : boolean
|
||||
>this : this
|
||||
>File : typeof File
|
||||
}
|
||||
set isFile(param) {
|
||||
>isFile : this is File
|
||||
>param : boolean
|
||||
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
>isDirectory : this is Directory
|
||||
>Directory : Directory
|
||||
|
||||
return this instanceof Directory;
|
||||
>this instanceof Directory : boolean
|
||||
>this : this
|
||||
>Directory : typeof Directory
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
>isNetworked : this is Networked & this
|
||||
>Networked : Networked
|
||||
|
||||
constructor(public path: string) {}
|
||||
>path : string
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
>File : File
|
||||
>FileSystemObject : FileSystemObject
|
||||
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
>path : string
|
||||
>content : string
|
||||
>super(path) : void
|
||||
>super : typeof FileSystemObject
|
||||
>path : string
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
>Directory : Directory
|
||||
>FileSystemObject : FileSystemObject
|
||||
|
||||
children: FileSystemObject[];
|
||||
>children : FileSystemObject[]
|
||||
>FileSystemObject : FileSystemObject
|
||||
}
|
||||
export interface Networked {
|
||||
>Networked : Networked
|
||||
|
||||
host: string;
|
||||
>host : string
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
>file : FileSystemObject
|
||||
>FileSystemObject : FileSystemObject
|
||||
>new File("foo/bar.txt", "foo") : File
|
||||
>File : typeof File
|
||||
>"foo/bar.txt" : string
|
||||
>"foo" : string
|
||||
|
||||
file.isNetworked = false;
|
||||
>file.isNetworked = false : boolean
|
||||
>file.isNetworked : this is Networked & FileSystemObject
|
||||
>file : FileSystemObject
|
||||
>isNetworked : this is Networked & FileSystemObject
|
||||
>false : boolean
|
||||
|
||||
file.isFSO = file.isFile;
|
||||
>file.isFSO = file.isFile : this is File
|
||||
>file.isFSO : this is FileSystemObject
|
||||
>file : FileSystemObject
|
||||
>isFSO : this is FileSystemObject
|
||||
>file.isFile : this is File
|
||||
>file : FileSystemObject
|
||||
>isFile : this is File
|
||||
|
||||
file.isFile = true;
|
||||
>file.isFile = true : boolean
|
||||
>file.isFile : this is File
|
||||
>file : FileSystemObject
|
||||
>isFile : this is File
|
||||
>true : boolean
|
||||
|
||||
let x = file.isFile;
|
||||
>x : boolean
|
||||
>file.isFile : this is File
|
||||
>file : FileSystemObject
|
||||
>isFile : this is File
|
||||
|
||||
if (file.isFile) {
|
||||
>file.isFile : this is File
|
||||
>file : FileSystemObject
|
||||
>isFile : this is File
|
||||
|
||||
file.content;
|
||||
>file.content : string
|
||||
>file : File
|
||||
>content : string
|
||||
|
||||
if (file.isNetworked) {
|
||||
>file.isNetworked : this is Networked & File
|
||||
>file : File
|
||||
>isNetworked : this is Networked & File
|
||||
|
||||
file.host;
|
||||
>file.host : string
|
||||
>file : Networked & File
|
||||
>host : string
|
||||
|
||||
file.content;
|
||||
>file.content : string
|
||||
>file : Networked & File
|
||||
>content : string
|
||||
}
|
||||
}
|
||||
else if (file.isDirectory) {
|
||||
>file.isDirectory : this is Directory
|
||||
>file : FileSystemObject
|
||||
>isDirectory : this is Directory
|
||||
|
||||
file.children;
|
||||
>file.children : FileSystemObject[]
|
||||
>file : Directory
|
||||
>children : FileSystemObject[]
|
||||
}
|
||||
else if (file.isNetworked) {
|
||||
>file.isNetworked : this is Networked & FileSystemObject
|
||||
>file : FileSystemObject
|
||||
>isNetworked : this is Networked & FileSystemObject
|
||||
|
||||
file.host;
|
||||
>file.host : string
|
||||
>file : Networked & FileSystemObject
|
||||
>host : string
|
||||
}
|
||||
|
||||
interface GenericLeadGuard<T> extends GenericGuard<T> {
|
||||
>GenericLeadGuard : GenericLeadGuard<T>
|
||||
>T : T
|
||||
>GenericGuard : GenericGuard<T>
|
||||
>T : T
|
||||
|
||||
lead(): void;
|
||||
>lead : () => void
|
||||
}
|
||||
|
||||
interface GenericFollowerGuard<T> extends GenericGuard<T> {
|
||||
>GenericFollowerGuard : GenericFollowerGuard<T>
|
||||
>T : T
|
||||
>GenericGuard : GenericGuard<T>
|
||||
>T : T
|
||||
|
||||
follow(): void;
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
interface GenericGuard<T> {
|
||||
>GenericGuard : GenericGuard<T>
|
||||
>T : T
|
||||
|
||||
target: T;
|
||||
>target : T
|
||||
>T : T
|
||||
|
||||
isLeader: this is (GenericLeadGuard<T>);
|
||||
>isLeader : this is GenericLeadGuard<T>
|
||||
>GenericLeadGuard : GenericLeadGuard<T>
|
||||
>T : T
|
||||
|
||||
isFollower: this is GenericFollowerGuard<T>;
|
||||
>isFollower : this is GenericFollowerGuard<T>
|
||||
>GenericFollowerGuard : GenericFollowerGuard<T>
|
||||
>T : T
|
||||
}
|
||||
|
||||
let guard: GenericGuard<File>;
|
||||
>guard : GenericGuard<File>
|
||||
>GenericGuard : GenericGuard<T>
|
||||
>File : File
|
||||
|
||||
if (guard.isLeader) {
|
||||
>guard.isLeader : this is GenericLeadGuard<File>
|
||||
>guard : GenericGuard<File>
|
||||
>isLeader : this is GenericLeadGuard<File>
|
||||
|
||||
guard.lead();
|
||||
>guard.lead() : void
|
||||
>guard.lead : () => void
|
||||
>guard : GenericLeadGuard<File>
|
||||
>lead : () => void
|
||||
}
|
||||
else if (guard.isFollower) {
|
||||
>guard.isFollower : this is GenericFollowerGuard<File>
|
||||
>guard : GenericGuard<File>
|
||||
>isFollower : this is GenericFollowerGuard<File>
|
||||
|
||||
guard.follow();
|
||||
>guard.follow() : void
|
||||
>guard.follow : () => void
|
||||
>guard : GenericFollowerGuard<File>
|
||||
>follow : () => void
|
||||
}
|
||||
|
||||
interface SpecificGuard {
|
||||
>SpecificGuard : SpecificGuard
|
||||
|
||||
isMoreSpecific: this is MoreSpecificGuard;
|
||||
>isMoreSpecific : this is MoreSpecificGuard
|
||||
>MoreSpecificGuard : MoreSpecificGuard
|
||||
}
|
||||
|
||||
interface MoreSpecificGuard extends SpecificGuard {
|
||||
>MoreSpecificGuard : MoreSpecificGuard
|
||||
>SpecificGuard : SpecificGuard
|
||||
|
||||
do(): void;
|
||||
>do : () => void
|
||||
}
|
||||
|
||||
let general: SpecificGuard;
|
||||
>general : SpecificGuard
|
||||
>SpecificGuard : SpecificGuard
|
||||
|
||||
if (general.isMoreSpecific) {
|
||||
>general.isMoreSpecific : this is MoreSpecificGuard
|
||||
>general : SpecificGuard
|
||||
>isMoreSpecific : this is MoreSpecificGuard
|
||||
|
||||
general.do();
|
||||
>general.do() : void
|
||||
>general.do : () => void
|
||||
>general : MoreSpecificGuard
|
||||
>do : () => void
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMemberErrors.ts(29,2): error TS1226: Type predicate 'this is File' is not assignable to 'this is Networked & FileSystemObject'.
|
||||
Type 'File' is not assignable to type 'Networked & FileSystemObject'.
|
||||
Type 'File' is not assignable to type 'Networked'.
|
||||
Property 'host' is missing in type 'File'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMemberErrors.ts(31,2): error TS1226: Type predicate 'this is FileSystemObject' is not assignable to 'this is File'.
|
||||
Type 'FileSystemObject' is not assignable to type 'File'.
|
||||
Property 'content' is missing in type 'FileSystemObject'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormThisMemberErrors.ts (2 errors) ====
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
export class FileSystemObject {
|
||||
isFSO: this is FileSystemObject;
|
||||
get isFile(): this is File {
|
||||
return this instanceof File;
|
||||
}
|
||||
set isFile(param) {
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
return this instanceof Directory;
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(public path: string) {}
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
export interface Networked {
|
||||
host: string;
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = file.isFile;
|
||||
~~~~~~~~~~~~~~~~
|
||||
!!! error TS1226: Type predicate 'this is File' is not assignable to 'this is Networked & FileSystemObject'.
|
||||
!!! error TS1226: Type 'File' is not assignable to type 'Networked & FileSystemObject'.
|
||||
!!! error TS1226: Type 'File' is not assignable to type 'Networked'.
|
||||
!!! error TS1226: Property 'host' is missing in type 'File'.
|
||||
file.isFSO = file.isNetworked;
|
||||
file.isFile = file.isFSO;
|
||||
~~~~~~~~~~~
|
||||
!!! error TS1226: Type predicate 'this is FileSystemObject' is not assignable to 'this is File'.
|
||||
!!! error TS1226: Type 'FileSystemObject' is not assignable to type 'File'.
|
||||
!!! error TS1226: Property 'content' is missing in type 'FileSystemObject'.
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
//// [typeGuardOfFormThisMemberErrors.ts]
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
export class FileSystemObject {
|
||||
isFSO: this is FileSystemObject;
|
||||
get isFile(): this is File {
|
||||
return this instanceof File;
|
||||
}
|
||||
set isFile(param) {
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
return this instanceof Directory;
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(public path: string) {}
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
export interface Networked {
|
||||
host: string;
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = file.isFile;
|
||||
file.isFSO = file.isNetworked;
|
||||
file.isFile = file.isFSO;
|
||||
}
|
||||
|
||||
//// [typeGuardOfFormThisMemberErrors.js]
|
||||
var __extends = (this && this.__extends) || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
||||
};
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
var Test;
|
||||
(function (Test) {
|
||||
var FileSystemObject = (function () {
|
||||
function FileSystemObject(path) {
|
||||
this.path = path;
|
||||
}
|
||||
Object.defineProperty(FileSystemObject.prototype, "isFile", {
|
||||
get: function () {
|
||||
return this instanceof File;
|
||||
},
|
||||
set: function (param) {
|
||||
// noop
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
Object.defineProperty(FileSystemObject.prototype, "isDirectory", {
|
||||
get: function () {
|
||||
return this instanceof Directory;
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
return FileSystemObject;
|
||||
}());
|
||||
Test.FileSystemObject = FileSystemObject;
|
||||
var File = (function (_super) {
|
||||
__extends(File, _super);
|
||||
function File(path, content) {
|
||||
_super.call(this, path);
|
||||
this.content = content;
|
||||
}
|
||||
return File;
|
||||
}(FileSystemObject));
|
||||
Test.File = File;
|
||||
var Directory = (function (_super) {
|
||||
__extends(Directory, _super);
|
||||
function Directory() {
|
||||
_super.apply(this, arguments);
|
||||
}
|
||||
return Directory;
|
||||
}(FileSystemObject));
|
||||
Test.Directory = Directory;
|
||||
var file = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = file.isFile;
|
||||
file.isFSO = file.isNetworked;
|
||||
file.isFile = file.isFSO;
|
||||
})(Test || (Test = {}));
|
||||
|
||||
|
||||
//// [typeGuardOfFormThisMemberErrors.d.ts]
|
||||
declare namespace Test {
|
||||
class FileSystemObject {
|
||||
path: string;
|
||||
isFSO: this is FileSystemObject;
|
||||
isFile: this is File;
|
||||
isDirectory: this is Directory;
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(path: string);
|
||||
}
|
||||
class File extends FileSystemObject {
|
||||
content: string;
|
||||
constructor(path: string, content: string);
|
||||
}
|
||||
class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
interface Networked {
|
||||
host: string;
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ function foo1<a>(value: void|a): void {
|
||||
>a : a
|
||||
|
||||
if (isVoid(value)) {
|
||||
>isVoid(value) : boolean
|
||||
>isVoid(value) : value is void
|
||||
>isVoid : <a>(value: void | a) => value is void
|
||||
>value : void | a
|
||||
|
||||
@@ -130,7 +130,7 @@ function baz1<a>(value: void|a): void {
|
||||
>a : a
|
||||
|
||||
if (isNonVoid(value)) {
|
||||
>isNonVoid(value) : boolean
|
||||
>isNonVoid(value) : value is a
|
||||
>isNonVoid : <a>(value: void | a) => value is a
|
||||
>value : void | a
|
||||
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
// @declaration: true
|
||||
class RoyalGuard {
|
||||
isLeader(): this is LeadGuard {
|
||||
return this instanceof LeadGuard;
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
return this instanceof FollowerGuard;
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
lead(): void {};
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
follow(): void {};
|
||||
}
|
||||
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
if (a.isLeader()) {
|
||||
a.lead();
|
||||
}
|
||||
else if (a.isFollower()) {
|
||||
a.follow();
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
|
||||
let b: GuardInterface;
|
||||
if (b.isLeader()) {
|
||||
b.lead();
|
||||
}
|
||||
else if (b.isFollower()) {
|
||||
b.follow();
|
||||
}
|
||||
|
||||
if (((a.isLeader)())) {
|
||||
a.lead();
|
||||
}
|
||||
else if (((a).isFollower())) {
|
||||
a.follow();
|
||||
}
|
||||
|
||||
if (((a["isLeader"])())) {
|
||||
a.lead();
|
||||
}
|
||||
else if (((a)["isFollower"]())) {
|
||||
a.follow();
|
||||
}
|
||||
|
||||
var holder2 = {a};
|
||||
|
||||
if (holder2.a.isLeader()) {
|
||||
holder2.a;
|
||||
}
|
||||
else {
|
||||
holder2.a;
|
||||
}
|
||||
|
||||
class ArrowGuard {
|
||||
isElite = (): this is ArrowElite => {
|
||||
return this instanceof ArrowElite;
|
||||
}
|
||||
isMedic = (): this is ArrowMedic => {
|
||||
return this instanceof ArrowMedic;
|
||||
}
|
||||
}
|
||||
|
||||
class ArrowElite extends ArrowGuard {
|
||||
defend(): void {}
|
||||
}
|
||||
|
||||
class ArrowMedic extends ArrowGuard {
|
||||
heal(): void {}
|
||||
}
|
||||
|
||||
let guard = new ArrowGuard();
|
||||
if (guard.isElite()) {
|
||||
guard.defend();
|
||||
}
|
||||
else if (guard.isMedic()) {
|
||||
guard.heal();
|
||||
}
|
||||
|
||||
interface Supplies {
|
||||
spoiled: boolean;
|
||||
}
|
||||
|
||||
interface Sundries {
|
||||
broken: boolean;
|
||||
}
|
||||
|
||||
interface Crate<T> {
|
||||
contents: T;
|
||||
volume: number;
|
||||
isSupplies(): this is Crate<Supplies>;
|
||||
isSundries(): this is Crate<Sundries>;
|
||||
}
|
||||
|
||||
let crate: Crate<{}>;
|
||||
|
||||
if (crate.isSundries()) {
|
||||
crate.contents.broken = true;
|
||||
}
|
||||
else if (crate.isSupplies()) {
|
||||
crate.contents.spoiled = true;
|
||||
}
|
||||
|
||||
// Matching guards should be assignable
|
||||
|
||||
a.isFollower = b.isFollower;
|
||||
a.isLeader = b.isLeader;
|
||||
|
||||
class MimicGuard {
|
||||
isLeader(): this is MimicLeader { return this instanceof MimicLeader; };
|
||||
isFollower(): this is MimicFollower { return this instanceof MimicFollower; };
|
||||
}
|
||||
|
||||
class MimicLeader extends MimicGuard {
|
||||
lead(): void {}
|
||||
}
|
||||
|
||||
class MimicFollower extends MimicGuard {
|
||||
follow(): void {}
|
||||
}
|
||||
|
||||
let mimic = new MimicGuard();
|
||||
|
||||
a.isLeader = mimic.isLeader;
|
||||
a.isFollower = mimic.isFollower;
|
||||
|
||||
if (mimic.isFollower()) {
|
||||
mimic.follow();
|
||||
mimic.isFollower = a.isFollower;
|
||||
}
|
||||
|
||||
|
||||
interface MimicGuardInterface {
|
||||
isLeader(): this is LeadGuard;
|
||||
isFollower(): this is FollowerGuard;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// @declaration: true
|
||||
class RoyalGuard {
|
||||
isLeader(): this is LeadGuard {
|
||||
return this instanceof LeadGuard;
|
||||
}
|
||||
isFollower(): this is FollowerGuard {
|
||||
return this instanceof FollowerGuard;
|
||||
}
|
||||
}
|
||||
|
||||
class LeadGuard extends RoyalGuard {
|
||||
lead(): void {};
|
||||
}
|
||||
|
||||
class FollowerGuard extends RoyalGuard {
|
||||
follow(): void {};
|
||||
}
|
||||
|
||||
interface GuardInterface extends RoyalGuard {}
|
||||
let a: RoyalGuard = new FollowerGuard();
|
||||
let b: GuardInterface = new LeadGuard();
|
||||
|
||||
// Mismatched guards shouldn't be assignable
|
||||
b.isFollower = b.isLeader;
|
||||
b.isLeader = b.isFollower;
|
||||
|
||||
a.isFollower = a.isLeader;
|
||||
a.isLeader = a.isFollower;
|
||||
|
||||
function invalidGuard(c: any): this is number {
|
||||
return false;
|
||||
}
|
||||
|
||||
let c: number | number[];
|
||||
if (invalidGuard(c)) {
|
||||
c;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
}
|
||||
|
||||
let holder = {invalidGuard};
|
||||
|
||||
if (holder.invalidGuard(c)) {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
else {
|
||||
c;
|
||||
holder;
|
||||
}
|
||||
|
||||
let detached = a.isFollower;
|
||||
|
||||
if (detached()) {
|
||||
a.follow();
|
||||
}
|
||||
else {
|
||||
a.lead();
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
// @target: es5
|
||||
// @declaration: true
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
export class FileSystemObject {
|
||||
isFSO: this is FileSystemObject;
|
||||
get isFile(): this is File {
|
||||
return this instanceof File;
|
||||
}
|
||||
set isFile(param) {
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
return this instanceof Directory;
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(public path: string) {}
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
export interface Networked {
|
||||
host: string;
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = false;
|
||||
file.isFSO = file.isFile;
|
||||
file.isFile = true;
|
||||
let x = file.isFile;
|
||||
if (file.isFile) {
|
||||
file.content;
|
||||
if (file.isNetworked) {
|
||||
file.host;
|
||||
file.content;
|
||||
}
|
||||
}
|
||||
else if (file.isDirectory) {
|
||||
file.children;
|
||||
}
|
||||
else if (file.isNetworked) {
|
||||
file.host;
|
||||
}
|
||||
|
||||
interface GenericLeadGuard<T> extends GenericGuard<T> {
|
||||
lead(): void;
|
||||
}
|
||||
|
||||
interface GenericFollowerGuard<T> extends GenericGuard<T> {
|
||||
follow(): void;
|
||||
}
|
||||
|
||||
interface GenericGuard<T> {
|
||||
target: T;
|
||||
isLeader: this is (GenericLeadGuard<T>);
|
||||
isFollower: this is GenericFollowerGuard<T>;
|
||||
}
|
||||
|
||||
let guard: GenericGuard<File>;
|
||||
if (guard.isLeader) {
|
||||
guard.lead();
|
||||
}
|
||||
else if (guard.isFollower) {
|
||||
guard.follow();
|
||||
}
|
||||
|
||||
interface SpecificGuard {
|
||||
isMoreSpecific: this is MoreSpecificGuard;
|
||||
}
|
||||
|
||||
interface MoreSpecificGuard extends SpecificGuard {
|
||||
do(): void;
|
||||
}
|
||||
|
||||
let general: SpecificGuard;
|
||||
if (general.isMoreSpecific) {
|
||||
general.do();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// @target: es5
|
||||
// @declaration: true
|
||||
// There's a 'File' class in the stdlib, wrap with a namespace to avoid collision
|
||||
namespace Test {
|
||||
export class FileSystemObject {
|
||||
isFSO: this is FileSystemObject;
|
||||
get isFile(): this is File {
|
||||
return this instanceof File;
|
||||
}
|
||||
set isFile(param) {
|
||||
// noop
|
||||
}
|
||||
get isDirectory(): this is Directory {
|
||||
return this instanceof Directory;
|
||||
}
|
||||
isNetworked: this is (Networked & this);
|
||||
constructor(public path: string) {}
|
||||
}
|
||||
|
||||
export class File extends FileSystemObject {
|
||||
constructor(path: string, public content: string) { super(path); }
|
||||
}
|
||||
export class Directory extends FileSystemObject {
|
||||
children: FileSystemObject[];
|
||||
}
|
||||
export interface Networked {
|
||||
host: string;
|
||||
}
|
||||
|
||||
let file: FileSystemObject = new File("foo/bar.txt", "foo");
|
||||
file.isNetworked = file.isFile;
|
||||
file.isFSO = file.isNetworked;
|
||||
file.isFile = file.isFSO;
|
||||
}
|
||||
Reference in New Issue
Block a user