ts-xor
Compose custom types containing mutually exclusive keys, using this generic Typescript helper type.
Last updated a year ago by maninak .
MIT · Repository · Bugs · Original npm · Tarball · package.json
$ cnpm install ts-xor 
SYNC missed versions from official npm registry.

ts-xor

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

Description

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

Installation

In your typescript powered, npm project, run:

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

Examples

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

NPM

This library is published on NPM.

Licence

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

Contributing

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

Current Tags

  • 1.0.8                                ...           latest (a year ago)

9 Versions

  • 1.0.8                                ...           a year ago
  • 1.0.7                                ...           a year ago
  • 1.0.6                                ...           2 years ago
  • 1.0.5                                ...           2 years ago
  • 1.0.4                                ...           2 years ago
  • 1.0.3                                ...           2 years ago
  • 1.0.2                                ...           2 years ago
  • 1.0.1                                ...           2 years ago
  • 1.0.0                                ...           2 years ago

Copyright 2014 - 2017 © taobao.org |