From 107dfc2ebcc2cf221bebde086ab3499189fa44e1 Mon Sep 17 00:00:00 2001 From: Matt Pocock Date: Wed, 8 Mar 2023 15:59:40 +0000 Subject: [PATCH] Fixed #103 --- .changeset/empty-elephants-tell.md | 25 +++++++++++++++++++++++++ readme.md | 15 --------------- src/entrypoints/array-includes.d.ts | 2 +- src/tests/array-includes.ts | 9 --------- 4 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 .changeset/empty-elephants-tell.md diff --git a/.changeset/empty-elephants-tell.md b/.changeset/empty-elephants-tell.md new file mode 100644 index 0000000..b2c341e --- /dev/null +++ b/.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 = []; + +// 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. diff --git a/readme.md b/readme.md index 0126c98..8589a2a 100644 --- a/readme.md +++ b/readme.md @@ -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 diff --git a/src/entrypoints/array-includes.d.ts b/src/entrypoints/array-includes.d.ts index f50b61f..11eefa3 100644 --- a/src/entrypoints/array-includes.d.ts +++ b/src/entrypoints/array-includes.d.ts @@ -4,7 +4,7 @@ interface ReadonlyArray { includes( searchElement: T | (TSReset.WidenLiteral & {}), fromIndex?: number, - ): searchElement is T; + ): boolean; } interface Array { diff --git a/src/tests/array-includes.ts b/src/tests/array-includes.ts index 2b23a96..6bcb811 100644 --- a/src/tests/array-includes.ts +++ b/src/tests/array-includes.ts @@ -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>]; - } -}); - doNotExecute(async () => { const arr: Array<"1" | "2" | "3"> = ["1", "2", "3"];