Skip to content

Commit

Permalink
docs: toEqualTypeOf vs toMatchTypeOf (#31)
Browse files Browse the repository at this point in the history
* build(typescript): use typescript 3.9rc

* docs: toEqualTypeOf vs toMatchTypeOf

this uses the new `// @ts-expect-error` directive

* docs: more .not examples

* docs: to -> with
  • Loading branch information
mmkal committed May 7, 2020
1 parent 050b572 commit b5f192a
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 19 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@
"mock-fs": "^4.11.0",
"prettier": "^2.0.2",
"read-pkg-up": "^7.0.1",
"typescript": "^3.7.4"
"typescript": "^3.9.1-rc"
}
}
47 changes: 40 additions & 7 deletions packages/expect-type/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ The `expectTypeOf` method takes a single argument, or a generic parameter. Neith
### Features

<!-- codegen:start {preset: markdownFromTests, source: src/__tests__/index.test.ts} -->
Check that two objects have equivalent types to `.toEqualTypeOf`:
Check that two objects have equivalent types with `.toEqualTypeOf`:

```typescript
expectTypeOf({a: 1}).toEqualTypeOf({a: 1})
Expand All @@ -70,25 +70,58 @@ expectTypeOf({a: 1}).toEqualTypeOf({a: 1})
expectTypeOf({a: 1}).toEqualTypeOf({a: 2})
```

`.toMatchTypeOf` checks that an object "matches" a type - that is, it has all the expected properties with correct types. This is similar to jest's `.toMatchObject`:
When there's no instance/runtime variable for the expected type, you can use generics:

```typescript
expectTypeOf({a: 1}).toEqualTypeOf<{a: number}>()
```

`.toEqualTypeOf` fails on extra properties:

```typescript
// @ts-expect-error
expectTypeOf({a: 1, b: 1}).toEqualTypeOf({a: 1})
```

To allow for extra properties, use `.toMatchTypeOf`. This checks that an object "matches" a type. This is similar to jest's `.toMatchObject`:

```typescript
expectTypeOf({a: 1, b: 1}).toMatchTypeOf({a: 1})
```

When there's no instance/runtime variable for the expected type, you can use generics:
Another example of the difference between `.toMatchTypeOf` and `.toEqualTypeOf`, using generics. `.toMatchTypeOf` can be used for "is-a" relationships:

```typescript
expectTypeOf({a: 1}).toEqualTypeOf<{a: number}>()
expectTypeOf({a: 1, b: 1}).toMatchTypeOf<{a: number}>()
type Fruit = {type: 'Fruit'; edible: boolean}
type Apple = {type: 'Fruit'; name: 'Apple'; edible: true}

expectTypeOf<Apple>().toMatchTypeOf<Fruit>()

// @ts-expect-error
expectTypeOf<Fruit>().toMatchTypeOf<Apple>()

// @ts-expect-error
expectTypeOf<Apple>().toEqualTypeOf<Fruit>()
```

Assertions can be inverted:
Assertions can be inverted with `.not`:

```typescript
expectTypeOf({a: 1}).not.toMatchTypeOf({b: 1})
```

`.not` can be easier than relying on `// @ts-expect-error`:

```typescript
type Fruit = {type: 'Fruit'; edible: boolean}
type Apple = {type: 'Fruit'; name: 'Apple'; edible: true}

expectTypeOf<Apple>().toMatchTypeOf<Fruit>()

expectTypeOf<Fruit>().not.toMatchTypeOf<Apple>()
expectTypeOf<Apple>().not.toEqualTypeOf<Fruit>()
```

Catch any/unknown/never types:

```typescript
Expand Down Expand Up @@ -126,7 +159,7 @@ expectTypeOf<1 | null>().toBeNullable()
expectTypeOf<1 | undefined | null>().toBeNullable()
```

Most assertions can be inverted with `.not`:
More `.not` examples:

```typescript
expectTypeOf(1).not.toBeUnknown()
Expand Down
41 changes: 34 additions & 7 deletions packages/expect-type/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,53 @@
import {expectTypeOf} from '..'

test('Check that two objects have equivalent types to `.toEqualTypeOf`', () => {
test('Check that two objects have equivalent types with `.toEqualTypeOf`', () => {
expectTypeOf({a: 1}).toEqualTypeOf({a: 1})
})

test('`.toEqualTypeOf` succeeds for objects with different values, but the same type', () => {
expectTypeOf({a: 1}).toEqualTypeOf({a: 2})
})

test('`.toMatchTypeOf` checks that an object "matches" a type - that is, it has all the expected properties with correct types. This is similar to jest\'s `.toMatchObject`', () => {
test("When there's no instance/runtime variable for the expected type, you can use generics", () => {
expectTypeOf({a: 1}).toEqualTypeOf<{a: number}>()
})

test('`.toEqualTypeOf` fails on extra properties', () => {
// @ts-expect-error
expectTypeOf({a: 1, b: 1}).toEqualTypeOf({a: 1})
})

test('To allow for extra properties, use `.toMatchTypeOf`. This checks that an object "matches" a type. This is similar to jest\'s `.toMatchObject`', () => {
expectTypeOf({a: 1, b: 1}).toMatchTypeOf({a: 1})
})

test("When there's no instance/runtime variable for the expected type, you can use generics", () => {
expectTypeOf({a: 1}).toEqualTypeOf<{a: number}>()
expectTypeOf({a: 1, b: 1}).toMatchTypeOf<{a: number}>()
test('Another example of the difference between `.toMatchTypeOf` and `.toEqualTypeOf`, using generics. `.toMatchTypeOf` can be used for "is-a" relationships', () => {
type Fruit = {type: 'Fruit'; edible: boolean}
type Apple = {type: 'Fruit'; name: 'Apple'; edible: true}

expectTypeOf<Apple>().toMatchTypeOf<Fruit>()

// @ts-expect-error
expectTypeOf<Fruit>().toMatchTypeOf<Apple>()

// @ts-expect-error
expectTypeOf<Apple>().toEqualTypeOf<Fruit>()
})

test('Assertions can be inverted', () => {
test('Assertions can be inverted with `.not`', () => {
expectTypeOf({a: 1}).not.toMatchTypeOf({b: 1})
})

test('`.not` can be easier than relying on `// @ts-expect-error`', () => {
type Fruit = {type: 'Fruit'; edible: boolean}
type Apple = {type: 'Fruit'; name: 'Apple'; edible: true}

expectTypeOf<Apple>().toMatchTypeOf<Fruit>()

expectTypeOf<Fruit>().not.toMatchTypeOf<Apple>()
expectTypeOf<Apple>().not.toEqualTypeOf<Fruit>()
})

test('Catch any/unknown/never types', () => {
expectTypeOf<unknown>().toBeUnknown()
expectTypeOf<any>().toBeAny()
Expand Down Expand Up @@ -52,7 +79,7 @@ test('Nullable types', () => {
expectTypeOf<1 | undefined | null>().toBeNullable()
})

test('Most assertions can be inverted with `.not`', () => {
test('More `.not` examples', () => {
expectTypeOf(1).not.toBeUnknown()
expectTypeOf(1).not.toBeAny()
expectTypeOf(1).not.toBeNever()
Expand Down
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8099,10 +8099,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=

typescript@^3.7.4:
version "3.7.4"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19"
integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw==
typescript@^3.9.1-rc:
version "3.9.1-rc"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.1-rc.tgz#81d5a5a0a597e224b6e2af8dffb46524b2eaf5f3"
integrity sha512-+cPv8L2Vd4KidCotqi2wjegBZ5n47CDRUu/QiLVu2YbeXAz78hIfcai9ziBiNI6JTGTVwUqXRug2UZxDcxhvFw==

uglify-js@^3.1.4:
version "3.6.3"
Expand Down

0 comments on commit b5f192a

Please sign in to comment.