Skip to content

Commit

Permalink
Fixed #103
Browse files Browse the repository at this point in the history
  • Loading branch information
mattpocock committed Mar 8, 2023
1 parent 5505a09 commit 107dfc2
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 25 deletions.
25 changes: 25 additions & 0 deletions .changeset/empty-elephants-tell.md
@@ -0,0 +1,25 @@
---
"@total-typescript/ts-reset": minor
---

Changed the array.includes on readonly arrays to NOT be a type predicate. Before this change, this perfectly valid code would not behave correctly.

```ts
type Code = 0 | 1 | 2;
type SpecificCode = 0 | 1;

const currentCode: Code = 0;

// Create an empty list of subset type
const specificCodeList: ReadonlyArray<SpecificCode> = [];

// This will be false, since 0 is not in []
if (specificCodeList.includes(currentCode)) {
currentCode; // -> SpecificCode
} else {
// This branch will be entered, and ts will think z is 2, when it is actually 0
currentCode; // -> 2
}
```

Removing the type predicate brings ts-reset closer towards correctness.
15 changes: 0 additions & 15 deletions readme.md
Expand Up @@ -188,21 +188,6 @@ users.includes("bryan");

This means you can test non-members of the array safely.

It also makes `.includes` a type predicate, meaning you can use it to narrow wider types to a set enum:

```ts
import "@total-typescript/ts-reset/array-includes";

const users = ["matt", "sofia", "waqas"] as const;

const isUser = (input: string) => {
if (users.includes(input)) {
// input is narrowed to "matt" | "sofia" | "waqas"
console.log(input);
}
};
```

### Make `Set.has()` less strict

```ts
Expand Down
2 changes: 1 addition & 1 deletion src/entrypoints/array-includes.d.ts
Expand Up @@ -4,7 +4,7 @@ interface ReadonlyArray<T> {
includes(
searchElement: T | (TSReset.WidenLiteral<T> & {}),
fromIndex?: number,
): searchElement is T;
): boolean;
}

interface Array<T> {
Expand Down
9 changes: 0 additions & 9 deletions src/tests/array-includes.ts
Expand Up @@ -50,15 +50,6 @@ doNotExecute(async () => {
arr.includes({ a: 1 });
});

doNotExecute(async () => {
let arr = [1, 2, 3] as const;

let member = 1;
if (arr.includes(member)) {
type tests = [Expect<Equal<typeof member, 1 | 2 | 3>>];
}
});

doNotExecute(async () => {
const arr: Array<"1" | "2" | "3"> = ["1", "2", "3"];

Expand Down

0 comments on commit 107dfc2

Please sign in to comment.