mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-29 16:29:19 -05:00
Addresses PR feedback
This commit is contained in:
@@ -3231,7 +3231,10 @@ module ts {
|
||||
|
||||
let returnType: Type;
|
||||
let typePredicate: TypePredicate;
|
||||
if (declaration.typePredicate) {
|
||||
if (classType) {
|
||||
returnType = classType;
|
||||
}
|
||||
else if (declaration.typePredicate) {
|
||||
returnType = booleanType;
|
||||
let typePredicateNode = declaration.typePredicate;
|
||||
let links = getNodeLinks(typePredicateNode);
|
||||
@@ -3242,14 +3245,11 @@ module ts {
|
||||
links.typeFromTypePredicate = getTypeFromTypeNode(declaration.typePredicate.type);
|
||||
}
|
||||
typePredicate = {
|
||||
parameterName: typePredicateNode.parameterName ? typePredicateNode.parameterName.text : undefined,
|
||||
parameterIndex: typePredicateNode.parameterName ? links.typePredicateParameterIndex : undefined,
|
||||
type: links.typeFromTypePredicate
|
||||
parameterName: typePredicateNode.parameterName ? typePredicateNode.parameterName.text : undefined,
|
||||
parameterIndex: typePredicateNode.parameterName ? links.typePredicateParameterIndex : undefined,
|
||||
type: links.typeFromTypePredicate
|
||||
};
|
||||
}
|
||||
else if (classType) {
|
||||
returnType = classType;
|
||||
}
|
||||
else if (declaration.type) {
|
||||
returnType = getTypeFromTypeNode(declaration.type);
|
||||
}
|
||||
@@ -3976,17 +3976,22 @@ module ts {
|
||||
|
||||
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) {
|
||||
signature.typePredicate.type = instantiateType(signature.typePredicate.type, mapper);
|
||||
freshTypePredicate = {
|
||||
parameterName: signature.typePredicate.parameterName,
|
||||
parameterIndex: signature.typePredicate.parameterIndex,
|
||||
type: instantiateType(signature.typePredicate.type, mapper)
|
||||
}
|
||||
}
|
||||
let result = createSignature(signature.declaration, freshTypeParameters,
|
||||
instantiateList(signature.parameters, mapper, instantiateSymbol),
|
||||
signature.resolvedReturnType ? instantiateType(signature.resolvedReturnType, mapper) : undefined,
|
||||
signature.typePredicate,
|
||||
freshTypePredicate,
|
||||
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
|
||||
result.target = signature;
|
||||
result.mapper = mapper;
|
||||
@@ -4656,33 +4661,33 @@ module ts {
|
||||
}
|
||||
|
||||
if (source.typePredicate && target.typePredicate) {
|
||||
if (source.typePredicate.parameterIndex !== target.typePredicate.parameterIndex ||
|
||||
source.typePredicate.type.symbol !== target.typePredicate.type.symbol) {
|
||||
|
||||
let hasDifferentParamaterIndex = source.typePredicate.parameterIndex !== target.typePredicate.parameterIndex;
|
||||
let hasDifferentTypes = !isTypeIdenticalTo(source.typePredicate.type, target.typePredicate.type);
|
||||
if (hasDifferentParamaterIndex || hasDifferentTypes) {
|
||||
if (reportErrors) {
|
||||
let sourceParamText = source.typePredicate.parameterName;
|
||||
let targetParamText = target.typePredicate.parameterName;
|
||||
let sourceTypeText = typeToString(source.typePredicate.type);
|
||||
let targetTypeText = typeToString(target.typePredicate.type);
|
||||
|
||||
if (source.typePredicate.parameterIndex !== target.typePredicate.parameterIndex) {
|
||||
reportError(Diagnostics.Parameter_index_from_0_does_not_match_the_parameter_index_from_1,
|
||||
if (hasDifferentParamaterIndex) {
|
||||
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1,
|
||||
sourceParamText,
|
||||
targetParamText);
|
||||
}
|
||||
if (source.typePredicate.type.symbol !== target.typePredicate.type.symbol) {
|
||||
if (hasDifferentTypes) {
|
||||
reportError(Diagnostics.Type_0_is_not_assignable_to_type_1,
|
||||
sourceTypeText,
|
||||
targetTypeText);
|
||||
}
|
||||
|
||||
reportError(Diagnostics.Type_guard_annotation_0_is_not_assignable_to_1,
|
||||
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1,
|
||||
`${sourceParamText} is ${sourceTypeText}`,
|
||||
`${targetParamText} is ${targetTypeText}`);
|
||||
}
|
||||
|
||||
return Ternary.False;
|
||||
}
|
||||
return Ternary.True;
|
||||
}
|
||||
else if (!source.typePredicate && target.typePredicate) {
|
||||
if (reportErrors) {
|
||||
@@ -5223,12 +5228,15 @@ module ts {
|
||||
|
||||
function inferFromSignature(source: Signature, target: Signature) {
|
||||
forEachMatchingParameterType(source, target, inferFromTypes);
|
||||
if (source.typePredicate &&
|
||||
target.typePredicate &&
|
||||
target.typePredicate.parameterIndex === source.typePredicate.parameterIndex) {
|
||||
|
||||
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
|
||||
return;
|
||||
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 infer from the type from type predicates. Since
|
||||
// we can't infer any type information from the return types. We can just add a return
|
||||
// statement after the below infer statement.
|
||||
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
|
||||
return;
|
||||
}
|
||||
}
|
||||
inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
|
||||
}
|
||||
@@ -5633,19 +5641,24 @@ module ts {
|
||||
}
|
||||
|
||||
if (targetType) {
|
||||
// Narrow to the target type if it's a subtype of the current type
|
||||
if (isTypeSubtypeOf(targetType, type)) {
|
||||
return targetType;
|
||||
}
|
||||
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, targetType)));
|
||||
}
|
||||
return getOptionalNarrowedType(type, targetType);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
function getOptionalNarrowedType(originalType: Type, narrowedTypeCandidate: Type) {
|
||||
// Narrow to the target type if it's a subtype of the current type
|
||||
if (isTypeSubtypeOf(narrowedTypeCandidate, originalType)) {
|
||||
return narrowedTypeCandidate;
|
||||
}
|
||||
// If the current type is a union type, remove all constituents that aren't subtypes of the target.
|
||||
if (originalType.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>originalType).types, t => isTypeSubtypeOf(t, narrowedTypeCandidate)));
|
||||
}
|
||||
return originalType;
|
||||
}
|
||||
|
||||
function shouldNarrowTypeByTypePredicate(signature: Signature, expr: CallExpression): boolean {
|
||||
if (!signature.typePredicate) {
|
||||
return false;
|
||||
@@ -5670,18 +5683,16 @@ module ts {
|
||||
}
|
||||
let signature = getResolvedSignature(expr);
|
||||
if (!assumeTrue) {
|
||||
if (type.flags & TypeFlags.Union && signature.typePredicate) {
|
||||
if (type.flags & TypeFlags.Union &&
|
||||
signature.typePredicate &&
|
||||
getSymbolAtLocation(expr.arguments[signature.typePredicate.parameterIndex]) === symbol) {
|
||||
|
||||
return getUnionType(filter((<UnionType>type).types, t => !isTypeSubtypeOf(t, signature.typePredicate.type)));
|
||||
}
|
||||
return type;
|
||||
}
|
||||
if (shouldNarrowTypeByTypePredicate(signature, expr)) {
|
||||
if (isTypeSubtypeOf(signature.typePredicate.type, type)) {
|
||||
return signature.typePredicate.type;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(filter((<UnionType>type).types, t => isTypeSubtypeOf(t, signature.typePredicate.type)));
|
||||
}
|
||||
return getOptionalNarrowedType(type, signature.typePredicate.type);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@@ -8640,7 +8651,7 @@ module ts {
|
||||
getTypeAtLocation(node.parameters[links.typePredicateParameterIndex]),
|
||||
node.typePredicate.type);
|
||||
}
|
||||
else if(node.typePredicate.parameterName) {
|
||||
else if (node.typePredicate.parameterName) {
|
||||
error(node.typePredicate.parameterName,
|
||||
Diagnostics.Cannot_find_parameter_0,
|
||||
node.typePredicate.parameterName.text);
|
||||
@@ -10217,6 +10228,9 @@ module ts {
|
||||
if (node.expression) {
|
||||
let func = getContainingFunction(node);
|
||||
if (func) {
|
||||
let signature = getSignatureFromDeclaration(func);
|
||||
let exprType = checkExpressionCached(node.expression);
|
||||
|
||||
if (func.asteriskToken) {
|
||||
// A generator does not need its return expressions checked against its return type.
|
||||
// Instead, the yield expressions are checked against the element type.
|
||||
@@ -10225,13 +10239,7 @@ module ts {
|
||||
return;
|
||||
}
|
||||
|
||||
let signature = getSignatureFromDeclaration(func);
|
||||
let exprType = checkExpressionCached(node.expression);
|
||||
if (signature.typePredicate && exprType !== booleanType) {
|
||||
error(node.expression, Diagnostics.A_type_guard_function_can_only_return_a_boolean);
|
||||
}
|
||||
let returnType = getReturnTypeOfSignature(signature);
|
||||
|
||||
if (func.kind === SyntaxKind.SetAccessor) {
|
||||
error(node.expression, Diagnostics.Setters_cannot_return_a_value);
|
||||
}
|
||||
@@ -10240,7 +10248,7 @@ module 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)) {
|
||||
else if (func.type || isGetAccessorWithAnnotatatedSetAccessor(func) || signature.typePredicate) {
|
||||
checkTypeAssignableTo(exprType, returnType, node.expression, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,8 +182,8 @@ module ts {
|
||||
A_non_type_guard_function_is_not_assignable_to_a_type_guard_function: { code: 1224, category: DiagnosticCategory.Error, key: "A non-type guard function is not assignable to a type guard function." },
|
||||
A_type_guard_function_can_only_return_a_boolean: { code: 1225, category: DiagnosticCategory.Error, key: "A type-guard function can only return a boolean." },
|
||||
Cannot_find_parameter_0: { code: 1226, category: DiagnosticCategory.Error, key: "Cannot find parameter '{0}'." },
|
||||
Type_guard_annotation_0_is_not_assignable_to_1: { code: 1227, category: DiagnosticCategory.Error, key: "Type-guard annotation '{0}' is not assignable to '{1}'." },
|
||||
Parameter_index_from_0_does_not_match_the_parameter_index_from_1: { code: 1228, category: DiagnosticCategory.Error, key: "Parameter index from '{0}' does not match the parameter index from '{1}'." },
|
||||
Type_predicate_0_is_not_assignable_to_1: { code: 1227, category: DiagnosticCategory.Error, key: "Type predicate '{0}' is not assignable to '{1}'." },
|
||||
Parameter_0_is_not_in_the_same_position_as_parameter_1: { code: 1228, category: DiagnosticCategory.Error, key: "Parameter '{0}' is not in the same position as parameter '{1}'." },
|
||||
Type_0_and_type_1_are_disjoint_types: { code: 1229, category: DiagnosticCategory.Error, key: "Type '{0}' and type '{1}' are disjoint types." },
|
||||
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
|
||||
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
|
||||
|
||||
@@ -715,11 +715,11 @@
|
||||
"category": "Error",
|
||||
"code": 1226
|
||||
},
|
||||
"Type-guard annotation '{0}' is not assignable to '{1}'.": {
|
||||
"Type predicate '{0}' is not assignable to '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 1227
|
||||
},
|
||||
"Parameter index from '{0}' does not match the parameter index from '{1}'.": {
|
||||
"Parameter '{0}' is not in the same position as parameter '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 1228
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(15,12): error TS1225: A type-guard function can only return a boolean.
|
||||
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(18,55): error TS2304: Cannot find name 'x'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,57): error TS1144: '{' or ';' expected.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(18,57): error TS2304: Cannot find name 'is'.
|
||||
@@ -17,13 +17,13 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(56,7):
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(61,7): error TS2339: Property 'propB' does not exist on type 'A'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(66,7): error TS2339: Property 'propB' does not exist on type 'A'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(71,46): error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'.
|
||||
Type-guard annotation 'p1 is C' is not assignable to 'p1 is B'.
|
||||
Type predicate 'p1 is C' is not assignable to 'p1 is B'.
|
||||
Type 'C' is not assignable to type 'B'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
|
||||
A non-type guard function is not assignable to a type guard function.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(81,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
|
||||
Type-guard annotation 'p2 is A' is not assignable to 'p1 is A'.
|
||||
Parameter index from 'p2' does not match the parameter index from 'p1'.
|
||||
Type predicate 'p2 is A' is not assignable to 'p1 is A'.
|
||||
Parameter 'p2' is not in the same position as parameter 'p1'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(87,1): error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
|
||||
tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56): error TS1226: Cannot find parameter 'p1'.
|
||||
|
||||
@@ -45,7 +45,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
|
||||
function hasANonBooleanReturnStatement(x): x is A {
|
||||
return '';
|
||||
~~
|
||||
!!! error TS1225: A type-guard function can only return a boolean.
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'boolean'.
|
||||
}
|
||||
|
||||
function hasTypeGuardTypeInsideTypeGuardType(x): x is x is A {
|
||||
@@ -137,7 +137,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
|
||||
acceptingDifferentSignatureTypeGuardFunction(isC);
|
||||
~~~
|
||||
!!! error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'.
|
||||
!!! error TS2345: Type-guard annotation 'p1 is C' is not assignable to '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'.
|
||||
|
||||
// Boolean not assignable to type guard
|
||||
@@ -154,8 +154,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(92,56)
|
||||
assign2 = function(p1, p2): p2 is A {
|
||||
~~~~~~~
|
||||
!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'.
|
||||
!!! error TS2322: Type-guard annotation 'p2 is A' is not assignable to 'p1 is A'.
|
||||
!!! error TS2322: Parameter index from 'p2' does not match the parameter index from 'p1'.
|
||||
!!! error TS2322: Type predicate 'p2 is A' is not assignable to 'p1 is A'.
|
||||
!!! error TS2322: Parameter 'p2' is not in the same position as parameter 'p1'.
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user