Skip to content

Commit a2d8247

Browse files
authored
docs(readme): Add TypeFactory usage (#66)
1 parent 5d84a9e commit a2d8247

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,75 @@ expect(14).toEndWith("4");
8181

8282
For a list of all matchers and extended documentation, please refer to the [API documentation](https://stackbuilders.github.io/assertive-ts/docs/build/).
8383

84+
### Type Factory 🏭
85+
86+
A great feature of AssertiveTS is the type safety across the API. But, what should you do if you want to check the value under test is of some specific type during runtime? The answer is simple, AssertiveTS provides a `.asType(TypeFactory)` method, where the [TypeFactory](https://stackbuilders.github.io/assertive-ts/docs/build/interfaces/TypeFactory.html) parameter lets you check for the specific type and narrow the assertion instance to a more specific one. To make things simpler, AssertiveTS provides [TypeFactories](https://stackbuilders.github.io/assertive-ts/docs/build/interfaces/StaticTypeFactories.html) for the basic types:
87+
88+
```ts
89+
import { expect, TypeFactories } from "@stackbuilders/assertive-ts";
90+
91+
expect(value)
92+
.asType(TypeFactories.String)
93+
.toBeEmpty();
94+
95+
expect(list)
96+
.asType(TypeFactories.array(TypeFactories.Number))
97+
.toHaveSameMembers([1, 2, 3, 4, 5]);
98+
```
99+
100+
If the built-in type factories are not enough to assert your specific type, you can always create your own factory. A `TypeFactory<S, A>` is nothing more than an object with 3 properties:
101+
102+
- `Factory: new(actual: S) => A` - The specific assertion constructor to return if the predicate is true. Where `S` is the actual value type, and `A` is the type of the assertion to return (`A` should extend from `Assertion<S>`).
103+
- `predicate(value: unknown): value is S` - A predicate function that checks if the value is of the expected type.
104+
- `typeName: string` - The name of the checked type. Used to make the assertion error message clearer.
105+
106+
So, using a custom `TypeFactory` can look like the following:
107+
108+
```ts
109+
interface Point3D {
110+
x: number;
111+
y: number;
112+
z: number;
113+
}
114+
115+
expect(maybePoint).asType({
116+
Factory: ObjectAssertion<Point3D>,
117+
predicate: (value): value is Point3D => {
118+
return typeof value === "object"
119+
&& value !== null
120+
&& "x" in value
121+
&& "y" in value
122+
&& "z" in value
123+
&& Object.values(value).every(v => typeof v === "number");
124+
},
125+
typeName: "Point3D"
126+
});
127+
```
128+
129+
### Handling TypeScript Unions
130+
131+
[Union types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types) are a TypeScript concept that is only applicable at type level. During runtime, the value can only be one of the types. For instance, if we say `const foo: number | string = ...`, at runtime `foo` will be either a `number` or a `string`. If you want to use a more specific assertion on a union type, you can use `.asType(..)` to first assert the expected type, and then move forward with more assertions:
132+
133+
```ts
134+
const foo: number | string = 5;
135+
136+
expect(foo)
137+
.asType(TypeFactories.Number)
138+
.toBePositive();
139+
```
140+
141+
### Help! The value can also be `null` or `undefined`
142+
143+
When a value can be also `null` or `undefined`, we're going over the same concept as [Union types](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#union-types). So if you want to make more specific assertions over a value that can be `null | undefined`, just use `.asType(..)` first:
144+
145+
```ts
146+
const bar: string | null | undefined = " ";
147+
148+
expect(bar)
149+
.asType(TypeFactories.String)
150+
.toBeBlank();
151+
```
152+
84153
## Test Runner Integration
85154

86155
- [Jest Integration](docs/jest-tutorial.md)

0 commit comments

Comments
 (0)