mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-05 16:38:05 -06:00
Reimplemented Nathan's changes.
This commit is contained in:
parent
29c18058d6
commit
4f84639e47
@ -3432,6 +3432,44 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
function getTypeOfBasePropertyDeclaration(declaration: PropertyDeclaration) {
|
||||
if (declaration.parent.kind === SyntaxKind.ClassDeclaration) {
|
||||
const parent = <ClassLikeDeclaration>declaration.parent;
|
||||
const propertyName = declaration.symbol.name;
|
||||
const extendedPropertyType = getSinglePropertyTypeOfTypes(getBaseTypes(<InterfaceType>getTypeOfSymbol(getSymbolOfNode(parent))), propertyName);
|
||||
if (extendedPropertyType) {
|
||||
return extendedPropertyType;
|
||||
}
|
||||
const implementedTypeNodes = getClassImplementsHeritageClauseElements(parent);
|
||||
if (implementedTypeNodes) {
|
||||
return getSinglePropertyTypeOfTypes(map(implementedTypeNodes, getTypeFromTypeReference), propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getSinglePropertyTypeOfTypes(types: Type[], propertyName: string) {
|
||||
let result: Type;
|
||||
for (const t of types) {
|
||||
if (t !== unknownType) {
|
||||
const property = getPropertyOfType(t, propertyName);
|
||||
if (!property || property.valueDeclaration.flags & NodeFlags.Private) {
|
||||
continue;
|
||||
}
|
||||
if (property.name === propertyName) {
|
||||
const propertyType = getTypeOfSymbol(property);
|
||||
if (result && result !== propertyType) {
|
||||
// if there's more than one matching property, return undefined
|
||||
return undefined;
|
||||
}
|
||||
result = propertyType;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getTargetType(type: ObjectType): Type {
|
||||
return type.flags & TypeFlags.Reference ? (<TypeReference>type).target : type;
|
||||
}
|
||||
@ -5898,7 +5936,7 @@ namespace ts {
|
||||
// Returns true if the given expression contains (at any level of nesting) a function or arrow expression
|
||||
// that is subject to contextual typing.
|
||||
function isContextSensitive(node: Expression | MethodDeclaration | ObjectLiteralElement): boolean {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isMethod(node));
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionExpression:
|
||||
case SyntaxKind.ArrowFunction:
|
||||
@ -5931,8 +5969,8 @@ namespace ts {
|
||||
return !node.typeParameters && areAllParametersUntyped && !isNullaryArrow;
|
||||
}
|
||||
|
||||
function isContextSensitiveFunctionOrObjectLiteralMethod(func: Node): func is FunctionExpression | MethodDeclaration {
|
||||
return (isFunctionExpressionOrArrowFunction(func) || isObjectLiteralMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func);
|
||||
function isContextSensitiveFunctionOrMethod(func: Node): func is FunctionExpression | MethodDeclaration {
|
||||
return (isFunctionExpressionOrArrowFunction(func) || isMethod(func)) && isContextSensitiveFunctionLikeDeclaration(func);
|
||||
}
|
||||
|
||||
function getTypeWithoutSignatures(type: Type): Type {
|
||||
@ -9374,7 +9412,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getContextualThisParameter(func: FunctionLikeDeclaration): Symbol {
|
||||
if (isContextSensitiveFunctionOrObjectLiteralMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
|
||||
if (isContextSensitiveFunctionOrMethod(func) && func.kind !== SyntaxKind.ArrowFunction) {
|
||||
const contextualSignature = getContextualSignature(func);
|
||||
if (contextualSignature) {
|
||||
return contextualSignature.thisParameter;
|
||||
@ -9387,7 +9425,7 @@ namespace ts {
|
||||
// Return contextual type of parameter or undefined if no contextual type is available
|
||||
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
|
||||
const func = parameter.parent;
|
||||
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
|
||||
if (isContextSensitiveFunctionOrMethod(func)) {
|
||||
const iife = getImmediatelyInvokedFunctionExpression(func);
|
||||
if (iife) {
|
||||
const indexOfParameter = indexOf(func.parameters, parameter);
|
||||
@ -9447,6 +9485,12 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
if (declaration.kind === SyntaxKind.PropertyDeclaration) {
|
||||
const type = getTypeOfBasePropertyDeclaration(<PropertyDeclaration>declaration);
|
||||
if (type) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
if (isBindingPattern(declaration.name)) {
|
||||
return getTypeFromBindingPattern(<BindingPattern>declaration.name, /*includePatternInType*/ true, /*reportErrors*/ false);
|
||||
}
|
||||
@ -9815,15 +9859,23 @@ namespace ts {
|
||||
|
||||
function getContextualSignatureForFunctionLikeDeclaration(node: FunctionLikeDeclaration): Signature {
|
||||
// Only function expressions, arrow functions, and object literal methods are contextually typed.
|
||||
return isFunctionExpressionOrArrowFunction(node) || isObjectLiteralMethod(node)
|
||||
return isFunctionExpressionOrArrowFunction(node) || isMethod(node)
|
||||
? getContextualSignature(<FunctionExpression>node)
|
||||
: undefined;
|
||||
}
|
||||
|
||||
function getContextualTypeForFunctionLikeDeclaration(node: FunctionExpression | MethodDeclaration) {
|
||||
return isObjectLiteralMethod(node) ?
|
||||
getContextualTypeForObjectLiteralMethod(node) :
|
||||
getApparentTypeOfContextualType(node);
|
||||
let type: Type;
|
||||
if (isFunctionExpressionOrArrowFunction(node)) {
|
||||
type = getApparentTypeOfContextualType(node);
|
||||
}
|
||||
else if (isObjectLiteralMethod(node)) {
|
||||
type = getContextualTypeForObjectLiteralMethod(node);
|
||||
}
|
||||
else if (isMethod(node)) {
|
||||
type = getTypeOfBasePropertyDeclaration(node);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Return the contextual signature for a given expression node. A contextual type provides a
|
||||
@ -9832,7 +9884,6 @@ namespace ts {
|
||||
// all identical ignoring their return type, the result is same signature but with return type as
|
||||
// union type of return types from these signatures
|
||||
function getContextualSignature(node: FunctionExpression | MethodDeclaration): Signature {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
const type = getContextualTypeForFunctionLikeDeclaration(node);
|
||||
if (!type) {
|
||||
return undefined;
|
||||
|
||||
@ -864,6 +864,10 @@ namespace ts {
|
||||
return predicate && predicate.kind === TypePredicateKind.Identifier;
|
||||
}
|
||||
|
||||
export function isMethod(node: Node): node is MethodDeclaration {
|
||||
return node && node.kind === SyntaxKind.MethodDeclaration;
|
||||
}
|
||||
|
||||
export function isThisTypePredicate(predicate: TypePredicate): predicate is ThisTypePredicate {
|
||||
return predicate && predicate.kind === TypePredicateKind.This;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user