Coder Social home page Coder Social logo

ts-type-info's Introduction

TSTypeInfo

npm version Build Status Coverage Status

TypeScript AST and code generator.

Uses the TypeScript Compiler API to get information about TypeScript code in an easy to use format.

npm install ts-type-info --save-dev

NOTICE - LIBRARY IS DEPRECATED

This library has been deprecated by ts-simple-ast:

https://github.com/dsherret/ts-simple-ast

Version 7.0 is the last final major release of ts-type-info.

There's certain issues with this library and to address them I had to do a complete redesign. ts-simple-ast wraps the typescript compiler rather than creating separate standalone objects. It's much more powerful and supports a lot more use cases.

AST

// V:\TestFile.ts

export class MyClass {
    myStringProperty: string;
    readonly myNumberProperty = 253;

    myMethod(myParameter: string) {
        return `Test: ${myParameter}`;
    }
}

Get the file info:

import * as TsTypeInfo from "ts-type-info";

const result = TsTypeInfo.getInfoFromFiles(["V:\\TestFile.ts"]);
const property = result.getFile("TestFile.ts")
    .getClass("MyClass")                            // get first by name
    .getProperty(p => p.defaultExpression != null); // or first by what matches

console.log(property.name);                   // myNumberProperty
console.log(property.type.text);              // number
console.log(property.defaultExpression.text); // 253
console.log(property.isReadonly);             // true

// or access the arrays directly
const myMethod = result.files[0].classes[0].methods[0];

console.log(myMethod.name); // myMethod

Code Generation

You can work with objects retrieved from the AST or start with your own new file definition:

import * as TsTypeInfo from "ts-type-info";

// create whatever you like at the start
const file = TsTypeInfo.createFile({
    classes: [{
        name: "MyClass",
        methods: [{
            name: "myMethod",
            parameters: [{ name: "myParam", type: "string" }],
            onBeforeWrite: writer => writer.write("// myMethod is here"),
            onWriteFunctionBody: writer => {
                writer.write(`if (myParam != null && myParam.length > 40)`).block(() => {
                    writer.write("alert(myParam)");
                });
                writer.newLine().write("return myParam;");
            }
        }]
    }]
});

// add to it later
const myClass = file.getClass("MyClass");
myClass.isAbstract = true;
myClass.addDecorator({
    name: "MyDecorator"
});

myClass.addProperty({
    name: "myProperty1",
    type: "string"
});
myClass.addProperty({
    name: "myProperty2",
    type: "number",
    defaultExpression: "4"
});

// write it out
console.log(file.write());

Outputs:

@MyDecorator
abstract class MyClass {
    myProperty1: string;
    myProperty2 = 4;

    // myMethod is here
    myMethod(myParam: string) {
        if (myParam != null && myParam.length > 40) {
            alert(myParam);
        }

        return myParam;
    }
}

Simple Examples

  • Strict Interfaces - Make all interface properties required and append "Strict" to the end of the interface name.

Full Examples

  • TsStateTestGenerator - Code generates functions for testing the state of objects. I used this in this ts-type-info and was able to discover a bunch of unreported bugs. I also no longer have to maintain a large portion of the project because the code is automatically generated for me. I highly recommend this.
  • TsCloneableGenerator - Code generates functions for cloning and filling objects.
  • TsObjectCreate - Code generates functions for creating objects with their types.
  • Server Bridge - Automatically generates client side code to communicate with the server from the server side code.

Include tsNodes

In case there's something you need from the compiler that's not implemented in this library, set the includeTsNodes option to true. This will include the TypeScript compiler nodes in the tsNode property of most objects.

import * as ts from "typescript";
import * as TsTypeInfo from "ts-type-info";

const result = TsTypeInfo.getInfoFromFiles(["V:\\TestFile.ts"], { includeTsNodes: true });
const typeChecker = result.getTypeChecker(); // ts.TypeChecker in case you need it
const myMethod = result.getFile("TestFile.ts").getClass("MyClass").getMethod("myMethod");
const myMethodNode = myMethod.tsNode as ts.MethodDeclaration;

console.log(myMethodNode.body.statements[0].getText()); // "return `Test: ${myParameter}`;"

ts-type-info's People

Contributors

dsherret avatar frankandrobot avatar vincent-pang avatar

Stargazers

Peter Morgan avatar Dimitrij Pinneker avatar HardCoreQual avatar 普通上班族jo avatar David Lai avatar edison avatar  avatar  avatar  avatar  avatar Uday Kumar avatar 宋昂 avatar haidong avatar  avatar  avatar  avatar minhaolee avatar  avatar Andrii avatar 이준범 avatar  avatar yohjr avatar lyxia_ios avatar  avatar Mouad Cherkaoui avatar bluelovers avatar li_xiaodong avatar  avatar Aviran avatar Icemic avatar Patrick Lienau avatar  avatar Kin Wang avatar Steve Sewell avatar Eric Loren avatar Claudiu Ivan avatar Francesco Soncina avatar David Martin avatar Victor Protsenko avatar Sudhakar avatar Touchumind avatar Leo avatar _deprecated_n_w avatar Joseph Kim avatar Vadym Holoveichuk avatar Diullei Gomes avatar Alex avatar Robin Baum avatar Saviio avatar Joooye_34 avatar JT Yu avatar Horiuchi Hiroki avatar Laurence Dougal Myers avatar Michał Lytek avatar Umed Khudoiberdiev avatar Alucardz avatar  avatar Thomas Hickman avatar Vincent Ogloblinsky avatar Fabian Leutgeb avatar Luo Gang avatar HNeukermans avatar Jeremie Pelletier avatar Wis avatar Morlay avatar Samier Saeed avatar Tom Piarulli avatar Nitzan Tomer avatar Vinh avatar Will Sahatdjian avatar Sebastian Sebald avatar Silvio avatar Andrew Bradley avatar Dustin Wehr avatar Serhii avatar yskw avatar Eric Anderson avatar Andrew Pietsch avatar  avatar Alexey Bolisov avatar Phuong Cao avatar Thomas Payne avatar John Weisz avatar Mattia Franchetto avatar Fabrizio Chignoli avatar Markus Wolf avatar Nick Strupat avatar Ryan Cavanaugh avatar Fredy R. Guibert フレディ avatar Joe Wood avatar shine avatar  avatar René Verheij avatar Brad Pillow avatar

Watchers

James Cloos avatar  avatar Fredy R. Guibert フレディ avatar Andrew Jakubowicz avatar  avatar

ts-type-info's Issues

Problem with internal modules

Hey man, tnx for recommending this lib, it's exactly what I was thinking of, already in the making!

I'm trying to run it on my projects, it works really nice for the project with external modules, but for the project with internal modules it doesnt return any classes.

In this project, all files have a reference to the main references.ts, which in turn contains references to all files in the project. I see the type-info tool therefor goes over the entire project if I feed it only 1 file of the project. It also goes over all the .d.ts files.

Before I was getting excactly one and the same class back for each file, which was called 'Basket'.
in basket.d.ts there was a (faulty) line

declare class Basket { ... }

I changed class to interface and the class was removed from all the files, but now I'm left with 0 classes in each file.

I expect the classes of internal modules are defined differently and the tool does not recognise them this way?

Fix broken serialization

Serialization has stopped working after switching to mixins. Fix it and then write tests for it.

Long type text is truncated

For example, the type in this:

options: { fileDefinition: TsTypeInfo.FileDefinition, definitionName: string, moduleName: string, referencePaths: string[] }

Will be truncated to:

{ fileDefinition: TsTypeInfo.FileDefinition, definitionName: string, moduleName: string, reference...

This has to do with the typescript compiler. There is probably a flag to make it get the full type name.

Enums

Add EnumDefinition and EnumMemberDefinition.

Functions

Add support for functions on the file level. Will be on the functions property of FileDefinition.

Static properties

Add staticProperties to ClassDefinition.

Similarly to staticMethods, this could have been rolled into properties. See reason why it's not in #8.

Static methods

Add staticMethods to ClassDefinition.

This could have been added to methods and then have a flag for static, but I think it's better to completely separate the two in order to prevent mistakes where someone accidentally forgets to check if a method is static.

Advanced arrays

In the array that's returned, there should be some methods for selecting specific file names or definitions by their name.

Performance - Ability to disable certain checks

For build performance, it might be beneficial to allow the user to specify certain features when they aren't necessary. For example, disable checking decorators. This would be quite easy to implement.

Tuple types

Do tuple types work? If so, then write some tests... otherwise, support them.

VariableDefinition within FunctionDefinition?

Should probably be a list that contains each statement (which includes definitions and expressions). Need to think about this more though.

Notes

SymbolFlag is: SymbolFalgs.FunctionScopedVariable (1).

Rest parameters

Add flag isRestParameter to ParameterDefinition.

When a parameter is a rest parameter, isRequired should be false.

VariableDefinition

For situations like this:

declare module "definition-var" {
    export let METHODS: string[];
}

The symbol flag of METHODS is a SymbolFlags.BlockScopedVariable (2) so it would be good to create a definition called VariableDefinition

Note that SymbolFlags.Variable (3) should be used as well.

Destructuring function parameters

Check if this works:

class MyClass {
    prop1: number;
    prop2: number;

    constructor ({ prop1, prop2 = 4 }: { prop1: number; prop2?: number; }) {
        this.prop1 = prop1;
        this.prop2 = prop2;
    }
}

Add base class AmbientableDefinition

Would set property isAmbient and hasDeclareKeyword to true in these cases:

declare class MyClass {}
declare interface MyInterface {}
declare function MyFunction();
declare var MyVariable;
declare enum MyEnum { MyMember = 1 };
declare namespace MyNamespace {}
declare module MyModule {}

Optional parameters

Add isRequired: boolean to ParameterDefinition for determining if it's an optional parameter.

Default parameters should be flagged as not required.

Manipulation methods

Add methods for manipulating the definitions.

For example, methods like classDef.addProperties(...);.

Imports

Would be on the FileDefinition level similar to re-exports.

Create structures automatically from Definitions

Using this library, the structure files themselves and "run" test helpers could be generated automatically from the definition classes.

Doing this will help me spend less time maintaining this aspect of the project and it will be guaranteed to be in sync with the definition classes.

A decorator could be used to specify what value something should default to in the tests.

Variables are missing declaration types

Ex: var, const, let. It should be called something like "declaration type".
I may be able to do a PR...where in the code are variables handled?

   {
    "declarationType": "var", // missing
    "name": "foo",
    "isExported": true,
    "typeExpression": {
     "types": [
      {
       "text": "string",
       "properties": [],
       "callSignatures": [],
       "typeArguments": []
      }
     ],
     "text": "string"
    },
    "defaultExpression": {
     "text": "two + three"
    }
   }

It's very straightforward... this code does it:

      var declarationType = 'var'
      declarationType = declarationList.flags & ts.NodeFlags.Let ? 'let' : declarationType
      declarationType = declarationList.flags & ts.NodeFlags.Const ? 'const' : declarationType

But it needs access to the original AST node.

ExportableDefinition

Create an ExportableDefinition. Will be used with parts of the application that are exportable (like classes and functions).

Change accessors to fields

What i mean by that is to simplify lines like:

private _constraintTypeExpression: TypeExpression;

get constraintTypeExpression() {
    return this._constraintTypeExpression;
}

To:

constraintTypeExpression: TypeExpression;

Generated documentation

The documentation should show the classes that this library uses. Those classes that will be displayed in the documentation should be generated by using this library. That way they will always stay up to date and do not need to be maintained.

Accessors

Just noticed that accessors are not supported. This needs to be added in.

Rest Parameters

Rest parameters should be added to ParameterDefinition with a isRestParameter flag.

Interfaces

Add support for interfaces on the file level.

Use runFileDefinitionTests in all test files

All test files should run this in order to find unexpected bugs like #23. Additionally a runClassDefinitionTests function should be created as well as the related structures. Use gulp ensure-dir-structures-match to see if there are any other functions that should be created.

After this, a thorough code review and clean up of the tests should be done. Right now it's not consistent and kind of messy.

Overall, these steps will improve the reliability of the tests.

Better error handling

  1. It should tell the user what symbol name it failed on. This should be a warning.
  2. For the most part, it should try to keep going on as much as possible.

Property constructor doesn't work in definition files

Since accessors are not allowed in definition files and get constructor(): string is put in the definition file as constructor: string, this errors because TypeScript expects constructor to be a constructor function.

The fix is to change constructor to constructorDef unfortunately.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.