NOTE Some source languages do not provide an elegant way to achieve overloading. If your chosen source language inherently supports it then you can proceed with defining overloads as normal.
Sempiler now supports normal overloading (ie. without the legacy
overloads API) even in source languages that inherently do not permit duplicate function names (such as TypeScript):
This provides for cleaner source code and a better developer experience, particularly when implementing multiple overloads of the same method or constructor.
NOTE The legacy
overloads API has been removed starting from this version.
Older versions of Sempiler provide a way to declare overloads and their respective implementations using the
If you are working in a language like TypeScript function overloading is not inherently supported. Instead you often have to parse the argument types in the actual function body to simulate overloading which is ugly and error prone.
Sempiler defines a globally available
||Define overloads for the enclosing context||Only valid as direct child of method or constructor body|
||Overload delegate signature||Encapsulates all or part of an overload implementation|
This might look daunting so let’s step through it in more detail.
In TypeScript we can already stack signatures on a method or constructor declaration.
This is helpful to us because the type checker will give us the correct Intellisense support for the matching signature at call sites.
Unfortunately it still leaves the ugly aforementioned argument parsing problem, but we can get around this by using
- The last declared signature in this example is known as a compatibility signature or (compat sig), and has a special meaning
- We pass a lambda function for each declared signature (except for the compat sig if present)
- The lambda signature must match the corresponding declared signature it maps to
- The lambda signature DOES NOT need to include any fakeywords mentioned in the declared signature
- The order that you pass the lambdas to
overloadsmust match the order of the declared signatures
Overload signatures often have no common representation between them - their type parameters, parameters or return types can not be represented as one signature.
It is as loose as possible because the strong typing for overloads comes from their lambda signatures. This type safety makes lambdas a great mechanism for providing the distinct function bodies.
If we are in a context that requires us to provide a functioin body, TypeScript expects the last declared signature to sufficiently represent all overload signatures. We can get around that with the compatibility signature:
||Definition of compatibility signature||Return type can be omitted if all overloads are
By placing this signature last, we provide a workaround for the type checker to be happy.
The compatibility signature is NOT emitted so you should not provide any implementations for it. It is transient.
Any statements outside of the
overloads construct will be shared across all overload implementations
Subsequent calls to
overloads inside the same scope will be combined in the sempiled output. This allows you to compose shared logic and logic specific to a particular overload.