Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/major-nights-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"std": minor
---

feat: Add `equalsOneOf` utility

6 changes: 6 additions & 0 deletions .changeset/salty-kiwis-give.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"std": minor
---

feat: Update `strings` API to return the matched string for `startsWithOneOf` and `endsWithOneOf`

5 changes: 1 addition & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@
"typedoc-material-theme": "^1.4.0"
},
"pnpm": {
"onlyBuiltDependencies": [
"@biomejs/biome",
"esbuild"
]
"onlyBuiltDependencies": ["@biomejs/biome", "esbuild"]
}
}
15 changes: 11 additions & 4 deletions src/ts/strings.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import { describe, expect, it } from 'vitest';
import * as strings from './strings';

describe('equalsOneOf', () => {
it('correctly identifies a string that equals one of the provided strings', () => {
expect(strings.equalsOneOf('aa', ['aa', 'ba'])).toBe('aa');
expect(strings.equalsOneOf('aa', ['ba', 'ca'])).toBe(undefined);
});
});

describe('startsWithOneOf', () => {
it('correctly identifies a string that starts with one of the provided strings', () => {
expect(strings.startsWithOneOf('aab', ['aa', 'ba'])).toBe(true);
expect(strings.startsWithOneOf('aab', ['ba', 'ca'])).toBe(false);
expect(strings.startsWithOneOf('aab', ['aa', 'ba'])).toBe('aa');
expect(strings.startsWithOneOf('aab', ['ba', 'ca'])).toBe(undefined);
});
});

describe('endsWithOneOf', () => {
it('correctly identifies a string that ends with one of the provided strings', () => {
expect(strings.endsWithOneOf('baa', ['aa', 'ca'])).toBe(true);
expect(strings.endsWithOneOf('baa', ['ab', 'ac'])).toBe(false);
expect(strings.endsWithOneOf('baa', ['aa', 'ca'])).toBe('aa');
expect(strings.endsWithOneOf('baa', ['ab', 'ac'])).toBe(undefined);
});
});

Expand Down
55 changes: 43 additions & 12 deletions src/ts/strings.ts
Original file line number Diff line number Diff line change
@@ -1,41 +1,72 @@
/** Returns true if `str` starts with one of the provided `strings`.
/** Returns the string that matches the string (if it exits). Great for matching string union types.
*
* @param str
* @param strings
* @returns
*
* ## Usage
* ```ts
* startsWithOneOf('ab', 'a', 'c'); // true
* startsWithOneOf('cc', 'a', 'b'); // false
* const methods = ['GET', 'PUT', 'POST', 'PATCH', 'DELETE'] as const;
*
* const methodStr: string = 'GET';
*
* const method = equalsOneOf(methodStr, methods);
*
* if (method) {
* // if method was just a string this would be a type error
* methods.includes(method)
* }
* ```
*/
export function equalsOneOf<T extends string>(str: string, strings: readonly T[]): T | undefined {
for (const s of strings) {
if (s === str) return s;
}

return undefined;
}

/** Returns the matched prefix for the string (if it exists). Great for matching string union types.
*
* @param str
* @param strings
* @returns
*
* ## Usage
* ```ts
* startsWithOneOf('ab', 'a', 'c'); // 'a'
* startsWithOneOf('cc', 'a', 'b'); // undefined
* ```
*/
export function startsWithOneOf(str: string, strings: string[]): boolean {
export function startsWithOneOf<T extends string>(
str: string,
strings: readonly T[]
): T | undefined {
for (const s of strings) {
if (str.startsWith(s)) return true;
if (str.startsWith(s)) return s;
}

return false;
return undefined;
}

/** Returns true if `str` starts with one of the provided `strings`.
/** Returns the matched suffix for the string (if it exists). Great for matching string union types.
*
* @param str
* @param strings
* @returns
*
* ## Usage
* ```ts
* endsWithOneOf('cb', 'a', 'b'); // true
* endsWithOneOf('cc', 'a', 'b'); // false
* endsWithOneOf('cb', 'a', 'b'); // 'b'
* endsWithOneOf('cc', 'a', 'b'); // undefined
* ```
*/
export function endsWithOneOf(str: string, strings: string[]): boolean {
export function endsWithOneOf<T extends string>(str: string, strings: readonly T[]): T | undefined {
for (const s of strings) {
if (str.endsWith(s)) return true;
if (str.endsWith(s)) return s;
}

return false;
return undefined;
}

/** Case insensitive equality. Returns true if `left.toLowerCase()` and `right.toLowerCase()` are equal.
Expand Down
Loading