Skip to content

Commit

Permalink
Clean up types of set a little bit
Browse files Browse the repository at this point in the history
  • Loading branch information
jmeistrich committed Nov 21, 2023
1 parent 898df3b commit d131e19
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 72 deletions.
14 changes: 6 additions & 8 deletions src/observableTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type ArrayOverrideFnNames =
| 'map'
| 'sort';

type ObservableComputed<T = any> = Readonly<Observable<T>>;
type ObservableComputed<T = any> = Readonly<ObservableNode<T>>;
type ObservableComputedTwoWay<T, T2> = Observable<T> & MutableObservableBase<T2, T2>;

type MakeReadonlyInner<T> = Omit<T, keyof MutableObservableBase<any, any>>;
Expand Down Expand Up @@ -78,13 +78,10 @@ interface ImmutableObservableBase<T> {
}

interface MutableObservableBase<T, T2> {
set(
value:
| RemoveObservables<T & T2>
| ((prev: RemoveObservables<T & T2>) => RemoveObservables<T & T2>)
| Promise<RemoveObservables<T & T2>>
| Observable<RemoveObservables<T & T2>>,
): Observable<T>;
set(value: RemoveObservables<T & T2>): Observable<T>;
set(value: (prev: RemoveObservables<T & T2>) => RemoveObservables<T & T2>): Observable<T>;
set(value: Promise<RemoveObservables<T & T2>>): Observable<T>;
set(value: Observable<RemoveObservables<T & T2>>): Observable<T>;
delete(): void;
}

Expand Down Expand Up @@ -165,6 +162,7 @@ type ObservableNode<T, NT = NonNullable<T>> = [NT] extends [never] // means that
: ObservableObject<T>;

type Simplify<T> = { [K in keyof T]: T[K] } & {};

type Observable<T = any> = ObservableNode<T>; // & {};

type ObservableReadable<T = any> = ImmutableObservableBase<T>;
Expand Down
111 changes: 47 additions & 64 deletions tests/types.test.ts
Original file line number Diff line number Diff line change
@@ -1,71 +1,54 @@
import { expectTypeOf } from 'expect-type';
import { Observable, ObservableComputed, ObservableComputedTwoWay } from '../src/observableTypes';
import { observable } from '../src/observable';

describe('Types', () => {
// describe('observable', () => {
// it('optional object return type when no argument is passed', () => {
// function noArgsObjectType() {
// return observable<{ foo: number }>();
// }

// type ObservableFn = ReturnType<typeof noArgsObjectType>;
// expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<{ foo: number } | undefined>();
// });

// it('optional return type when no argument is passed', () => {
// function noArgs() {
// return observable<string>();
// }

// type ObservableFn = ReturnType<typeof noArgs>;
// expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<string | undefined>();
// });

// it('optional return type when optional argument is passed', () => {
// function withOptionalArg(something?: string) {
// return observable(something);
// }

// type ObservableFn = ReturnType<typeof withOptionalArg>;
// expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<string | undefined>();
// });

// it('return type with promise info when promise is passed', () => {
// function withPromise() {
// return observable(Promise.resolve('foo'));
// }

// type ObservableFn = ReturnType<typeof withPromise>;
// expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<string & PromiseInfo>();
// });

// it('optional return type with promise info when promise with optional value is passed', () => {
// function withOptionalPromiseValue(something?: Promise<string>) {
// return observable(something);
// }

// type ObservableFn = ReturnType<typeof withOptionalPromiseValue>;
// expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<(string & PromiseInfo) | undefined>();
// });

// it('issue #151', () => {
// type ObservableFn = ReturnType<
// typeof observable<{
// optional?: { foo: string };
// nullable: { foo: string } | null;
// }>
// >;

// expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<{
// optional?: { foo: string };
// nullable: { foo: string } | null;
// }>();

// // Note that if a parent is nullable, the child is optional (undefined)
// expectTypeOf<ObservableFn['nullable']['foo']['get']>().returns.toEqualTypeOf<string | undefined>();
// expectTypeOf<ObservableFn['optional']['foo']['get']>().returns.toEqualTypeOf<string | undefined>();
// });
// });
describe('observable', () => {
it('optional object return type when no argument is passed', () => {
function noArgsObjectType() {
return observable<{ foo: number }>();
}

type ObservableFn = ReturnType<typeof noArgsObjectType>;
expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<{ foo: number } | undefined>();
});

it('optional return type when no argument is passed', () => {
function noArgs() {
return observable<string>();
}

type ObservableFn = ReturnType<typeof noArgs>;
expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<string | undefined>();
});

it('optional return type when optional argument is passed', () => {
function withOptionalArg(something?: string) {
return observable(something);
}

type ObservableFn = ReturnType<typeof withOptionalArg>;
expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<string | undefined>();
});

it('issue #151', () => {
type ObservableFn = ReturnType<
typeof observable<{
optional?: { foo: string };
nullable: { foo: string } | null;
}>
>;

expectTypeOf<ObservableFn['get']>().returns.toEqualTypeOf<{
optional?: { foo: string };
nullable: { foo: string } | null;
}>();

// Note that if a parent is nullable, the child is optional (undefined)
expectTypeOf<ObservableFn['nullable']['foo']['get']>().returns.toEqualTypeOf<string | undefined>();
expectTypeOf<ObservableFn['optional']['foo']['get']>().returns.toEqualTypeOf<string | undefined>();
});
});

describe('Observable', () => {
describe('with any', () => {
Expand Down

0 comments on commit d131e19

Please sign in to comment.