Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate more type tests to TSTyche #1989

Merged
merged 3 commits into from Feb 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .prettierignore
Expand Up @@ -8,3 +8,7 @@ type-definitions/flow-tests/
!type-definitions/ts-tests/deepCopy.ts
!type-definitions/ts-tests/empty.ts
!type-definitions/ts-tests/es6-collections.ts
!type-definitions/ts-tests/exports.ts
!type-definitions/ts-tests/from-js.ts
!type-definitions/ts-tests/functional.ts
!type-definitions/ts-tests/groupBy.ts
6 changes: 5 additions & 1 deletion tstyche.config.json
Expand Up @@ -4,6 +4,10 @@
"**/type-definitions/ts-tests/covariance.ts",
"**/type-definitions/ts-tests/deepCopy.ts",
"**/type-definitions/ts-tests/empty.ts",
"**/type-definitions/ts-tests/es6-collections.ts"
"**/type-definitions/ts-tests/es6-collections.ts",
"**/type-definitions/ts-tests/exports.ts",
"**/type-definitions/ts-tests/from-js.ts",
"**/type-definitions/ts-tests/functional.ts",
"**/type-definitions/ts-tests/groupBy.ts"
]
}
125 changes: 96 additions & 29 deletions type-definitions/ts-tests/exports.ts
@@ -1,5 +1,6 @@
// Some tests look like they are repeated in order to avoid false positives.

import { expect, test } from 'tstyche';
import * as Immutable from 'immutable';
import {
List,
Expand All @@ -14,32 +15,98 @@ import {
Collection,
} from 'immutable';

List; // $ExpectType typeof List
Map; // $ExpectType typeof Map
OrderedMap; // $ExpectType typeof OrderedMap
OrderedSet; // $ExpectType typeof OrderedSet
// TODO: Turn on once https://github.com/Microsoft/dtslint/issues/19 is resolved.
Range; // $ ExpectType (start?: number | undefined, end?: number | undefined, step?: number | undefined) => Indexed<number>
Comment on lines -21 to -22
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Notice that few assertions were disabled by adding a space: // $ ExpectType instead of // $ExpectType. I think now they work as expected.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Range did change in 5.x in that way yes 😉

Repeat; // $ExpectType <T>(value: T, times?: number | undefined) => Indexed<T>
Seq; // $ExpectType typeof Seq
Set; // $ExpectType typeof Set
Stack; // $ExpectType typeof Stack
Collection; // $ExpectType typeof Collection
Collection.Set; // $ExpectType <T>(collection?: Iterable<T> | ArrayLike<T> | undefined) => Set<T>
Collection.Keyed; // $ ExpectType { <K, V>(collection: Iterable<[K, V]>): Keyed<K, V>; <V>(obj: { [key: string]: V; }): Keyed<string, V> }
Collection.Indexed; // $ExpectType <T>(collection?: Iterable<T> | ArrayLike<T> | undefined) => Indexed<T>

Immutable.List; // $ExpectType typeof List
Immutable.Map; // $ExpectType typeof Map
Immutable.OrderedMap; // $ExpectType typeof OrderedMap
Immutable.OrderedSet; // $ExpectType typeof OrderedSet
// TODO: Turn on once https://github.com/Microsoft/dtslint/issues/19 is resolved.
Immutable.Range; // $ ExpectType (start?: number | undefined, end?: number | undefined, step?: number | undefined) => Indexed<number>
Immutable.Repeat; // $ExpectType <T>(value: T, times?: number | undefined) => Indexed<T>
Immutable.Seq; // $ExpectType typeof Seq
Immutable.Set; // $ExpectType typeof Set
Immutable.Stack; // $ExpectType typeof Stack
Immutable.Collection; // $ExpectType typeof Collection
Immutable.Collection.Set; // $ExpectType <T>(collection?: Iterable<T> | ArrayLike<T> | undefined) => Set<T>
Immutable.Collection.Keyed; // $ ExpectType { <K, V>(collection: Iterable<[K, V]>): Keyed<K, V>; <V>(obj: { [key: string]: V; }): Keyed<string, V> }
Immutable.Collection.Indexed; // $ExpectType <T>(collection?: Iterable<T> | ArrayLike<T> | undefined) => Indexed<T>
test('named imports', () => {
expect(List).type.toEqual<typeof List>();

expect(Map).type.toEqual<typeof Map>();

expect(OrderedMap).type.toEqual<typeof OrderedMap>();

expect(OrderedSet).type.toEqual<typeof OrderedSet>();

expect(Range).type.toEqual<
(
start: number,
end: number,
step?: number | undefined
) => Seq.Indexed<number>
>();

expect(Repeat).type.toEqual<
<T>(value: T, times?: number | undefined) => Seq.Indexed<T>
>();

expect(Seq).type.toEqual<typeof Seq>();

expect(Set).type.toEqual<typeof Set>();

expect(Stack).type.toEqual<typeof Stack>();

expect(Collection).type.toEqual<typeof Collection>();

expect(Collection.Set).type.toEqual<
<T>(
collection?: Iterable<T> | ArrayLike<T> | undefined
) => Collection.Set<T>
>();

expect(Collection.Keyed).type.toEqual<{
<K, V>(collection?: Iterable<[K, V]> | undefined): Collection.Keyed<K, V>;
<V>(obj: { [key: string]: V }): Collection.Keyed<string, V>;
}>();

expect(Collection.Indexed).type.toEqual<
<T>(
collection?: Iterable<T> | ArrayLike<T> | undefined
) => Collection.Indexed<T>
>();
});

test('namespace import', () => {
expect(Immutable.List).type.toEqual<typeof Immutable.List>();

expect(Immutable.Map).type.toEqual<typeof Immutable.Map>();

expect(Immutable.OrderedMap).type.toEqual<typeof Immutable.OrderedMap>();

expect(Immutable.OrderedSet).type.toEqual<typeof Immutable.OrderedSet>();

expect(Immutable.Range).type.toEqual<
(
start: number,
end: number,
step?: number | undefined
) => Immutable.Seq.Indexed<number>
>();

expect(Immutable.Repeat).type.toEqual<
<T>(value: T, times?: number | undefined) => Immutable.Seq.Indexed<T>
>();

expect(Immutable.Seq).type.toEqual<typeof Immutable.Seq>();

expect(Immutable.Set).type.toEqual<typeof Immutable.Set>();

expect(Immutable.Stack).type.toEqual<typeof Immutable.Stack>();

expect(Immutable.Collection).type.toEqual<typeof Immutable.Collection>();

expect(Immutable.Collection.Set).type.toEqual<
<T>(
collection?: Iterable<T> | ArrayLike<T> | undefined
) => Immutable.Collection.Set<T>
>();

expect(Immutable.Collection.Keyed).type.toEqual<{
<K, V>(
collection?: Iterable<[K, V]> | undefined
): Immutable.Collection.Keyed<K, V>;
<V>(obj: { [key: string]: V }): Immutable.Collection.Keyed<string, V>;
}>();

expect(Immutable.Collection.Indexed).type.toEqual<
<T>(
collection?: Iterable<T> | ArrayLike<T> | undefined
) => Immutable.Collection.Indexed<T>
>();
});
59 changes: 26 additions & 33 deletions type-definitions/ts-tests/from-js.ts
@@ -1,49 +1,42 @@
import { fromJS, List, Map } from 'immutable';
import { expect, test } from 'tstyche';
import { fromJS, Collection, List, Map, MapOf } from 'immutable';

{
// fromJS
test('fromJs', () => {
expect(fromJS({}, (a: any, b: any) => b)).type.toEqual<
jdeniau marked this conversation as resolved.
Show resolved Hide resolved
Collection<unknown, unknown>
>();

// $ExpectType Collection<unknown, unknown>
fromJS({}, (a: any, b: any) => b);
expect(fromJS('abc')).type.toBeString();

// $ExpectType string
fromJS('abc');
expect(fromJS([0, 1, 2])).type.toEqual<List<number>>();

// $ExpectType List<number>
fromJS([0, 1, 2]);
expect(fromJS(List([0, 1, 2]))).type.toEqual<List<number>>();

// $ExpectType List<number>
fromJS(List([0, 1, 2]));
expect(fromJS({ a: 0, b: 1, c: 2 })).type.toEqual<
Map<'b' | 'a' | 'c', number>
>();

// $ExpectType Map<"b" | "a" | "c", number>
fromJS({a: 0, b: 1, c: 2});
expect(fromJS(Map({ a: 0, b: 1, c: 2 }))).type.toEqual<
MapOf<{ a: number; b: number; c: number }>
>();

// $ExpectType MapOf<{ a: number; b: number; c: number; }>
fromJS(Map({a: 0, b: 1, c: 2}));
expect(fromJS([{ a: 0 }])).type.toEqual<List<Map<'a', number>>>();

// $ExpectType List<Map<"a", number>>
fromJS([{a: 0}]);
expect(fromJS({ a: [0] })).type.toEqual<Map<'a', List<number>>>();

// $ExpectType Map<"a", List<number>>
fromJS({a: [0]});
expect(fromJS([[[0]]])).type.toEqual<List<List<List<number>>>>();

// $ExpectType List<List<List<number>>>
fromJS([[[0]]]);

// $ExpectType Map<"a", Map<"b", Map<"c", number>>>
fromJS({a: {b: {c: 0}}});
}

{
// fromJS in an array of function
expect(fromJS({ a: { b: { c: 0 } } })).type.toEqual<
Map<'a', Map<'b', Map<'c', number>>>
>();
});

test('fromJS in an array of function', () => {
const create = [(data: any) => data, fromJS][1];

// $ExpectType any
create({ a: 'A' });
expect(create({ a: 'A' })).type.toBeAny();

const createConst = ([(data: any) => data, fromJS] as const)[1];

// $ExpectType Map<"a", string>
createConst({ a: 'A' });
}
expect(createConst({ a: 'A' })).type.toEqual<Map<'a', string>>();
});
109 changes: 44 additions & 65 deletions type-definitions/ts-tests/functional.ts
@@ -1,84 +1,63 @@
import {
get,
has,
set,
remove,
update,
} from 'immutable';
import { expect, test } from 'tstyche';
import { get, has, set, remove, update } from 'immutable';

{
// get
test('get', () => {
expect(get([1, 2, 3], 0)).type.toEqual<number | undefined>();

// $ExpectType number | undefined
get([1, 2, 3], 0);
expect(get([1, 2, 3], 0, 'a')).type.toEqual<number | 'a'>();

// $ExpectType number | "a"
get([1, 2, 3], 0, 'a');
expect(get({ x: 10, y: 20 }, 'x')).type.toEqual<number | undefined>();

// $ExpectType number | undefined
get({ x: 10, y: 20 }, 'x');
expect(get({ x: 10, y: 20 }, 'z', 'missing')).type.toEqual<
number | 'missing'
>();
});

// $ExpectType number | "missing"
get({ x: 10, y: 20 }, 'z', 'missing');
}
test('has', () => {
expect(has([1, 2, 3], 0)).type.toBeBoolean();

{
// has
expect(has({ x: 10, y: 20 }, 'x')).type.toBeBoolean();
});

// $ExpectType boolean
has([1, 2, 3], 0);
test('set', () => {
expect(set([1, 2, 3], 0, 10)).type.toEqual<number[]>();

// $ExpectType boolean
has({ x: 10, y: 20 }, 'x');
}
expect(set([1, 2, 3], 0, 'a')).type.toRaiseError();

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere .not.toBeCallableWith() matcher should be used instead of .toRaiseError(). Keeping it as it was, but I will come back after implementing .toBeCallableWith():

expect(set).type.not.toBeCallableWith([1, 2, 3], 0, 'a');

{
// set
expect(set([1, 2, 3], 'a', 0)).type.toRaiseError();

// $ExpectType number[]
set([1, 2, 3], 0, 10);
expect(set({ x: 10, y: 20 }, 'x', 100)).type.toEqual<{
x: number;
y: number;
}>();

// $ExpectError
set([1, 2, 3], 0, 'a');
expect(set({ x: 10, y: 20 }, 'x', 'a')).type.toRaiseError();
});

// $ExpectError
set([1, 2, 3], 'a', 0);
test('remove', () => {
expect(remove([1, 2, 3], 0)).type.toEqual<number[]>();

// $ExpectType { x: number; y: number; }
set({ x: 10, y: 20 }, 'x', 100);
expect(remove({ x: 10, y: 20 }, 'x')).type.toEqual<{
x: number;
y: number;
}>();
});

// $ExpectError
set({ x: 10, y: 20 }, 'x', 'a');
}
test('update', () => {
expect(update([1, 2, 3], 0, (v: number) => v + 1)).type.toEqual<number[]>();

{
// remove
expect(update([1, 2, 3], 0, 1)).type.toRaiseError();

// $ExpectType number[]
remove([1, 2, 3], 0);
expect(update([1, 2, 3], 0, (v: string) => v + 'a')).type.toRaiseError();

// $ExpectType { x: number; y: number; }
remove({ x: 10, y: 20 }, 'x');
}
expect(update([1, 2, 3], 'a', (v: number) => v + 1)).type.toRaiseError();

{
// update
expect(update({ x: 10, y: 20 }, 'x', (v: number) => v + 1)).type.toEqual<{
x: number;
y: number;
}>();

// $ExpectType number[]
update([1, 2, 3], 0, (v: number) => v + 1);

// $ExpectError
update([1, 2, 3], 0, 1);

// $ExpectError
update([1, 2, 3], 0, (v: string) => v + 'a');

// $ExpectError
update([1, 2, 3], 'a', (v: number) => v + 1);

// $ExpectType { x: number; y: number; }
update({ x: 10, y: 20 }, 'x', (v: number) => v + 1);

// $ExpectError
update({ x: 10, y: 20 }, 'x', (v: string) => v + 'a');
}
expect(
update({ x: 10, y: 20 }, 'x', (v: string) => v + 'a')
).type.toRaiseError();
});