-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
/
getContextualType.ts
51 lines (48 loc) · 1.56 KB
/
getContextualType.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import * as tools from 'ts-api-utils';
import * as ts from 'typescript';
/**
* Returns the contextual type of a given node.
* Contextual type is the type of the target the node is going into.
* i.e. the type of a called function's parameter, or the defined type of a variable declaration
*/
export function getContextualType(
checker: ts.TypeChecker,
node: ts.Expression,
): ts.Type | undefined {
const parent = node.parent;
if (!parent) {
return;
}
if (ts.isCallExpression(parent) || ts.isNewExpression(parent)) {
if (node === parent.expression) {
// is the callee, so has no contextual type
return;
}
} else if (
ts.isVariableDeclaration(parent) ||
ts.isPropertyDeclaration(parent) ||
tools.isParameterDeclaration(parent)
) {
return parent.type ? checker.getTypeFromTypeNode(parent.type) : undefined;
} else if (ts.isJsxExpression(parent)) {
return checker.getContextualType(parent);
} else if (ts.isPropertyAssignment(parent) && ts.isIdentifier(node)) {
return checker.getContextualType(node);
} else if (
ts.isBinaryExpression(parent) &&
parent.operatorToken.kind === ts.SyntaxKind.EqualsToken &&
parent.right === node
) {
// is RHS of assignment
return checker.getTypeAtLocation(parent.left);
} else if (
![ts.SyntaxKind.TemplateSpan, ts.SyntaxKind.JsxExpression].includes(
parent.kind,
)
) {
// parent is not something we know we can get the contextual type of
return;
}
// TODO - support return statement checking
return checker.getContextualType(node);
}