Add support for type aliases, restructure
This commit is contained in:
parent
d1072031d6
commit
e3232882aa
@ -26,6 +26,8 @@ export interface ITyped<T> {
|
||||
}
|
||||
|
||||
type AorB = 'A' | 'B'
|
||||
/* tslint:disable-next-line */
|
||||
type Param<T> = {t: T}
|
||||
|
||||
export class Person {
|
||||
readonly name!: Name
|
||||
@ -54,4 +56,5 @@ export class Typed<A, B extends 'singleVal', C = 'defVal'> {
|
||||
b!: ITyped<B>
|
||||
c!: ITyped<C>
|
||||
d!: ITyped<A> | ITyped<B>
|
||||
e!: Param<Company>
|
||||
}
|
||||
|
||||
@ -53,45 +53,40 @@ export function typecheck() {
|
||||
* of types. For example: types.filter(filterGlobalTypes)
|
||||
*/
|
||||
function filterGlobalTypes(type: ts.Type): boolean {
|
||||
console.log('filterGlobalTypes', typeToString(type))
|
||||
// console.log('fgt', typeToString(type))
|
||||
if (type.aliasSymbol) {
|
||||
// keep type aliases
|
||||
return true
|
||||
}
|
||||
const symbol = type.getSymbol()
|
||||
if (!symbol) {
|
||||
console.log(' no symbol')
|
||||
// console.log(' no symbol')
|
||||
// e.g. string or number types have no symbol
|
||||
return false
|
||||
}
|
||||
if (symbol && !((symbol as any).parent)) {
|
||||
console.log(' no parent')
|
||||
// console.log(' no parent')
|
||||
// e.g. Array symbol has no parent
|
||||
return false
|
||||
}
|
||||
if (type.isLiteral()) {
|
||||
console.log(' is literal')
|
||||
// console.log(' is literal')
|
||||
return false
|
||||
}
|
||||
if (type.isUnionOrIntersection()) {
|
||||
console.log(' is union or intersection')
|
||||
// union type params should have already been extracted
|
||||
// console.log(' is u or i')
|
||||
return false
|
||||
}
|
||||
if (isObjectType(type) && isTypeReference(type)) {
|
||||
console.log(' is reference')
|
||||
if (isObjectType(type.target)
|
||||
&& type.target.objectFlags & ts.ObjectFlags.Tuple) {
|
||||
// console.log(' is object type')
|
||||
if (isObjectType(type.target) &&
|
||||
type.target.objectFlags & ts.ObjectFlags.Tuple) {
|
||||
// console.log(' is tuple')
|
||||
return false
|
||||
}
|
||||
}
|
||||
// if (isObjectType(type) && type.objectFlags & ts.ObjectFlags.Tuple) {
|
||||
// console.log(' is tuple')
|
||||
// // tuple params should have already been extracted
|
||||
// return false
|
||||
// }
|
||||
|
||||
console.log(' ',
|
||||
type.flags,
|
||||
(type as any).objectFlags,
|
||||
!!symbol,
|
||||
symbol && !!(symbol as any).parent,
|
||||
)
|
||||
// console.log(' keep!')
|
||||
return true
|
||||
}
|
||||
|
||||
@ -99,6 +94,9 @@ export function typecheck() {
|
||||
* Converts a generic type to the target of the type reference.
|
||||
*/
|
||||
function mapGenericTypes(type: ts.Type): ts.Type {
|
||||
if (type.aliasSymbol) {
|
||||
return checker.getDeclaredTypeOfSymbol(type.aliasSymbol)
|
||||
}
|
||||
if (isObjectType(type) && isTypeReference(type)) {
|
||||
return type.target
|
||||
}
|
||||
@ -117,39 +115,32 @@ export function typecheck() {
|
||||
* Recursively retrieves a list of all type parameters.
|
||||
*/
|
||||
function getAllTypeParameters(type: ts.Type): ts.Type[] {
|
||||
if (isObjectType(type) && isTypeReference(type)) {
|
||||
const types: ts.Type[] = [type]
|
||||
|
||||
if (type.typeArguments) {
|
||||
type.typeArguments.forEach(t => {
|
||||
const ta = getAllTypeParameters(t)
|
||||
types.push(...ta)
|
||||
function collectTypeParams(
|
||||
type2: ts.Type, params?: readonly ts.Type[],
|
||||
): ts.Type[] {
|
||||
const types: ts.Type[] = [type2]
|
||||
if (params) {
|
||||
params.forEach(t => {
|
||||
const atp = getAllTypeParameters(t)
|
||||
types.push(...atp)
|
||||
})
|
||||
}
|
||||
return types
|
||||
}
|
||||
|
||||
if (type.aliasSymbol) {
|
||||
return collectTypeParams(type, type.aliasTypeArguments)
|
||||
}
|
||||
if (isObjectType(type) && isTypeReference(type)) {
|
||||
return collectTypeParams(type, type.typeArguments)
|
||||
}
|
||||
|
||||
if (type.isUnionOrIntersection()) {
|
||||
const unionOrIntersectionTypes = type.types
|
||||
// const types = [type, ...type.types]
|
||||
const types: ts.Type[] = [type]
|
||||
type.types.forEach(t => {
|
||||
const tsp = getAllTypeParameters(t)
|
||||
types.push(...tsp)
|
||||
})
|
||||
return types
|
||||
return collectTypeParams(type, type.types)
|
||||
}
|
||||
|
||||
if (type.isClassOrInterface()) {
|
||||
if (type.typeParameters) {
|
||||
const types = [type, ...type.typeParameters]
|
||||
type.typeParameters.forEach(t => {
|
||||
const tsp = getAllTypeParameters(t)
|
||||
types.push(...tsp)
|
||||
})
|
||||
return types
|
||||
}
|
||||
return [type]
|
||||
return collectTypeParams(type, type.typeParameters)
|
||||
}
|
||||
|
||||
return [type]
|
||||
@ -166,31 +157,23 @@ export function typecheck() {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit nodes finding exported classes
|
||||
*/
|
||||
function visit(node: ts.Node) {
|
||||
// Only consider exported nodes
|
||||
if (!isNodeExported(node)) {
|
||||
function handleClassDeclaration(node: ts.ClassDeclaration) {
|
||||
if (!node.name) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ts.isClassDeclaration(node) && node.name) {
|
||||
// This is a top level class, get its symbol
|
||||
const symbol = checker.getSymbolAtLocation(node.name)
|
||||
if (!symbol) {
|
||||
return
|
||||
}
|
||||
|
||||
const typeParameters: ts.TypeParameter[] = []
|
||||
const expandedTypeParameters: ts.Type[] = []
|
||||
const allRelevantTypes: ts.Type[] = []
|
||||
if (symbol) {
|
||||
// console.log('===')
|
||||
// console.log('text', node.getText(node.getSourceFile()))
|
||||
// console.log('class', symbol.getName())
|
||||
const type = checker.getDeclaredTypeOfSymbol(symbol)
|
||||
|
||||
if (type.isClassOrInterface() && type.typeParameters) {
|
||||
type.typeParameters.forEach(tp => {
|
||||
// console.log(' tp.symbol.name', tp.symbol.name)
|
||||
const constraint = tp.getConstraint()
|
||||
if (constraint) {
|
||||
expandedTypeParameters.push(...getAllTypeParameters(tp))
|
||||
@ -266,6 +249,18 @@ export function typecheck() {
|
||||
|
||||
classDefs.push(classDef)
|
||||
}
|
||||
|
||||
/**
|
||||
* Visit nodes finding exported classes
|
||||
*/
|
||||
function visit(node: ts.Node) {
|
||||
// Only consider exported nodes
|
||||
if (!isNodeExported(node)) {
|
||||
return
|
||||
}
|
||||
|
||||
if (ts.isClassDeclaration(node)) {
|
||||
handleClassDeclaration(node)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user