TypeScript icon, indicating that this package has built-in type declarations

    1.0.8 • Public • Published


    Compose custom types containing mutually exclusive keys, using this generic Typescript helper type.

    npm version Build Status Greenkeeper badge Last commit

    Licence Downloads per week NPM dependent packages Github stars

    Minified and gzipped size Dependencies


    Typescript's union operator (|) allows combining two types A and B, into a superset type C which can contain all the members of both A and B.

    But sometimes the requirements dictate that we combine two types with mutually exclusive members. So take the members A.a and B.b. Given type C = A | B then we want to impose the restriction that we can set either C.a or C.b but never both AND at least one of the two!

    Typescript does not support this feature out of the box yet.

    This package introduces the new type XOR. You can use XOR to compose your own custom types with mutually exclusive members.

    XOR effectively implements the logical XOR operator from boolean algebra as defined by the following truth table:

    A B Result
    0 0 0
    0 1 1
    1 0 1
    1 1 0


    In your typescript powered, npm project, run:

    npm install -D ts-xor # yarn add -D ts-xor 


    A simple example

    In any typescript file you can just have:

    import { XOR } from 'ts-xor'
    interface A {
      a: string
    interface B {
      b: string
    let A_XOR_B: XOR<A, B>
    A_XOR_B = { a: '' }         // OK
    A_XOR_B = { b: '' }         // OK
    A_XOR_B = { a: '', b: '' }  // fails
    A_XOR_B = {}                // fails

    A real-life example

    Say that we have the following specification for the response of a weather forecast service:

    1. A weather forecast object always contains the id and station members
    2. A weather forecast object always contains either a member rain or a member snow, but never both at the same time.
    3. The rain or snow members are objects containing additional forecast accuracy data
    4. The rain or snow member always contain either a member 1h or a member 3h with a number value, but never both keys at the same time.
    import { XOR } from 'ts-xor'
    type ForecastAccuracy = XOR<{ '1h': number }, { '3h': number }>
    interface WeatherForecastBase {
      id: number
      station: string
    interface WeatherForecastWithRain extends WeatherForecastBase {
      rain: ForecastAccuracy
    interface WeatherForecastWithSnow extends WeatherForecastBase {
      snow: ForecastAccuracy
    type WeatherForecast = XOR<WeatherForecastWithRain, WeatherForecastWithSnow>
    const ourTestCase: WeatherForecast = {
      id: 123456,
      station: 'Acropolis Weather Reporter',
      // rain: { '1h': 1 },           // OK
      // rain: { '2h': 1 },           // fails
      // rain: { '3h': 1 },           // OK
      // rain: {},                    // fails
      // rain: { '1h': 1 , '3h': 3 }, // fails
      // lel: { '3h': 1 },            // fails
      // snow: { '3h': 1 },           // OK
      // when BOTH `rain` AND `snow` are declared, compilation fails

    Tests and Coverage

    The library ts-xor is fully covered with acceptance and mutation tests against the typescript compiler itself. The tests can be found inside the test folder.

    To run all tests locally, execute the following command inside your git-cloned ts-xor folder:

    npm test


    This library is published on NPM.


    Distributed under the MIT license. See LICENSE.md for more information.


    This project's commits comply with the Conventional Commits guidelines.

    1. Fork it (https://github.com/maninak/ts-xor/fork)
    2. Create your feature/fix branch (git checkout -b feat/foobar)
    3. Commit your changes (git commit -am 'feat(foobar): add support for foobar tricks')
    4. Push to the branch (git push origin feat/fooBar)
    5. Create a new Pull Request


    npm i ts-xor

    DownloadsWeekly Downloads






    Unpacked Size

    8.91 kB

    Total Files


    Last publish


    • maninak