From 5f61c48b3ab43bb8047319c18bd4b2e8328e6274 Mon Sep 17 00:00:00 2001 From: Benedikt Franke Date: Fri, 26 Nov 2021 15:41:35 +0100 Subject: [PATCH] feat: add NonEmptyArray and specialized implementation of last() --- src/array.test.ts | 41 ++++++++++++++++++++++++++++++++++++++++- src/array.ts | 13 +++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/src/array.test.ts b/src/array.test.ts index 3b12eae..d28a6e1 100644 --- a/src/array.test.ts +++ b/src/array.test.ts @@ -1,4 +1,31 @@ -import { containSameValues, insertIf, withoutIndex } from './array'; +import { + containSameValues, + insertIf, + isNonEmptyArray, + last, + NonEmptyArray, + withoutIndex, +} from './array'; + +describe('NonEmptyArray', () => { + it('can be proven to be non-empty', () => { + const array = [1]; + + // @ts-expect-error intentionally wrong + let nonEmptyArray: NonEmptyArray = []; + + // @ts-expect-error intentionally wrong + nonEmptyArray = array; + + if (isNonEmptyArray(array)) { + nonEmptyArray = array; + } + + expect(isNonEmptyArray(nonEmptyArray)).toBe(true); + expect(isNonEmptyArray([undefined])).toBe(true); + expect(isNonEmptyArray([])).toBe(false); + }); +}); describe('withoutIndex', () => { it('handles empty arrays', () => { @@ -40,3 +67,15 @@ describe('insertIf', () => { expect(insertIf(false, 1, 2)).toEqual([]); }); }); + +describe('last', () => { + it('returns the last element of an array', () => { + const array: NonEmptyArray = [1, 2]; + const actual: number = last(array); + expect(actual).toEqual(2); + }); + + it('returns undefined for empty arrays', () => { + expect(last([])).toEqual(undefined); + }); +}); diff --git a/src/array.ts b/src/array.ts index e39f3b4..063f29f 100644 --- a/src/array.ts +++ b/src/array.ts @@ -1,5 +1,11 @@ import { isEqual, sortBy } from 'lodash'; +export type NonEmptyArray = Array & { 0: T }; + +export function isNonEmptyArray(value: Array): value is NonEmptyArray { + return value.length > 0; +} + /** * Return a new array that does not contain the item at the specified index. */ @@ -39,3 +45,10 @@ export function insertIf( ): Array { return condition ? elements : []; } + +export function last>( + array: A, +): A extends NonEmptyArray ? T : T | undefined { + // @ts-expect-error too magical + return array[array.length - 1]; +}