Skip to content

Instantly share code, notes, and snippets.

@achmedzhanov
Last active March 12, 2019 15:26
Show Gist options
  • Save achmedzhanov/a01fa80ff33c013044f7557fc85bde51 to your computer and use it in GitHub Desktop.
Save achmedzhanov/a01fa80ff33c013044f7557fc85bde51 to your computer and use it in GitHub Desktop.
type Eq<T1, T2> = Diff<T1, T2> extends never ? Diff<T2, T1> extends never ? 'equals' : 'c2' : 'c3';
type Diff<T, U> = T extends U ? never : T;
type PredicateGuard<I, O> = Eq<O, null> extends 'equal' ? null : O extends I ? O : never;
type PredicateGuard2<I, O> = O extends I ? null extends O ? O : O : never;
;
type Predicate<I, O extends I> = (i: I) => i is O;
type Predicate2<I, O extends I> = (i: I) => i is PredicateGuard2<I, O>;
const and = <I, O1 extends I, O2 extends I>(p1: Predicate<I, O1>, p2: Predicate<I, O2>) =>
(i: I): i is (O1 & O2) => p1(i) && p2(i);
const or = <I, O1 extends I, O2 extends I>(p1: Predicate<I, O1>, p2: Predicate<I, O2>) =>
(i: I): i is (O1 | O2) => p1(i) || p2(i);
type NotNull<T extends any | null> = T extends null ? never : T;
type Null<T> = T extends null ? null : never;
type Not<I, O extends I> = O extends null ? NotNull<O> : Diff<I, O>;
//type Eq<T1, T2>
//type Eq<T1, T2> = Diff<T1, T2> extends never ? Diff<T2, T1> extends never ? 'equals' : 'neq' : 'neq;
type et1 = Eq<string, number>;
type et2 = Eq<string, string>;
type et3 = Eq<string, string | number>;
type et4 = Eq<string | number, string>;
type et5 = Eq<null, null>;
type et6 = Eq<string | null, null>;
type c = Diff<string, string>;
type Not2<I, O extends I> = Eq<O, null> extends 'equals' ? NotNull<I> : Diff<I, O>;
// const not = <I, O extends I>(p: Predicate<I, O>) =>
// (i: I): i is (Not<I, O>) => !p(i);
const not2 = <I, O extends I>(p: Predicate<I, O>) =>
(i: I): i is (Not2<I, O>) => !p(i);
const not = <I, O extends I>(p: Predicate<I, O>) =>
(i: I): i is (Diff<I, O>) => !p(i);
const isNull = <I>(i: I | null ): i is null =>
i === null;
const isNull2 = <I>(i: Diff<I, null> | null): i is Null<I> =>
i === null;
const isUndefined = <I>(i: I | undefined): i is undefined =>
i === undefined;
const items = [ "foo", null, 123, undefined, true ];
const filtered = items.filter(and(not(isNull), not(isUndefined)));
const notNull2 = not2(isNull2);
const filtered2 = items.filter(notNull2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment