From c667c9b72adaa2b152192767338ec88dd6b532fa Mon Sep 17 00:00:00 2001 From: Scott J Dickerson Date: Thu, 28 Sep 2023 17:35:51 -0400 Subject: [PATCH] Setup TS to know about `.filter(Boolean)` With `array-filter-Boolean`, TS will select a better Array.filter() override so this kind of thing will work automatically without an explicit type casting: ```js const a: Array = ["A", "B", undefined, null, "C"]; const b: string[] = a.filter(Boolean); ``` See https://www.karltarvas.com/typescript-array-filter-boolean.html See https://stackoverflow.com/a/51390763/1470607 Signed-off-by: Scott J Dickerson --- .../application-form/application-form.tsx | 2 +- client/src/app/utils/model-utils.tsx | 6 ++-- client/types/array-filter-Boolean.ts | 28 +++++++++++++++++++ 3 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 client/types/array-filter-Boolean.ts diff --git a/client/src/app/pages/applications/components/application-form/application-form.tsx b/client/src/app/pages/applications/components/application-form/application-form.tsx index 476175bea0..909dc0eda4 100644 --- a/client/src/app/pages/applications/components/application-form/application-form.tsx +++ b/client/src/app/pages/applications/components/application-form/application-form.tsx @@ -597,7 +597,7 @@ const useApplicationFormData = ({ // Fetch data const { tagCategories } = useFetchTagCategories(); const tags = useMemo( - () => tagCategories.flatMap((tc) => tc.tags).filter(Boolean) as Tag[], + () => tagCategories.flatMap((tc) => tc.tags).filter(Boolean), [tagCategories] ); diff --git a/client/src/app/utils/model-utils.tsx b/client/src/app/utils/model-utils.tsx index 5488be59b6..1136fad3ee 100644 --- a/client/src/app/utils/model-utils.tsx +++ b/client/src/app/utils/model-utils.tsx @@ -229,7 +229,7 @@ export const toRef = ( export const toRefs = ( source: Iterable ): Array | undefined => - !source ? undefined : ([...source].map(toRef).filter(Boolean) as Ref[]); + !source ? undefined : [...source].map(toRef).filter(Boolean); /** * Take an array of source items that look like a `Ref`, find the first one that matches @@ -271,11 +271,11 @@ export const matchItemsToRefs = ( ): Array | undefined => !matchValues ? undefined - : (matchValues + : matchValues .map((toMatch) => !toMatch ? undefined : items.find((item) => matchOperator(itemMatchFn(item), toMatch)) ) .map(toRef) - .filter(Boolean) as Ref[]); + .filter(Boolean); diff --git a/client/types/array-filter-Boolean.ts b/client/types/array-filter-Boolean.ts new file mode 100644 index 0000000000..741e1c984b --- /dev/null +++ b/client/types/array-filter-Boolean.ts @@ -0,0 +1,28 @@ +/** + * Fixes https://github.com/microsoft/TypeScript/issues/16655 for `Array.prototype.filter()` + * For example, using the fix the type of `bar` is `string[]` in the below snippet as it should be. + * + * const foo: (string | null | undefined)[] = []; + * const bar = foo.filter(Boolean); + * + * For related definitions, see https://github.com/microsoft/TypeScript/blob/master/src/lib/es5.d.ts + * + * Original licenses apply, see + * - https://github.com/microsoft/TypeScript/blob/master/LICENSE.txt + * - https://stackoverflow.com/help/licensing + */ + +/** See https://stackoverflow.com/a/51390763/1470607 */ +type Falsy = false | 0 | "" | null | undefined; + +interface Array { + /** + * Returns the elements of an array that meet the condition specified in a callback function. + * @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array. + * @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value. + */ + filter( + predicate: BooleanConstructor, + thisArg?: any + ): Exclude[]; +}