forked from typescript-eslint/typescript-eslint
/
propertyTypes.ts
51 lines (44 loc) · 1.53 KB
/
propertyTypes.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 ts from 'typescript';
export function getTypeOfPropertyOfName(
checker: ts.TypeChecker,
type: ts.Type,
name: string,
escapedName?: ts.__String,
): ts.Type | undefined {
// Most names are directly usable in the checker and aren't different from escaped names
if (!escapedName || !isSymbol(escapedName)) {
return checker.getTypeOfPropertyOfType(type, name);
}
// Symbolic names may differ in their escaped name compared to their human-readable name
// https://github.com/typescript-eslint/typescript-eslint/issues/2143
const escapedProperty = type
.getProperties()
.find(property => property.escapedName === escapedName);
return escapedProperty
? checker.getDeclaredTypeOfSymbol(escapedProperty)
: undefined;
}
export function getTypeOfPropertyOfType(
checker: ts.TypeChecker,
type: ts.Type,
property: ts.Symbol,
): ts.Type | undefined {
return getTypeOfPropertyOfName(
checker,
type,
property.getName(),
property.getEscapedName(),
);
}
// Symbolic names need to be specially handled because TS api is not sufficient for these cases.
function isSymbol(escapedName: string): boolean {
return isKnownSymbol(escapedName) || isPrivateIdentifierSymbol(escapedName);
}
// case for escapedName: "__@foo@10", name: "__@foo@10"
function isKnownSymbol(escapedName: string): boolean {
return escapedName.startsWith('__@');
}
// case for escapedName: "__#1@#foo", name: "#foo"
function isPrivateIdentifierSymbol(escapedName: string): boolean {
return escapedName.startsWith('__#');
}