The ts-advanced-types
library is a collection of utility types designed to simplify and enhance TypeScript development. I started it four years ago to address common challenges such as excluding specific properties from objects, enforcing mutually exclusive type options, and defining tree-like data models, making your code more expressive and maintainable.
Built to streamline everyday TypeScript tasks, this library consolidates frequently used advanced types into a reusable package. By sharing these tools with the community, my goal is to help developers write cleaner, more reliable code and save time across projects.
Installation and setup
Setting up the ts-advanced-types
library is straightforward. Since the project is not transpiled, it directly exposes all types and utilities through its index.ts
file. This ensures a lightweight and hassle-free integration into your TypeScript project.
Steps to install:
1 Add the library to your project via npm or yarn:
npm install ts-advanced-types
# or
yarn add ts-advanced-types
2 Import the required types or utilities directly from the package:
import { TypeXOR, Without } from 'ts-advanced-types';
No additional configuration is needed—you’re ready to start using the library. This simplicity allows you to focus entirely on leveraging the provided tools to enhance your TypeScript workflows.
What's inside
The library includes a wide range of utility types and helpers that solve common TypeScript challenges. From enforcing stricter object constraints to creating mutually exclusive type options, each utility is designed to address specific use cases while improving code clarity and maintainability. These types are all ready to use and can seamlessly integrate into your existing projects, saving you time and effort
Utility types
-
Without<T, U>
Remove all properties from T that are assignable to U -
TypeXOR<T, U>
XOR of two types
Basic types
-
Falsy
JavaScript falsy types -
PrimitiveValidIndexSignature
JavaScript primitive types accepted as index signatures -
Primitive
JavaScript primitive non-falsy types -
Complex
JavaScript non-falsy types -
FalsyOrLiteral
JavaScript primitive types, including falsy values -
Document<T = Complex>
An object made of string keys and non-falsy values. To add new types to values, use theT
type parameter. -
JsonOrString
A JSON, as a string or as a parsed object or array
Advanced types/classes
-
TreeItem<T>
A generic tree -
EmptyConstructorOf<T>
A type that implements a constructor without arguments -
ClonableType<T>
A type that is clonable: it can be instantiated with a partial object
Utility functions
-
isFalsyOrSpaces(value)
Check if a value is falsy or a string with only spaces, ignoring number 0 -
withoutProps(obj, ...props)
Clones an object, optionally removing a list of properties -
equals(a, b)
Checks if two objects are equal using theequals
method or strict equality -
getMethods(obj)
List all methods of an object and its prototypes
Contribute and share your feedback
The library is an evolving project, and contributions from the developer community are always welcome. If you have ideas for new utility types, improvements, or discover any issues, feel free to open a pull request or report an issue on the GitHub repository.
Your feedback is invaluable in shaping the library to better serve TypeScript developers. If you’ve used ts-advanced-types
in your projects, I’d love to hear about your experience! Leave a comment on this post or share your thoughts directly on GitHub. Together, we can make TypeScript development even more efficient and enjoyable.
Top comments (3)
Hello. It is a good thing to hear that people are interested in TypeScript.
I checked out your code and it requires revision. Refer to this playground.
In this sample,
x.b
is now of typeundefined
when it was originallystring
:As I understand
Without
, it is the same as TS'Omit
, only Omit works as expected.Then I don't understand TypeXOR. What is "an exclusive OR" of two types? This one I cannot infer. If you can explain, it would be appreciated. The fact that is defined using
Without
makes matters worse because it is a faulty type to start with.The playground link seems to show a union of all properties of each of the typés, and when they coincide, the data types are unionized. Since I don't understand the type, I cannot rule this as correct or not.
Anyway, good idea. If you want to see some pretty cool tricks, including recursive ones, I recently re-wrote the TypeScript for wj-config. This is a hierarchical configuration package and its new TypeScript is powerful. You can read the TypeScript Wiki page.
Hi @webjose! Thanks for your valuable comment.
I started writing these types 8 years ago, and I pushed them to GitHub for the first time 2 years ago. Since then, a lot has changed in TypeScript, including the introduction of utility types that weren't available back then (only around version 3.5 did we start using them).
I completely agree that
Without
is essentially anOmit
. I will likely remove it from the library in the next version.Regarding
TypeXOR
, I also agree that the documentation could use some improvement for better clarity. However, I've faced challenges in clearly explaining its definition.For now, the best way I can explain it is through an old use case where I used it: an implementation signature where the single argument must be either one specific type or a completely different one.
I see. In that case, and if you're serious about contributing to the TypeScript community like this, what you must do now is make a full upgrade to the latest TypeScript. Once you do that and remove what is no longer needed, proceed to thoroughly document the remaining types, ideally with examples and use cases.
Once you do that, you can think about adding "unit tests" for the types using tsd. This way you'll have a robust foundation that can be built upon.
Good luck!