You can try this https://github.com/amol-/dukpy which is a combo of Python and C and offers limited TypeScript compilation capabilities.
In general you might be better off using a native TypeScript compiler and call it from Python instead
Answer from Philippe Ombredanne on Stack ExchangeVideos
» pip install dukpy
Hey TS community on Reddit
I am looking for some help / guidance & would be grateful for any helpful advice
So there's a project that i came across that is written in mostly typescript. However, i want to use a flask/python based front-end for it, so i need to know how can i make an API / package in Python that can call/execute typescript code from the project ?
I am not sure if my technical vocabulary is entirely correct, but basically i am looking to integrate a Typescript project in a Python front-end; by making calls to Typescript commands / calls from Python.
Would appreciate any and all help in this regard !
EDIT : I am not very proficient in Javascript or Typescript
» pip install ts2python
Of course, people have reservations against using either. However, my question is only regarding which is better of the two.
Would the answer be different if,
The compiler targets -> ARM v. NASM
The compiler targets -> LLVM IR
C (like how, for example Nim, does things)
I don't use my own parser/lexer, and use libraries
And no, the built in "type hints" don't count.
It would be great to use a statically compiled language in the world of Python.
TypeScript's approach would be perfect. Build type definitions for all your dependencies. Support strict mode or not, allowing you to buck the system if needed.
Do Python debuggers support source maps? Probably not, considering there are no transpilers (that I'm aware of).
Python unlike JavaScript is strong typed so the need for something like typescript is lessened.
Instead you can use type annotations and either the mypy linter or your ides linter to enforce the typing.
In effect, this gives you all the same benefits as typescript without much overhead.
There is http://mypy-lang.org/
It seems to me that the only thing missing is something similar to typescripts interfaces.
While tools like MyPy, Pyright, and Pylance have significantly improved static typing in Python, they don't offer the same level of rigor and performance as fully compiled languages.
Imagine a language that compiles to Python bytecode, providing:
Strong static typing: catching errors early and improving code reliability.
Performance benefits: through compilation and optimizations.
Advanced language features: such as algebraic data types, pattern matching, and better concurrency support.
But what are the trade-offs? Would such a language be compatible with the vast Python ecosystem? Could a compiler achieve the same performance as the CPython interpreter? And would the added complexity outweigh the benefits for many Python developers?
I'm curious to hear your thoughts. Have you ever experimented with statically typed Python dialects or considered the potential benefits and drawbacks of a more rigid type system?
For the code completion and type hinting in IDEs, just add static typing for the Person and Address classes and you are already good to go. Assuming you use the latest python3.6, here's a rough equivalent of the typescript classes from your example:
# spam.py
from typing import Optional, Sequence
class Address:
street: str
housenumber: int
housenumber_postfix: Optional[str]
def __init__(self, street: str, housenumber: int,
housenumber_postfix: Optional[str] = None) -> None:
self.street = street
self.housenumber = housenumber
self.housenumber_postfix = housenumber_postfix
class Person:
name: str
adresses: Sequence[Address]
def __init__(self, name: str, adresses: Sequence[str]) -> None:
self.name = name
self.adresses = adresses
person = Person('Joe', [
Address('Sesame', 1),
Address('Baker', 221, housenumber_postfix='b')
]) # type: Person
I suppose the boilerplate you mentioned emerges when adding the class constructors. This is indeed inavoidable. I would wish default constructors were generated at runtime when not declared explicitly, like this:
class Address:
street: str
housenumber: int
housenumber_postfix: Optional[str]
class Person:
name: str
adresses: Sequence[Address]
if __name__ == '__main__':
alice = Person('Alice', [Address('spam', 1, housenumber_postfix='eggs')])
bob = Person('Bob', ()) # a tuple is also a sequence
but unfortunately you have to declare them manually.
Edit
As Michael0x2a pointed out in the comment, the need for default constructors is made avoidable in python3.7 which introduced a @dataclass decorator, so one can indeed declare:
@dataclass
class Address:
street: str
housenumber: int
housenumber_postfix: Optional[str]
@dataclass
class Person:
name: str
adresses: Sequence[Address]
and get the default impl of several methods, reducing the amount of boilerplate code. Check out PEP 557 for more details.
I guess you could see stub files that can be generated from your code, as some kind of interface files:
$ stubgen spam # stubgen tool is part of mypy package
Created out/spam.pyi
The generated stub file contains the typed signatures of all non-private classes and functions of the module without implementation:
# Stubs for spam (Python 3.6)
#
# NOTE: This dynamically typed stub was automatically generated by stubgen.
from typing import Optional, Sequence
class Address:
street: str
housenumber: int
housenumber_postfix: Optional[str]
def __init__(self, street: str, housenumber: int, housenumber_postfix: Optional[str]=...) -> None: ...
class Person:
name: str
adresses: Sequence[Address]
def __init__(self, name: str, adresses: Sequence[str]) -> None: ...
person: Person
These stub files are also recognized by IDEs and if your original module is not statically typed, they will use the stub file for type hints and code completion.
A TypeScript interface describes a JavaScript object. Such an object is analogous to a Python dictionary with well-known string keys, which is described by a TypedDict.
TypeScript interface example
For example the TypeScript interface:
interface Address {
street: string;
housenumber: number;
}
will describe JavaScript objects like:
var someAddress = {
street: 'SW Gemini Dr.',
housenumber: 9450,
};
Python TypedDict example
The equivalent Python TypedDict:
from typing import TypedDict
class Address(TypedDict):
street: str
housenumber: int
will describe Python dictionaries like:
some_address = {
'street': 'SW Gemini Dr.',
'housenumber': 9450,
}
# or equivalently:
some_address = dict(
street='SW Gemini Dr.',
housenumber=9450,
)
These dictionaries can be serialized to/from JSON trivially and will conform to the analogous TypeScript interface type.
Note: If you are using Python 2 or older versions of Python 3, you may need to use the older function-based syntax for TypedDict:
from mypy_extensions import TypedDict
Address = TypedDict('Address', {
'street': str,
'housenumber': int,
})
Alternatives
There are other ways in Python to represent structures with named properties.
Data classes, available in Python 3.7, have read-write keys. However they cannot be serialized to/from JSON automatically.
from dataclasses import dataclass
@dataclass
class Address:
street: str
housenumber: int
my_address = Address(
street='SW Gemini Dr.',
housenumber=9450,
)
Named tuples are cheap and have read-only keys. They also cannot be serialized to/from JSON automatically.
from typing import NamedTuple
class Address(NamedTuple):
street: str
housenumber: int
my_address = Address(
street='SW Gemini Dr.',
housenumber=9450,
)
Simple namespaces, available in Python 3.3, are similar to data classes but are not very well known.
from types import SimpleNamespace
class Address(SimpleNamespace):
street: str
housenumber: int
my_address = Address(
street='SW Gemini Dr.',
housenumber=9450,
)
attrs is a long-standing third-party library that is similar to data classes but with many more features. attrs is recognized by the mypy typechecker.
import attrs
@attr.s(auto_attribs=True)
class Address:
street: str
housenumber: int
my_address = Address(
street='SW Gemini Dr.',
housenumber=9450,
)