Skip to content

Instantly share code, notes, and snippets.

@aztack
Created July 2, 2020 15:34
Show Gist options
  • Save aztack/a2359d86901800e8bfcd1d2e95a9f5b1 to your computer and use it in GitHub Desktop.
Save aztack/a2359d86901800e8bfcd1d2e95a9f5b1 to your computer and use it in GitHub Desktop.
Equal.ts
// https://stackoverflow.com/questions/53807517/how-to-test-if-two-types-are-exactly-the-same
// https://github.com/Microsoft/TypeScript/issues/27024
// https://github.com/microsoft/TypeScript/issues/37314#issuecomment-598459316
/*
type Equals<X,Y> =
(<T>() => T extends X ? true : false) extends
(<T>() => T extends Y ? true : false) ? true : false;
*/
type Equal<T, S> = [T] extends [S] ? ([S] extends [T] ? true : false) : false
type Base = {
x: symbol;
};
type Part1 = {
part1: number;
};
type Part2 = {
part2: string;
};
type NoneOrAll<T, Base, P1, P2> =
Equal<T, Base & P1 & P2> extends true
? T
: (Equal<T, Base> extends true
? T
: never);
// Ret1 to Ret5 are 'never's
type Ret1 = NoneOrAll<{part1: number, part2: string}, Base, Part1, Part2>;
type Ret2 = NoneOrAll<{part1: string}, Base, Part1, Part2>;
type Ret3 = NoneOrAll<{part2: string}, Base, Part1, Part2>;
type Ret4 = NoneOrAll<{x: symbol, part1: number}, Base, Part1, Part2>;
type Ret5 = NoneOrAll<{x: symbol, part2: string}, Base, Part1, Part2>;
type Ret6 = NoneOrAll<{x: symbol}, Base, Part1, Part2>; // {x: symbol}
type Ret7 = NoneOrAll<{x: symbol, part1: number, part2: string}, Base, Part1, Part2>; // {x: symbol, part1: number ,part2: string}
function f<T>(param: NoneOrAll<T, {name: string}, {age: number}, {sex: string}>) {}
f({name: 'jack'});
f({name: 'jack', age: 27, sex: 'male'});
f({name: 'jack', age: 27})
f({name: 'jack', sex: 'male'})
@aztack
Copy link
Author

aztack commented Jul 2, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment