Giter VIP home page Giter VIP logo

typescript-transformer's Introduction

Transform PHP types to TypeScript

Latest Version on Packagist Tests Styling PHPStan Total Downloads

This package allows you to convert PHP classes to TypeScript.

This class...

/** @typescript */
class User
{
    public int $id;
    public string $name;
    public ?string $address;
}

... will be converted to this TypeScript type:

export type User = {
    id: number;
    name: string;
    address: string | null;
}

Here's another example.

class Languages extends Enum
{
    const TYPESCRIPT = 'typescript';
    const PHP = 'php';
}

The Languages enum will be converted to:

export type Languages = 'typescript' | 'php';

You can find the full documentation here.

Support us

We invest a lot of resources into creating best in class open source packages. You can support us by buying one of our paid products.

We highly appreciate you sending us a postcard from your hometown, mentioning which of our package(s) you are using. You'll find our address on our contact page. We publish all received postcards on our virtual postcard wall.

Installation

You can install this package via composer:

composer require spatie/typescript-transformer

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security

If you've found a bug regarding security please mail [email protected] instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

typescript-transformer's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

typescript-transformer's Issues

No default/clean install possible due to PHP-parser version conflict

install command on a new Laravel project:

composer require spatie/laravel-typescript-transformer

Generates this issue:

Problem 1
- spatie/typescript-transformer[2.1.13, ..., 2.2.2] require nikic/php-parser ^4.13 -> found nikic/php-parser[v4.13.0, ..., v4.18.0] but the package is fixed to v5.0.0 (lock file version) by a partial update and that version does not match.
- spatie/laravel-typescript-transformer[2.3.0, ..., 2.3.2] require spatie/typescript-transformer ^2.1.13 -> satisfiable by spatie/typescript-transformer[2.1.13, ..., 2.2.2].

Temporary workaround is to first install an older php-parser version by adding this to your require section of composer.json:
"nikic/php-parser": "^4.1"

missing dependencies?

In Laravel 9.48 I've composer required
Laravel Data and then this typescript-transformer package.

When I run php artisan typescript:transform it complaints about several missing dependencies, related to nesbot/carbon package:

Interface "PHPStan\Reflection\MethodsClassReflectionExtension" not found at vendor/nesbot/carbon/src/Carbon/PHPStan/MacroExtension.php:27

Class "Doctrine\DBAL\Types\VarDateTimeType" not found at vendor/nesbot/carbon/src/Carbon/Doctrine/DateTimeType.php:12

I have mostly been doing node/NPM and my expectation would be that these dependencies were handled automatically with composer, like in npm, but maybe I'm wrong.

I apologize if this is not really an issue with typescript-transformer.

i am using this packge but unable to transform the php class into typeScript

My Php Class

<?php

namespace Domain\Orders\DataTransferObjects;

use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript]
class TestType
{
    public string $name;

}

and i get this response in my console

+-----------+-------------------+
| PHP class | TypeScript entity |
+-----------+-------------------+
Transformed 0 PHP types to TypeScript

Using the transformer without artisan

I think it would be great to be able to use the transformer without artisan, e.g. in non-laravel apps or in laravel packages that don't have artisan installed.

Maybe this could be achieved by providing a more general CLI as a vendor binary? The path to the config file could be provided as an argument.

If you are open to the idea, I'd be happy to give it a shot and create a pull request.

Thanks,
Michael

Workflows are referencing vulnerable actions

Hello, there!

As part of the university research we are currently doing regarding the security of Github Actions, we noticed that one or many of the workflows that are part of this repository are referencing vulnerable versions of the third-party actions. As part of a disclosure process, we decided to open issues to notify GitHub Community.

Please note that there are could be some false positives in our methodology, thus not all of the open issues could be valid. If that is the case, please let us know, so that we can improve on our approach. You can contact me directly using an email: ikoishy [at] ncsu.edu

Thanks in advance

  1. The workflow run-tests.yml is referencing action shivammathur/setup-php using references v1. However this reference is missing the commit 7163319 which may contain fix to the vulnerability.

The vulnerability fix that is missing by actions' versions could be related to:
(1) CVE fix
(2) upgrade of vulnerable dependency
(3) fix to secret leak and others.
Please consider updating the reference to the action.

If you end up updating the reference, please let us know. We need the stats for the paper :-)

PHP enums still not transformed correctly

Using the following versions:

        "spatie/laravel-data": "^1.2.4",
        "spatie/laravel-typescript-transformer": "^2.1.3",
        "spatie/typescript-transformer": "^2.1.6"

The following Data object:

#[TypeScript]
class Test extends Data
{
    public function __construct(
        public WorkOrderType $type = WorkOrderType::UNKNOWN,
    ) {
    }
}

enum WorkOrderType: string
{
    case UNKNOWN = 'UNKNOWN;
}

Gets transformed to any:

export type Test = {
     type: any;
};

Am I missing something in setup or config that causes this?

My work around is adding the following processor. Maybe this could be (improved and) included by default?

class ConvertEnumTypeProcessor implements TypeProcessor
{
    public function process(
        Type $type,
        ReflectionParameter | ReflectionMethod | ReflectionProperty $reflection,
        MissingSymbolsCollection $missingSymbolsCollection
    ): ?Type {
        if ($type instanceof Object_ && enum_exists($type->__toString())) {
            $backing_type = (new ReflectionEnum($type->__toString()))->getBackingType();

            return $backing_type ? (new TypeResolver())->resolve((string) $backing_type) : $type;
        }

        return $type;
    }
}

Nullable property types

Although we have a concept of null in property types, we don't have a concept for nullable property types like:

name ?: string;

ArrayShapes

phpdocs with arrayshapes fails.

for exemple: /** @var array{a: int[], b: string[], c: float} $config **/

first it fails at the regexp:

return '/@var ((?:\s?[\\w?|\\\\<>,-]+(?:\[])?)+)/';

then it fails at transpiling (phpDocumentor\Reflection\PseudoTypes\ArrayShape)

default => throw new Exception("Could not transform type: {$type}")

it's partly solved with:

$type instanceof PseudoType => $this->execute($type->underlyingType()),

Senario 1

Input: /** @var array<string, array{a: int[], b: string[], c: float}> $config **/

Expected: {[key: string]: {a: number[], b: string[], c: number}}

Current: RuntimeException Unexpected token "", expected '>' at offset 19 on line 1,
due to the regexp only catching @var array<string, array

Feature request: Make namespace in ts file optional

Hi Spatie! Thanks for amazing package.
I have some issue with generated ts file - our fe guys wants all entities be w\o namespaces.

Something like:

typescript-transformer.php

...
   'preserve_namespaces' => true/false,
.....

Please add this feature

Broken link in the docs

Issue

docs/usage/using-transformers.md has a link at the very bottom that should lead to docs/transformers/getting-started.md, however it's broken and redirects to docs/introduction.md.

## Writing your own transformers
We've added a whole section in the docs about [writing transformers](docs/typescript-transformer/v2/transformers/getting-started).

My inspection

The link in the .md source file seems to be structured correctly:

We've added a whole section in the docs about [writing transformers](docs/typescript-transformer/v2/transformers/getting-started).

Upon further inspection in the browser, it appears that the link is not resolved to an absolute url, but to the relative url just like in the document itself.

<!-- Link expected to resolve to this -->
<a href="https://spatie.be/docs/typescript-transformer/v2/transformers/getting-started">writing transformers</a>

<!-- Instead we get this -->
<a href="docs/typescript-transformer/v2/transformers/getting-started">writing transformers</a>

The issue manifests because the source file and the target file are located in different namespaces (directories), clicking on the link appends it to the current namespace, eventually resolving to https://spatie.be/docs/typescript-transformer/v2/usage/docs/typescript-transformer/v2/transformers/getting-started, a link that doesn't exist, hence redirection to the introduction page.

Mitigation

This issue can be fixed in one of two ways.

  1. Using absolute url instead of relative
We've added a whole section in the docs about [writing transformers](https://spatie.be/docs/typescript-transformer/v2/transformers/getting-started).
  1. Using directory traversal to navigate to target namespace/file
We've added a whole section in the docs about [writing transformers](../transformers/getting-started).

The second mitigation is cleaner in my opinion, a PR with such a mitigation will be submitted momentarily.

Suggestions

This might be the only instance of this issue in spatie/typescript-transformer docs, but as far as I know, all spatie packages generate their docs the same way, therefore similar issues might be present in docs of other packages.

I suggest to use a script to scan the docs directory in every spatie package to catch any instance of a file having a link to another file in a different namespace.

Also, having a Github Actions job that warns/fixes this issue will insure future proofing against introducing such links accidentally.

Backslashes are removed from enum values when using ::class notation.

I've got the following situation. I want to map the enum values to a class-string so I can use them for my polymorphic relation and in the modal to cast them to a human readable enum.

<?php

namespace App\Enums\Pokemon;

use App\Models\Pokemon\PokemonEncounter;
use App\Models\Pokemon\PokemonEncounterMove;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript()]
enum BattleRoundActionType: string
{
    case SwapPokemon = PokemonEncounter::class;
    case ExecuteMove = PokemonEncounterMove::class;
}

Then later in the model, I can do the following:

<?php

namespace App\Models\Pokemon;

use App\Enums\Pokemon\BattleRoundActionType;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;

class BattleRound extends Model
{
    protected $casts = [
        'initiator_action_id'   => 'int',
        'initiator_action_type' => BattleRoundActionType::class,
    ];

    public function initiatorAction(): MorphTo
    {
        return $this->morphTo();
    }
}

However, when running the TypeScript generator, this results in the following code:

declare namespace App.Enums.Pokemon {
  export type BattleRoundActionType =
    | 'AppModelsPokemonPokemonEncounter'
    | 'AppModelsPokemonPokemonEncounterMove';
}

This is what I expected:

declare namespace App.Enums.Pokemon {
  export type BattleRoundActionType =
    | 'App\\Models\\Pokemon\\PokemonEncounter';
    | 'App\\Models\\Pokemon\\PokemonEncounterMove';
}

Running:

  • PHP 8.2 on Mac
  • Package version 2.3.2

Update

I found out that it is Prettier that removes the backslashes because they have no use. Without Prettier, the result looks like this:

declare namespace App.Enums.Pokemon {
export type BattleRoundActionType = 'App\Models\Pokemon\PokemonEncounter' | 'App\Models\Pokemon\PokemonEncounterMove';
}

Still not what I expected, the backslashes should be double, but it explains why there were no backslashes at all.

Mechanism to include multiple search paths?

I was wondering if there was a mechanism to include multiple search paths? We're looking to introduce to a fairly large code base and it can take a long time to search through all the classes. However, we have classes in a couple different top level directories that we'd like to convert.

app/
  Foo/
  Bar/
  Irrelevant/

Something like search_paths' => [app_path('Foo'), app_path('Bar')] would be awesome but I'm not sure how to go about it.

Transformed 0 PHP types to TypeScript

I'm running the script on windows 11 with PHP version 8.2.7 I've also tried several approaches without success:

set up a project with only "spatie/typescript-transformer" v2 installed... 0 TypeScript code generated.
create a Laravel project and publish the configuration of "spatie/laravel-typescript-transformer" v2... 0 TypeScript code generated.

+-----------+-------------------+
| PHP class | TypeScript entity |
+-----------+-------------------+
Transformed 0 PHP types to TypeScript

I've tested both approaches to commenting my PHP classes.

/** @typescript */

and

#[TypeScript]

I'm a little desperate

my composer.json

{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The skeleton application for the Laravel framework.",
    "keywords": ["laravel", "framework"],
    "license": "MIT",
    "require": {
        "php": "^8.1",
        "guzzlehttp/guzzle": "^7.2",
        "laravel/framework": "^10.10",
        "laravel/sanctum": "^3.2",
        "laravel/tinker": "^2.8",
        "spatie/laravel-typescript-transformer": "^2.3"
    },
    "require-dev": {
        "fakerphp/faker": "^1.9.1",
        "laravel/pint": "^1.0",
        "laravel/sail": "^1.18",
        "mockery/mockery": "^1.4.4",
        "nunomaduro/collision": "^7.0",
        "phpunit/phpunit": "^10.1",
        "spatie/laravel-ignition": "^2.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/",
            "Database\\Factories\\": "database/factories/",
            "Database\\Seeders\\": "database/seeders/"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Tests\\": "tests/"
        }
    },
    "scripts": {
        "post-autoload-dump": [
            "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
            "@php artisan package:discover --ansi"
        ],
        "post-update-cmd": [
            "@php artisan vendor:publish --tag=laravel-assets --ansi --force"
        ],
        "post-root-package-install": [
            "@php -r \"file_exists('.env') || copy('.env.example', '.env');\""
        ],
        "post-create-project-cmd": [
            "@php artisan key:generate --ansi"
        ]
    },
    "extra": {
        "laravel": {
            "dont-discover": []
        }
    },
    "config": {
        "optimize-autoloader": true,
        "preferred-install": "dist",
        "sort-packages": true,
        "allow-plugins": {
            "pestphp/pest-plugin": true,
            "php-http/discovery": true
        }
    },
    "minimum-stability": "stable",
    "prefer-stable": true
}

my typescript-transformer.php

<?php
/*
 * Copyright (c) 2023 La Maison Fantastique - All Rights Reserved
 */

declare(strict_types=1);

use Spatie\LaravelTypeScriptTransformer\Transformers\DtoTransformer;
use Spatie\LaravelTypeScriptTransformer\Transformers\SpatieStateTransformer;
use Spatie\TypeScriptTransformer\Collectors\DefaultCollector;
use Spatie\TypeScriptTransformer\Collectors\EnumCollector;
use Spatie\TypeScriptTransformer\Formatters\PrettierFormatter;
use Spatie\TypeScriptTransformer\Transformers\EnumTransformer;
use Spatie\TypeScriptTransformer\Transformers\InterfaceTransformer;
use Spatie\TypeScriptTransformer\Transformers\SpatieEnumTransformer;

return [
    /*
     * The paths where typescript-transformer will look for PHP classes
     * to transform, this will be the `app` path by default.
     */

    'auto_discover_types'       => [app_path('/../../../www/app')],

    /*
     * Collectors will search for classes in the `auto_discover_types` paths and choose the correct
     * transformer to transform them. By default, we include a DefaultCollector which will search
     * for @typescript annotated and ![TypeScript] attributed classes to transform.
     */

    'collectors'                => [
        DefaultCollector::class,
        EnumCollector::class,
    ],

    /*
     * Transformers take PHP classes(e.g., enums) as an input and will output
     * a TypeScript representation of the PHP class.
     */

    'transformers'              => [
        DtoTransformer::class,
        EnumTransformer::class,
        InterfaceTransformer::class,
        SpatieEnumTransformer::class,
        SpatieStateTransformer::class,
    ],

    /*
     * In your classes, you sometimes have types that should always be replaced
     * by the same TypeScript representations. For example, you can replace a
     * Datetime always with a string. You define these replacements here.
     */

    'default_type_replacements' => [
        // DateTime::class               => 'string',
        // DateTimeImmutable::class      => 'string',
        // Carbon\CarbonImmutable::class => 'string',
        // Carbon\Carbon::class          => 'string',
    ],

    // The package will write the generated TypeScript to this file.
    'output_file'               => resource_path('/../../../www/src/@types/generated.d.ts'),

    /*
     * When the package is writing types to the output file, a writer is used to
     * determine the format. By default, this is the `TypeDefinitionWriter`.
     * But you can also use the `ModuleWriter` or implement your own.
     */

    'writer'                    => Spatie\TypeScriptTransformer\Writers\ModuleWriter::class,

    /*
     * The generated TypeScript file can be formatted. We ship a Prettier formatter
     * out of the box: `PrettierFormatter` but you can also implement your own one.
     * The generated TypeScript will not be formatted when no formatter was set.
     */

    'formatter'                 => PrettierFormatter::class,

    /*
     * Enums can be transformed into types or native TypeScript enums, by default
     * the package will transform them to types.
     */

    'transform_to_native_enums' => false,
];

I deliberately targeted a project outside the scope of Laravel because I don't use it in my project and I didn't want to pollute it with a Laravel installation.

There should be a "Transformer order matters!" warning in the docs

I really hope I'm not blind here and I missed that warning but I feel like it'd be useful to specify somewhere in the docs that the order in which you specify which Transformers to use matters.

DtoTransformer before EnumTransformer

$config = TypeScriptTransformerConfig::create()
    ->autoDiscoverTypes(__DIR__ . '/../Contracts')
    ->transformToNativeEnums()
    ->transformers([
        DtoTransformer::class,
        EnumTransformer::class,
    ])
    ->outputFile(__DIR__ . '/../../assets/generated/types.d.ts')
;

The above PHP configuration results in DtoTransformer handling everything, including enums which then results in the wrong TypeScript being generated.

declare namespace App.Contracts {
    export type MapDefinition = {
        layers: { [key: string]: any };
        projection: [string, string];
        centerCoordinates: [number, number];
    };
    export type NodeType = {
        name: string;
        value: number;
    };
}

EnumTransformer before DtoTransformer

$config = TypeScriptTransformerConfig::create()
    ->autoDiscoverTypes(__DIR__ . '/../Contracts')
    ->transformToNativeEnums()
    ->transformers([
        EnumTransformer::class,
        DtoTransformer::class,
    ])
    ->outputFile(__DIR__ . '/../../assets/generated/types.d.ts')
;

The above configuration correctly lets the EnumTransformer act first and generate a correct TypeScript enum.

declare namespace App.Contracts {
    export enum NodeType { 'OutdoorPath' = 0, 'Hallway' = 1, 'Room' = 2, 'Stairs' = 3, 'Elevator' = 4 };
    export type MapDefinition = {
        layers: { [key: string]: any };
        projection: [string, string];
        centerCoordinates: [number, number];
    };
}

My ask

In retrospect, it makes complete sense that the order of transformers matters but it wasn't until I ran into this problem that I figured that out. I don't think the behavior should change but the docs should have a warning talking about that fact. I'd send a PR but I'm not sure where to best place that information.

But thank you for this library! It's been such a timesaver for my project! ❤️

Use arrays with PHP types

Right now we have to use something like this (please correct me if I'm wrong) to create array types:

  #[LiteralTypeScriptType('App.Http.Resources.Email[]|null')]
  public ?array $emails;

It would be great if we could reference PHP types directly and generate an array based on it.

how to include specific private properties

Hello,

i'm just trying your package and since now it looks really impressive
but now i have the following situation:
i have php-models, that have private properties BUT they are "accessible from public" (a small implementation with magic getters to only get the data loaded if needed)

is there a way (like [#Hidden] but the other way ^^) to tell your script to include them other then defining the whole typescript myself?

Pick up the `DataCollectionOf` attribute from spatie/laravel-data

Currently, when creating typescript definitions of spatie/laravel-data objects, it's required to add an docblock static the arrayable type of the property:

#[TypeScript]
class UserData extends Data {
    public function __construct(
        public string $name,
        /** @var PostData[] $posts */
        #[DataCollectionOf(PostData::class)]
        public DataCollection $posts,
    ) {}
}

It would be great if it was possible to remove the docblock there and infer the type from the DataCollectionOf attribute.

[BUG] Unresolved array-key type

I use spatie/laravel-data to trigger the bug

Example:

class Input extends BaseInput
{
    /**
     * @param  Collection<array-key, array-key>  $product_ids
     */
    public function __construct(
        public Collection $product_ids,
    ) {
    }
}
php artisan typescript:transform

# ouput error
# Could not transform type: array-key

See:

https://github.com/spatie/typescript-transformer/blob/main/src/Actions/TranspileTypeToTypeScriptAction.php#L42

If Type implements the \phpDocumentor\Reflection\PseudoType interface, it should call \phpDocumentor\Reflection\PseudoType::underlyingType() to return the correct Type

Use `undefined` instead of `null` by default

So, in TypeScript we use null very sparsely. Usually we use undefined in interfaces.

The difference is confusing because, well, it's JavaScript -- but basically null is when you want to have to explicitly declare a variable with no value, whereas undefined is for cases when a variable should not necessarily be initialized.

Aside from the theory, the practical difference is that you may omit declaring undefined union variables/properties, but you can't omit null union variables/properties, you have to declare them.

For instance, the following would be valid:

interface User {
  id?: number
  name: string
}

const user: User = {
  name: 'John'
}

While the following is not:

interface User {
  id: number | null
  name: string
}

const user: User = {
  name: 'John'
  // Error! `name` is missing
}

For this reason, I think that it would be better to convert nullable PHP types to use undefined instead of an explicit null.

I'm willing to PR but I didn't want to source-dive if you weren't going to agree with that opinion.

Generating Record-like types

I can't seem to find a way to generate a type like the following:

type FleetDetails = Record<Domain.Operations.Enums.AircraftType, Domain.Operations.Data.AircraftData[]>

I had to resort to something like that:

class FleetRadarData extends Data
{
    public function __construct(
        #[LiteralTypeScriptType('Record<Domain.Operations.Enums.AircraftType, Domain.Operations.Data.AircraftData[]>')]
        public readonly array $fleet,
        // ...
    ) {
    }
}

I don't think it's ideal because the string is not refactor-proof. I would love to be able to have an API for this using actual FQCNs, but I have no clue how I could describe the value part of the record being an array. For a simple key-value record, we could have something like this:

#[TypeScriptRecord(AircraftType::class, AircraftData::class)]

Maybe the solution would be to have a AircraftDataCollection class but I don't know how it could be typed without adding an attribute for it and specific support.

Any input?

Configure fallbackvalues other then any

It would be nice to be able to configure the fallback values for unknown symbols and mixed.

Currently unknown symbols/classes is always converted to any.

I'd love to be able to configure that value to be either unknown or maybe even {[key: string]: unknown} as we know it's a class/object.

Make transform of Enums to types or to native enums configurable on class level (using an attribute)

In most cases transforming PHP backed enums to type is preferable. However in some cases we need it as a Typescript Enum, for instance when we need to iterate it in order to generate a list of options. Currently it is either types or Enums, configurable using the TypeScriptTransformerConfig.

It would be very useful if the Enum and the Type transforming can be split in 2 Transformer classes, e.g. TypeEnumTransformer and NativeEnumTransformer. The EnumTransformer uses these and additionally you can use the Attribute #[TypeScriptTransformer(NativeEnumTransformer::class)] when you need a Typescript native enum.

Does the above make sense and are you interested in a PR?

How to deal with model properties?

Thanks for this great library as it worked pretty well so far for me. Though, now I face an issue when I define properties on my models:

  public int $id;
  public string $name;

which is correctly transformed to:

export type Team = {
    id: number;
    name: string;
    ...
}

However, PHP complains now:

Typed property App\Models\Team::$id must not be accessed before initialization

Any idea how I can avoid this error? I also tried to use default values for the properties but then again my models lose the actual database values.

If I define them like this I can avoid the PHP error but then the Typescript type is also nullable:

private ?string $name = NULL;

P.S.: I use PHP 8.0

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.