tstyche 6.0.0-rc.0 → 6.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +27 -24
  2. package/dist/tstyche.js +15 -22
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -13,7 +13,7 @@ TSTyche is a type testing tool for TypeScript. It ships with `describe()` and `t
13
13
 
14
14
  ## Helpers
15
15
 
16
- If you are used to test JavaScript, a simple type test file should look familiar:
16
+ If you are used to testing, a type test should look familiar:
17
17
 
18
18
  ```ts
19
19
  import { expect, test } from "tstyche";
@@ -30,42 +30,33 @@ test("isSameLength", () => {
30
30
  });
31
31
  ```
32
32
 
33
- To organize, debug and plan tests TSTyche has:
33
+ To group and organize tests, TSTyche has:
34
34
 
35
35
  - `test()`, `it()` and `describe()` helpers,
36
36
  - with `.only`, `.skip` and `.todo` run mode flags.
37
37
 
38
38
  ## Assertions
39
39
 
40
- The assertions can be used to write type tests (like in the above example) or mixed in your unit tests:
40
+ The `expect` style assertions can check either the inferred type of an expression (as in the example above) or a type directly:
41
41
 
42
42
  ```ts
43
- import assert from "node:assert";
44
- import test from "node:test";
45
- import * as tstyche from "tstyche";
43
+ import { expect } from "tstyche";
46
44
 
47
- function toMilliseconds(value: number) {
48
- if (typeof value === "number" && !Number.isNaN(value)) {
49
- return value * 1000;
50
- }
45
+ type AsyncProps<T> = {
46
+ [K in keyof T]+?: T[K] | Promise<T[K]>;
47
+ };
51
48
 
52
- throw new Error("Not a number");
53
- }
54
-
55
- test("toMilliseconds", () => {
56
- const sample = toMilliseconds(10);
49
+ type WithLoading<T> = T & { loading: boolean };
57
50
 
58
- assert.equal(sample, 10_000);
59
- tstyche.expect(sample).type.toBe<number>();
60
-
61
- // Will pass as a type test and not throw at runtime
62
- tstyche.expect(toMilliseconds).type.not.toBeCallableWith("20");
63
- });
51
+ expect<WithLoading<AsyncProps<{ query: string }>>>().type.toBe<{
52
+ query?: string | Promise<string>;
53
+ loading: boolean;
54
+ }>();
64
55
  ```
65
56
 
66
57
  Here is the list of all matchers:
67
58
 
68
- - `.toBe()`, `.toBeAssignableFrom()`, `.toBeAssignableTo()` compare types or types of expression,
59
+ - `.toBe()`, `.toBeAssignableFrom()`, `.toBeAssignableTo()` compare types or type of expressions,
69
60
  - `.toAcceptProps()` checks the type of JSX component props,
70
61
  - `.toBeApplicable` ensures that the decorator function can be applied,
71
62
  - `.toBeCallableWith()` checks whether a function is callable with the given arguments,
@@ -74,13 +65,23 @@ Here is the list of all matchers:
74
65
 
75
66
  ## Runner
76
67
 
77
- The `tstyche` command is the heart of TSTyche. For example, it can select test files by path, filter tests by name and to run the tests against specific versions of TypeScript:
68
+ The `tstyche` command is the heart of TSTyche. It allows you to select test files by path, filter tests by name and run them against specific versions of TypeScript:
78
69
 
79
70
  ```shell
80
71
  tstyche query-params --only multiple --target '>=5.6'
81
72
  ```
82
73
 
83
- This simple! (And it has watch mode too.)
74
+ It is that simple! Actually, TSTyche does even more:
75
+
76
+ - checks messages of errors suppressed by `// @ts-expect-error`,
77
+ - generates type tests from a data table,
78
+ - runs tests in watch mode.
79
+
80
+ ## Try It Out
81
+
82
+ Try TSTyche online on StackBlitz:
83
+
84
+ [![Open in StackBlitz][starter-badge]][starter-url]
84
85
 
85
86
  ## Documentation
86
87
 
@@ -98,3 +99,5 @@ Visit [tstyche.org](https://tstyche.org) to view the full documentation.
98
99
  [install-size-url]: https://packagephobia.com/result?p=tstyche
99
100
  [coverage-badge]: https://badgen.net/codacy/coverage/a581ca5c323a455886b7bdd9623c4ec8
100
101
  [coverage-url]: https://app.codacy.com/gh/tstyche/tstyche/coverage/dashboard
102
+ [starter-badge]: https://developer.stackblitz.com/img/open_in_stackblitz.svg
103
+ [starter-url]: https://tstyche.org/new
package/dist/tstyche.js CHANGED
@@ -4550,9 +4550,9 @@ class ToAcceptProps {
4550
4550
  }
4551
4551
  }
4552
4552
 
4553
- function containsInstantiableType(target, compiler) {
4553
+ function containsInstantiable(target, compiler) {
4554
4554
  return ("types" in target &&
4555
- target.types.some((type) => type.flags & compiler.TypeFlags.InstantiableNonPrimitive));
4555
+ target.types.some((type) => type.flags & compiler.TypeFlags.Instantiable));
4556
4556
  }
4557
4557
  function getIndexSignatures(type, compiler, typeChecker) {
4558
4558
  if (type.flags & compiler.TypeFlags.Intersection) {
@@ -4587,9 +4587,6 @@ function getTargetSymbol(symbol, compiler) {
4587
4587
  function isCheckFlagSet(symbol, flag, compiler) {
4588
4588
  return !!(symbol.flags & compiler.SymbolFlags.Transient && symbol.links.checkFlags & flag);
4589
4589
  }
4590
- function isSymbolFromDefaultLibrary(symbol, program) {
4591
- return !!symbol.declarations?.every((declaration) => program.isSourceFileDefaultLibrary(declaration.getSourceFile()));
4592
- }
4593
4590
 
4594
4591
  function getParameterFactsFromTuple(type, position, compiler) {
4595
4592
  return {
@@ -4677,13 +4674,11 @@ class SeenService {
4677
4674
  class Structure {
4678
4675
  #compiler;
4679
4676
  #compilerOptions;
4680
- #program;
4681
4677
  #seen = new SeenService();
4682
4678
  #typeChecker;
4683
4679
  constructor(compiler, program) {
4684
4680
  this.#compiler = compiler;
4685
4681
  this.#compilerOptions = program.getCompilerOptions();
4686
- this.#program = program;
4687
4682
  this.#typeChecker = program.getTypeChecker();
4688
4683
  }
4689
4684
  #compareMaybeNullish(a, b) {
@@ -4713,7 +4708,7 @@ class Structure {
4713
4708
  return true;
4714
4709
  }
4715
4710
  }
4716
- if (containsInstantiableType(a, this.#compiler) || containsInstantiableType(b, this.#compiler)) {
4711
+ if (containsInstantiable(a, this.#compiler) || containsInstantiable(b, this.#compiler)) {
4717
4712
  return false;
4718
4713
  }
4719
4714
  if ((a.flags & b.flags) | this.#compiler.TypeFlags.StructuredType) {
@@ -4791,9 +4786,8 @@ class Structure {
4791
4786
  }
4792
4787
  compareObjects(a, b) {
4793
4788
  if (a.objectFlags & b.objectFlags & this.#compiler.ObjectFlags.Reference) {
4794
- const isSame = this.compareTypeReferences(a, b);
4795
- if (isSame != null) {
4796
- return isSame;
4789
+ if (!((a.objectFlags | b.objectFlags) & this.#compiler.ObjectFlags.ClassOrInterface)) {
4790
+ return this.compareTypeReferences(a, b);
4797
4791
  }
4798
4792
  }
4799
4793
  return this.compareStructuredTypes(a, b);
@@ -4805,21 +4799,20 @@ class Structure {
4805
4799
  }
4806
4800
  return false;
4807
4801
  }
4808
- if ((a.objectFlags | b.objectFlags) & this.#compiler.ObjectFlags.Class) {
4802
+ if (!this.compare(a.target, b.target)) {
4809
4803
  return this.compareStructuredTypes(a, b);
4810
4804
  }
4811
- if (a.symbol !== b.symbol) {
4812
- if (isSymbolFromDefaultLibrary(a.symbol, this.#program) || isSymbolFromDefaultLibrary(b.symbol, this.#program)) {
4813
- return false;
4814
- }
4815
- return;
4816
- }
4817
4805
  const aTypeArguments = this.#typeChecker.getTypeArguments(a);
4818
4806
  const bTypeArguments = this.#typeChecker.getTypeArguments(b);
4819
4807
  if (aTypeArguments.length !== bTypeArguments.length) {
4820
4808
  return false;
4821
4809
  }
4822
- return aTypeArguments.every((type, i) => this.compare(type, bTypeArguments[i]));
4810
+ for (let i = 0; i < aTypeArguments.length; i++) {
4811
+ if (!this.compare(aTypeArguments[i], bTypeArguments[i])) {
4812
+ return false;
4813
+ }
4814
+ }
4815
+ return true;
4823
4816
  }
4824
4817
  compareTuples(a, b) {
4825
4818
  if (a.target.readonly !== b.target.readonly) {
@@ -5049,8 +5042,8 @@ class Structure {
5049
5042
  return type.regularType;
5050
5043
  }
5051
5044
  if (type.flags & this.#compiler.TypeFlags.UnionOrIntersection) {
5052
- const candidateType = this.#normalize(type.types[0]);
5053
- if (type.types.every((t) => this.compare(this.#normalize(t), candidateType))) {
5045
+ const candidateType = type.types[0];
5046
+ if (type.types.every((t) => this.compare(t, candidateType))) {
5054
5047
  return candidateType;
5055
5048
  }
5056
5049
  }
@@ -5912,7 +5905,7 @@ class FileRunner {
5912
5905
  class Runner {
5913
5906
  #eventEmitter = new EventEmitter();
5914
5907
  #resolvedConfig;
5915
- static version = "6.0.0-rc.0";
5908
+ static version = "6.0.1";
5916
5909
  constructor(resolvedConfig) {
5917
5910
  this.#resolvedConfig = resolvedConfig;
5918
5911
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "6.0.0-rc.0",
3
+ "version": "6.0.1",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",