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