DEV Community

Discussion on: Advanced TypeScript Exercises - Answer 3

Collapse
 
koalayt profile image
He Yuntao

I find another solution:

// Detail see: https://stackoverflow.com/questions/42123407/does-typescript-support-mutually-exclusive-types
type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
type XOR<T, U> = (T | U) extends object ? (Without<T, U> & U) | (Without<U, T> & T) : T | U;

class BothString {
    constructor(public a: string, public b: string) {}
}

class BothNumber {
    constructor(public a: number, public b: number) {}
}

type BothStringOrNumber = XOR<BothString, BothNumber>

// Now the function body is simple
function f (input: BothStringOrNumber) {
    if (input instanceof BothString) {
        return input.a + ':' + input.b;
    } else {
        return input.a + input.b
    }
}

// Behave as expect
f({a: 2, b: 3}); // correct usage
f({a: 1, b: 'a'}); // error!
f({a: 'a', b: 2}); // error!
f({a: 'a', b: 'b'}) // correct usage

Enter fullscreen mode Exit fullscreen mode