Master TypeScript Function Overloads with the overload-func Library

This article explains how to use the overload-func library to separate implementation from overload signatures in TypeScript, providing runtime matching, full type checking, and flexible configuration while keeping the codebase clean and maintainable.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Master TypeScript Function Overloads with the overload-func Library

Preface

When building generic libraries that need multiple overload signatures, TypeScript's native overloads can become messy. This article introduces a runtime‑based solution that separates implementation while preserving full type checking.

Installation

npm install overload-func

Usage

Define overload signatures with createOverloadedFunction and add implementations via addImple. The library matches arguments at runtime and returns correctly typed results.

import { createOverloadedFunction } from 'overload-func';

const func = createOverloadedFunction<[ (a: string) => string, (a: number, b: number) => boolean ]>();

func.addImple('string', a => a);
func.addImple('number', 'number', (a, b) => a > b);

Calling func('hello') yields a string, while func(1, 2) yields a boolean, with TypeScript providing proper inference and errors for mismatched calls.

Built‑in Types

string → string number → number boolean → boolean null → null undefined → undefined symbol → symbol bigint → bigint function → Function array → any[] date → Date map → Map set → Set weakmap → WeakMap weakset → WeakSet regexp → RegExp promise → Promise error → Error object →

object

Advanced Guide

Options such as allowMultiple let a single overload have several implementations; the last implementation’s return value is used.

const func = createOverloadedFunction<[ (a: string) => string, (a: number, b: number) => boolean ]>({ allowMultiple: true });

func.addImple('string', a => { console.log('first implementation'); return a; });
func.addImple('string', a => { console.log('second implementation'); return a.toUpperCase(); });

const r1 = func('hello'); // HELLO

Extended types can be created with createExtendType to add custom keys for addImple, enabling overloads based on class instances.

class Teacher { constructor(public name: string, public salary: number) {} }
class Student { constructor(public name: string, public score: number) {} }

const extendType = createExtendType({ teacher: Teacher, student: Student });

const test = createOverloadedFunction<[ (t: Teacher) => string, (s: Student) => number ], typeof extendType>({ extendType });

test.addImple('teacher', t => t.name);
test.addImple('student', s => s.name.length);

const res1 = test(new Teacher('John', 5000)); // 'John'
const res2 = test(new Student('Alice', 90)); // 5

The library also supports overloads that use this in class methods, requiring regular functions (not arrow functions) for correct this typing.

const test = createOverloadedFunction<[ (this: Test, n: number) => boolean, (this: Test, n: string, s: string) => string ]>();

test.addImple('number', function (n) { return n > this.count; });

test.addImple('string', 'string', function (n, m) { return n + m; });

class Test { count = 10; test = test; }
const t = new Test();
console.log(t.test(8)); // false
console.log(t.test('pknk', 'lll')); // 'pknklll'

Conclusion

The overload‑func package provides a lightweight runtime implementation while delivering comprehensive TypeScript typings, improving developer experience for complex overload scenarios.

TypeScripttype safetyfunction overloadgeneric libraryoverload-funcruntime overload
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.