This document describes the experimental operator overloading and function overload dispatch features added to this TypeScript fork.
Operator overloading in this TypeScript fork allows user-defined types to provide custom behavior for operators such as +, -, *, /, comparison, and bitwise operators. The implementation works by transforming operator expressions into method calls on the operand types, if those methods exist.
This feature is enabled with the compiler option operatorOverloading.
The following mappings are used to resolve operator overloads:
Binary Operators:
| Operator | Left Method | Right Method |
|---|---|---|
+ |
add |
add |
- |
sub |
rsub |
* |
mul |
mul |
/ |
div |
rdiv |
% |
mod |
rmod |
** |
pow |
rpow |
& |
and |
and |
| |
or |
or |
^ |
xor |
xor |
<< |
shl |
|
>> |
shr |
|
>>> |
asr |
|
< |
lt |
gt |
<= |
le |
ge |
> |
gt |
lt |
>= |
ge |
le |
== |
eq |
eq |
!= |
ne |
ne |
Unary Operators:
| Operator | Method |
|---|---|
++ |
inc |
-- |
dec |
+ |
pos |
- |
neg |
~ |
inv |
! |
not |
For comparison, the method cmp may be used, with the result compared to zero (e.g., a.cmp(b) < 0).
When the compiler encounters an operator expression (like a + b), it:
- Uses the above mapping to determine the method name(s) to check.
- Checks if the left operand's type has a method with that name (using the type checker).
- If found, verifies the method signature matches the expected operand types.
- If valid, rewrites the operator expression as a method call (e.g.,
a.add(b)). - For some operators, also checks the right operand for a corresponding method (e.g.,
rsubfor right-side subtraction). - For comparison operators, may also check for a
cmpmethod and rewrite as a comparison against zero (e.g.,a.cmp(b) < 0). - If no suitable method is found, the operator behaves as usual.
class Point {
x: number;
y: number;
add(other: Point): Point {
return new Point(this.x + other.x, this.y + other.y);
}
}
const p1 = new Point(1, 2);
const p2 = new Point(3, 4);
const p3 = p1 + p2; // Transformed to p1.add(p2) if 'add' exists- Operator overloads are resolved at compile time by checking for matching methods on operand types.
- Only supported operators (see implementation mapping) can be overloaded.
- If no matching method is found, the operator behaves as in standard TypeScript.
Function overload dispatch in this fork enables selection of function implementations based on argument types. It works by generating mangled function names for each overloaded implementation, and rewriting calls to use the correct implementation. Functions (or methods) with multiple signatures but only a single implementation work as before.
This feature is enabled with the compiler option functionOverloadDispatch.
For each overloaded function or method, a mangled name is generated using the base name and a suffix encoding the parameter types:
nfor numbersfor stringbfor booleanifor bigintufor undefined0for nullvfor voidafor anyxfor unknownA...for array typesT...for tuple typesF...for function typesO...for object types (with class/interface name if available)U...for union typesI...for intersection types
For example, foo(x: number) becomes foo$n, and foo(x: string, y: number[]) becomes foo$sAn.
At call sites, the compiler determines the argument types and rewrites the call to the correct mangled function name.
function foo(x: number): number { /* ... */ }
function foo(x: string): string { /* ... */ }
foo(42); // Transformed to foo$n(42)
foo("hi"); // Transformed to foo$s("hi")- Overload resolution is performed at compile time using type information.
- Function and method implementations are renamed to unique mangled names.
- See
src/compiler/transformers/functionOverloadDispatch.tsfor implementation details.
When both operator overloading and function overload dispatch are enabled, operator methods themselves can be overloaded and mangled. For example, you can provide multiple overloads for an operator method such as add, and the correct overload will be selected and mangled based on the operand types.
Example:
class Point {
x: number;
y: number;
add(other: Point): Point { /* ... */ }
add(other: number): Point { /* ... */ }
}
const p = new Point(1, 2);
p + p; // Transformed to p.add$OPoint(p)
p + 5; // Transformed to p.add$n(5)This allows for highly flexible operator overloading, with dispatch based on operand types.
Please report issues or suggestions via the repository's issue tracker.
View the original TypeScript README on GitHub
TypeScript is a language for application-scale JavaScript. TypeScript adds optional types to JavaScript that support tools for large-scale JavaScript applications for any browser, for any host, on any OS. TypeScript compiles to readable, standards-based JavaScript. Try it out at the playground, and stay up to date via our blog and Twitter account.
Find others who are using TypeScript at our community page.
For the latest stable version:
npm install -D typescriptFor our nightly builds:
npm install -D typescript@nextThere are many ways to contribute to TypeScript.
- Submit bugs and help us verify fixes as they are checked in.
- Review the source code changes.
- Engage with other TypeScript users and developers on StackOverflow.
- Help each other in the TypeScript Community Discord.
- Join the #typescript discussion on Twitter.
- Contribute bug fixes.
This project has adopted the Microsoft Open Source Code of Conduct. For more information see the Code of Conduct FAQ or contact opencode@microsoft.com with any additional questions or comments.
For details on our planned features and future direction, please refer to our roadmap.