feedback from pr

This commit is contained in:
Wesley Wigham
2015-12-03 13:46:37 -08:00
parent 859cc53c11
commit d7208e81d6
9 changed files with 148 additions and 20 deletions

View File

@@ -4732,12 +4732,11 @@ namespace ts {
}
function cloneTypePredicate(predicate: TypePredicate, mapper: TypeMapper): ThisTypePredicate | IdentifierTypePredicate {
if (predicate.kind === TypePredicateKind.Identifier) {
const identifierPredicate = predicate as IdentifierTypePredicate;
if (isIdentifierTypePredicate(predicate)) {
return {
kind: TypePredicateKind.Identifier,
parameterName: identifierPredicate.parameterName,
parameterIndex: identifierPredicate.parameterIndex,
parameterName: predicate.parameterName,
parameterIndex: predicate.parameterIndex,
type: instantiateType(predicate.type, mapper)
} as IdentifierTypePredicate;
}
@@ -4751,18 +4750,14 @@ namespace ts {
function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature {
let freshTypeParameters: TypeParameter[];
let freshTypePredicate: ThisTypePredicate | IdentifierTypePredicate;
if (signature.typeParameters && !eraseTypeParameters) {
freshTypeParameters = instantiateList(signature.typeParameters, mapper, instantiateTypeParameter);
mapper = combineTypeMappers(createTypeMapper(signature.typeParameters, freshTypeParameters), mapper);
}
if (signature.typePredicate) {
freshTypePredicate = cloneTypePredicate(signature.typePredicate, mapper);
}
const result = createSignature(signature.declaration, freshTypeParameters,
instantiateList(signature.parameters, mapper, instantiateSymbol),
instantiateType(signature.resolvedReturnType, mapper),
freshTypePredicate,
signature.typePredicate && cloneTypePredicate(signature.typePredicate, mapper),
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
result.target = signature;
result.mapper = mapper;
@@ -6752,7 +6747,7 @@ namespace ts {
const predicate = signature.typePredicate;
if (isIdentifierTypePredicate(predicate)) {
if (expr.arguments[predicate.parameterIndex] &&
getSymbolAtLocation(expr.arguments[predicate.parameterIndex]) === symbol) {
getSymbolAtTypePredicatePosition(expr.arguments[predicate.parameterIndex]) === symbol) {
return getNarrowedType(type, predicate.type, assumeTrue);
}
}
@@ -6762,18 +6757,28 @@ namespace ts {
if (expression.kind === SyntaxKind.ElementAccessExpression || expression.kind === SyntaxKind.PropertyAccessExpression) {
const accessExpression = expression as ElementAccessExpression | PropertyAccessExpression;
const possibleIdentifier = skipParenthesizedNodes(accessExpression.expression);
if (possibleIdentifier.kind === SyntaxKind.Identifier && getSymbolAtLocation(possibleIdentifier) === symbol) {
if (possibleIdentifier.kind === SyntaxKind.Identifier && getSymbolAtTypePredicatePosition(possibleIdentifier) === symbol) {
return getNarrowedType(type, predicate.type, assumeTrue);
}
}
}
return type;
}
function skipParenthesizedNodes(expression: Expression): Expression {
while (expression.kind === SyntaxKind.ParenthesizedExpression) {
expression = (expression as ParenthesizedExpression).expression;
}
return expression;
function skipParenthesizedNodes(expression: Expression): Expression {
while (expression.kind === SyntaxKind.ParenthesizedExpression) {
expression = (expression as ParenthesizedExpression).expression;
}
return expression;
}
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));
}
}

View File

@@ -1632,7 +1632,7 @@
"category": "Error",
"code": 2517
},
"A this based type guard is not assignable to a parameter based type guard": {
"A 'this'-based type guard is not assignable to a parameter-based type guard": {
"category": "Error",
"code": 2518
},

View File

@@ -132,7 +132,8 @@ a.isFollower = mimic.isFollower;
if (mimic.isFollower()) {
mimic.follow();
mimic.isFollower = a.isFollower;
}
}
//// [typeGuardFunctionOfFormThis.js]
var __extends = (this && this.__extends) || function (d, b) {
@@ -279,3 +280,58 @@ 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;

View File

@@ -369,3 +369,4 @@ if (mimic.isFollower()) {
>a : Symbol(a, Decl(typeGuardFunctionOfFormThis.ts, 17, 3))
>isFollower : Symbol(RoyalGuard.isFollower, Decl(typeGuardFunctionOfFormThis.ts, 3, 5))
}

View File

@@ -425,3 +425,4 @@ if (mimic.isFollower()) {
>a : RoyalGuard
>isFollower : () => this is FollowerGuard
}

View File

@@ -7,9 +7,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts(27,1): error TS2322: Type '() => this is FollowerGuard' is not assignable to type '() => 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 (5 errors) ====
==== tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors.ts (7 errors) ====
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
@@ -73,4 +75,17 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionOfFormThisErrors
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'.
}

View File

@@ -48,6 +48,15 @@ if (holder.invalidGuard(c)) {
else {
c;
holder;
}
let detached = a.isFollower;
if (detached()) {
a.follow();
}
else {
a.lead();
}
//// [typeGuardFunctionOfFormThisErrors.js]
@@ -111,3 +120,33 @@ 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;

View File

@@ -1,3 +1,4 @@
// @declaration: true
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
@@ -131,4 +132,4 @@ a.isFollower = mimic.isFollower;
if (mimic.isFollower()) {
mimic.follow();
mimic.isFollower = a.isFollower;
}
}

View File

@@ -1,3 +1,4 @@
// @declaration: true
class RoyalGuard {
isLeader(): this is LeadGuard {
return this instanceof LeadGuard;
@@ -47,4 +48,13 @@ if (holder.invalidGuard(c)) {
else {
c;
holder;
}
let detached = a.isFollower;
if (detached()) {
a.follow();
}
else {
a.lead();
}