forked from orbit-oss/is
parent
ef35cc350a
commit
c68ad76062
3 changed files with 33 additions and 3 deletions
|
|
@ -8,6 +8,7 @@ import type {
|
|||
Predicate,
|
||||
Primitive,
|
||||
TypedArray,
|
||||
UrlString,
|
||||
WeakRef,
|
||||
Whitespace,
|
||||
} from './types.js';
|
||||
|
|
@ -760,7 +761,7 @@ export function isUrlSearchParams(value: unknown): value is URLSearchParams {
|
|||
return getObjectType(value) === 'URLSearchParams';
|
||||
}
|
||||
|
||||
export function isUrlString(value: unknown): value is string {
|
||||
export function isUrlString(value: unknown): value is UrlString {
|
||||
if (!isString(value)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -894,7 +895,7 @@ type Assert = {
|
|||
dataView: (value: unknown, message?: string) => asserts value is DataView;
|
||||
enumCase: <T = unknown>(value: unknown, targetEnum: T, message?: string) => asserts value is T[keyof T];
|
||||
urlInstance: (value: unknown, message?: string) => asserts value is URL;
|
||||
urlString: (value: unknown, message?: string) => asserts value is string;
|
||||
urlString: (value: unknown, message?: string) => asserts value is UrlString;
|
||||
truthy: <T>(value: T | Falsy, message?: string) => asserts value is T;
|
||||
falsy: (value: unknown, message?: string) => asserts value is Falsy;
|
||||
nan: (value: unknown, message?: string) => asserts value is number;
|
||||
|
|
@ -1650,7 +1651,7 @@ export function assertUrlSearchParams(value: unknown, message?: string): asserts
|
|||
}
|
||||
}
|
||||
|
||||
export function assertUrlString(value: unknown, message?: string): asserts value is string {
|
||||
export function assertUrlString(value: unknown, message?: string): asserts value is UrlString {
|
||||
if (!isUrlString(value)) {
|
||||
throw new TypeError(message ?? typeErrorMessage('string with a URL', value));
|
||||
}
|
||||
|
|
@ -1705,4 +1706,5 @@ export type {
|
|||
Predicate,
|
||||
Primitive,
|
||||
TypedArray,
|
||||
UrlString,
|
||||
} from './types.js';
|
||||
|
|
|
|||
|
|
@ -75,3 +75,10 @@ export type Predicate = (value: unknown) => boolean;
|
|||
export type NonEmptyString = string & {0: string};
|
||||
|
||||
export type Whitespace = ' ';
|
||||
|
||||
/**
|
||||
A string that represents a valid URL.
|
||||
|
||||
This is a branded type to prevent incorrect TypeScript type narrowing.
|
||||
*/
|
||||
export type UrlString = string & {readonly __brand: 'UrlString'};
|
||||
|
|
|
|||
21
test/test.ts
21
test/test.ts
|
|
@ -17,6 +17,7 @@ import is, {
|
|||
type Primitive,
|
||||
type TypedArray,
|
||||
type TypeName,
|
||||
type UrlString,
|
||||
} from '../source/index.js';
|
||||
import {keysOf} from '../source/utilities.js';
|
||||
|
||||
|
|
@ -757,6 +758,26 @@ test('is.urlString', t => {
|
|||
});
|
||||
});
|
||||
|
||||
// Type test for urlString narrowing fix (issue #212)
|
||||
// This test demonstrates that the fix allows proper type narrowing in both branches
|
||||
(() => {
|
||||
const value: unknown = 'test';
|
||||
|
||||
if (is.urlString(value)) {
|
||||
// ✅ In true branch: value is narrowed to UrlString
|
||||
expectTypeOf(value).toEqualTypeOf<UrlString>();
|
||||
expectTypeOf(value).toMatchTypeOf<string>();
|
||||
} else {
|
||||
// ✅ In false branch: value remains unknown (not incorrectly narrowed)
|
||||
expectTypeOf(value).toEqualTypeOf<unknown>();
|
||||
|
||||
// ✅ Manual narrowing to string still works
|
||||
if (typeof value === 'string') {
|
||||
expectTypeOf(value).toEqualTypeOf<string>();
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
test('is.truthy', t => {
|
||||
t.true(is.truthy('unicorn'));
|
||||
t.true(is.truthy('🦄'));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue