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.

Updated API

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.

Legacy API

Older versions of Sempiler provide a way to declare overloads and their respective implementations using the overloads(...) API.

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 overloads function:

Symbol Usage Notes
overloads(...bodies : delegate[]) : any Define overloads for the enclosing context Only valid as direct child of method or constructor body
delegate = (...args : any[]) => any Overload delegate signature Encapsulates all or part of an overload implementation

This might look daunting so let’s step through it in more detail.

Signatures

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 overloads:

Compat Sig

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:

Symbol Usage Notes
(...args : any) : any Definition of compatibility signature Return type can be omitted if all overloads are void

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.

Sharing

Any statements outside of the overloads construct will be shared across all overload implementations

Composition

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.