mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-13 14:09:06 -05:00
Fix narrowing, interfaces. Expose issue with generic instantiation
This commit is contained in:
@@ -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,16 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkTypePredicate(node: TypePredicateNode) {
|
||||
if (node.parameterName && node.parameterName.kind === SyntaxKind.Identifier) {
|
||||
checkStrictModeIdentifier(node.parameterName as Identifier);
|
||||
}
|
||||
if (node.parameterName && node.parameterName.kind === SyntaxKind.ThisType) {
|
||||
seenThisKeyword = true;
|
||||
}
|
||||
bind(node.type);
|
||||
}
|
||||
|
||||
function bindSourceFileIfExternalModule() {
|
||||
setExportContextFlag(file);
|
||||
if (isExternalModule(file)) {
|
||||
|
||||
@@ -2634,7 +2634,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
|
||||
@@ -4602,7 +4608,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getPredicateType(node: TypePredicateNode): Type {
|
||||
if (!(node.parent.kind === SyntaxKind.PropertyDeclaration || node.parent.kind === SyntaxKind.GetAccessor)) {
|
||||
if (!(node.parent.kind === SyntaxKind.PropertyDeclaration || node.parent.kind === SyntaxKind.PropertySignature || node.parent.kind === SyntaxKind.GetAccessor)) {
|
||||
return booleanType;
|
||||
}
|
||||
else {
|
||||
@@ -6008,6 +6014,9 @@ namespace ts {
|
||||
|
||||
function getWidenedType(type: Type): Type {
|
||||
if (type.flags & TypeFlags.RequiresWidening) {
|
||||
if (type.flags & TypeFlags.PredicateType) {
|
||||
return booleanType;
|
||||
}
|
||||
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
|
||||
return anyType;
|
||||
}
|
||||
@@ -11078,8 +11087,9 @@ namespace ts {
|
||||
}
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.GetAccessor:
|
||||
return node === (<SignatureDeclaration>node.parent).type;
|
||||
return node === (node.parent as (PropertyDeclaration | GetAccessorDeclaration | PropertySignature)).type;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -11104,12 +11114,8 @@ namespace ts {
|
||||
if (node.type.kind === SyntaxKind.TypePredicate) {
|
||||
const typePredicate = getSignatureFromDeclaration(node).typePredicate;
|
||||
const typePredicateNode = <TypePredicateNode>node.type;
|
||||
checkSourceElement(typePredicateNode);
|
||||
if (isIdentifierTypePredicate(typePredicate)) {
|
||||
if (!isInLegalTypePredicatePosition(typePredicateNode)) {
|
||||
error(typePredicateNode,
|
||||
Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
|
||||
return;
|
||||
}
|
||||
if (typePredicate.parameterIndex >= 0) {
|
||||
if (node.parameters[typePredicate.parameterIndex].dotDotDotToken) {
|
||||
error(typePredicateNode.parameterName,
|
||||
@@ -11157,15 +11163,6 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!isInLegalThisTypePredicatePosition(typePredicateNode)) {
|
||||
error(typePredicateNode,
|
||||
Diagnostics.A_this_based_type_predicate_is_only_allowed_in_class_or_interface_members_get_accessors_or_return_type_positions_for_functions_and_methods);
|
||||
return;
|
||||
}
|
||||
// Reuse this type diagnostics on the this type node to determine if a this type predicate is valid
|
||||
getTypeFromThisTypeNode(typePredicateNode.parameterName as ThisTypeNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
checkSourceElement(node.type);
|
||||
@@ -14295,8 +14292,13 @@ namespace ts {
|
||||
if (node.parameterName.kind === SyntaxKind.Identifier && !isInLegalTypePredicatePosition(node)) {
|
||||
error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
|
||||
}
|
||||
else if (node.parameterName.kind === SyntaxKind.ThisType && (!isInLegalThisTypePredicatePosition(node) || getTypeFromThisTypeNode(node.parameterName as ThisTypeNode) === unknownType)) {
|
||||
error(node, Diagnostics.A_this_based_type_predicate_is_only_allowed_in_class_or_interface_members_get_accessors_or_return_type_positions_for_functions_and_methods);
|
||||
else if (node.parameterName.kind === SyntaxKind.ThisType) {
|
||||
if (!isInLegalThisTypePredicatePosition(node)) {
|
||||
error(node, Diagnostics.A_this_based_type_predicate_is_only_allowed_in_class_or_interface_members_get_accessors_or_return_type_positions_for_functions_and_methods);
|
||||
}
|
||||
else {
|
||||
getTypeFromThisTypeNode(node.parameterName as ThisTypeNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2120,7 +2120,7 @@ namespace ts {
|
||||
UnionOrIntersection = Union | Intersection,
|
||||
StructuredType = ObjectType | Union | Intersection,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
|
||||
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral | PredicateType,
|
||||
/* @internal */
|
||||
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
|
||||
}
|
||||
|
||||
@@ -133,3 +133,9 @@ if (mimic.isFollower()) {
|
||||
mimic.follow();
|
||||
mimic.isFollower = a.isFollower;
|
||||
}
|
||||
|
||||
|
||||
interface MimicGuardInterface {
|
||||
isLeader(): this is LeadGuard;
|
||||
isFollower(): this is FollowerGuard;
|
||||
}
|
||||
|
||||
@@ -40,4 +40,64 @@ namespace Test {
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
class doThing<T> {
|
||||
constructor(private x: T) {}
|
||||
isThing(x: any): x is doThing<T> {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let z: doThing<{}> = new doThing({x: 10});
|
||||
let z1 = new doThing({x: 10});
|
||||
if (z1.isThing(z)) {
|
||||
z;
|
||||
}
|
||||
}
|
||||
|
||||
function f(g: (x: number) => void) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
f(function(x) {
|
||||
|
||||
|
||||
})
|
||||
Reference in New Issue
Block a user