From dc100ccc112b434a3c69fd8365cb4c965715e426 Mon Sep 17 00:00:00 2001 From: lukaszkowalik2 <87244916+lukaszkowalik2@users.noreply.github.com> Date: Sun, 13 Oct 2024 15:46:54 +0200 Subject: [PATCH] feat(isFile): add `isFile` (#704) * feat(isFile): added support for isFile * fix(isFile): added missing .ts extensions * Update docs/ko/reference/predicate/isFile.md --------- Co-authored-by: Sojin Park --- docs/ja/reference/predicate/isFile.md | 31 ++++++++++ docs/ko/reference/predicate/isFile.md | 31 ++++++++++ docs/reference/predicate/isFile.md | 31 ++++++++++ docs/zh_hans/reference/predicate/isFile.md | 31 ++++++++++ src/predicate/index.ts | 1 + src/predicate/isFile.spec.ts | 70 ++++++++++++++++++++++ src/predicate/isFile.ts | 28 +++++++++ 7 files changed, 223 insertions(+) create mode 100644 docs/ja/reference/predicate/isFile.md create mode 100644 docs/ko/reference/predicate/isFile.md create mode 100644 docs/reference/predicate/isFile.md create mode 100644 docs/zh_hans/reference/predicate/isFile.md create mode 100644 src/predicate/isFile.spec.ts create mode 100644 src/predicate/isFile.ts diff --git a/docs/ja/reference/predicate/isFile.md b/docs/ja/reference/predicate/isFile.md new file mode 100644 index 000000000..33c890a52 --- /dev/null +++ b/docs/ja/reference/predicate/isFile.md @@ -0,0 +1,31 @@ +# isFile + +指定された値が`File`であるかどうかをチェックします。 + +この関数はTypeScriptで型述語としても機能し、引数の型を`File`に絞り込みます。 + +## シグネチャ + +```typescript +function isFile(x: unknown): x is File; +``` + +### パラメータ + +- `x` (`unknown`): `File`であるかどうかを確認する値。 + +### 戻り値 + +(`x is File`): 値が`File`であれば`true`、そうでなければ`false`。 + +## 例 + +```typescript +const file = new File(['content'], 'example.txt', { type: 'text/plain' }); +const blob = new Blob(['content'], { type: 'text/plain' }); +const value = {}; + +console.log(isFile(file)); // true +console.log(isFile(blob)); // false +console.log(isFile(value)); // false +``` diff --git a/docs/ko/reference/predicate/isFile.md b/docs/ko/reference/predicate/isFile.md new file mode 100644 index 000000000..ec47a5a45 --- /dev/null +++ b/docs/ko/reference/predicate/isFile.md @@ -0,0 +1,31 @@ +# isFile + +주어진 값이 `File`인지 확인해요. + +TypeScript의 타입 가드로 사용할 수 있어요. 파라미터로 주어진 값의 타입을 `File`로 좁혀요. + +## 시그니처 + +```typescript +function isFile(x: unknown): x is File; +``` + +### 매개변수 + +- `x` (`unknown`): `File`인지 확인할 값. + +### 반환값 + +(`x is File`): 값이 File이면 `true`, 그렇지 않으면 `false`. + +## 예시 + +```typescript +const file = new File(['content'], 'example.txt', { type: 'text/plain' }); +const blob = new Blob(['content'], { type: 'text/plain' }); +const value = {}; + +console.log(isFile(file)); // true +console.log(isFile(blob)); // false +console.log(isFile(value)); // false +``` diff --git a/docs/reference/predicate/isFile.md b/docs/reference/predicate/isFile.md new file mode 100644 index 000000000..6e56bede1 --- /dev/null +++ b/docs/reference/predicate/isFile.md @@ -0,0 +1,31 @@ +# isFile + +Checks if the given value is a `File`. + +This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `File`. + +## Signature + +```typescript +function isFile(x: unknown): x is File; +``` + +### Parameters + +- `x` (`unknown`): The value to test if it is a `File`. + +### Returns + +(`x is File`): True if the value is a `File`, false otherwise. + +## Examples + +```typescript +const file = new File(['content'], 'example.txt', { type: 'text/plain' }); +const blob = new Blob(['content'], { type: 'text/plain' }); +const value = {}; + +console.log(isFile(file)); // true +console.log(isFile(blob)); // false +console.log(isFile(value)); // false +``` diff --git a/docs/zh_hans/reference/predicate/isFile.md b/docs/zh_hans/reference/predicate/isFile.md new file mode 100644 index 000000000..37f210a0a --- /dev/null +++ b/docs/zh_hans/reference/predicate/isFile.md @@ -0,0 +1,31 @@ +# isFile + +检查给定的值是否是一个`File`。 + +此函数测试提供的值是否是`File`的实例。 如果该值是`File`的实例,则返回`true`,否则返回`false`。 + +## 签名 + +```typescript +function isFile(x: unknown): x is File; +``` + +### 参数 + +- `x` (`unknown`): 要测试的值是否是一个`File`。 + +### 返回值 + +(`x is File`): 如果该值是一个`File`,则返回`true`,否则返回`false`。 + +## 示例 + +```typescript +const file = new File(['content'], 'example.txt', { type: 'text/plain' }); +const blob = new Blob(['content'], { type: 'text/plain' }); +const value = {}; + +console.log(isFile(file)); // true +console.log(isFile(blob)); // false +console.log(isFile(value)); // false +``` diff --git a/src/predicate/index.ts b/src/predicate/index.ts index 5708cff0e..344fe617f 100644 --- a/src/predicate/index.ts +++ b/src/predicate/index.ts @@ -5,6 +5,7 @@ export { isDate } from './isDate.ts'; export { isEqual } from './isEqual.ts'; export { isEqualWith } from './isEqualWith.ts'; export { isError } from './isError.ts'; +export { isFile } from './isFile.ts'; export { isFunction } from './isFunction.ts'; export { isJSONArray } from './isJSONArray.ts'; export { isJSONObject } from './isJSONObject.ts'; diff --git a/src/predicate/isFile.spec.ts b/src/predicate/isFile.spec.ts new file mode 100644 index 000000000..f9ecdecbf --- /dev/null +++ b/src/predicate/isFile.spec.ts @@ -0,0 +1,70 @@ +import { afterAll, beforeAll, describe, expect, it } from 'vitest'; +import { isFile } from './isFile'; + +describe('isFile', () => { + let originalFile: typeof File; + + beforeAll(() => { + originalFile = globalThis.File; + //@ts-expect-error - globalThis.File is browser only. + globalThis.File = class File extends Blob { + name: string; + constructor(chunks: any[], filename: string, options?: BlobPropertyBag) { + super(chunks, options); + this.name = filename; + } + }; + }); + + afterAll(() => { + globalThis.File = originalFile; + }); + + it('returns true if the value is a File', () => { + const file = new File(['content'], 'example.txt', { type: 'text/plain' }); + expect(isFile(file)).toBe(true); + }); + + it('returns false if the value is not a File', () => { + expect(isFile(0)).toBe(false); + expect(isFile('abc')).toBe(false); + expect(isFile(123)).toBe(false); + expect(isFile({ a: 1 })).toBe(false); + expect(isFile([1, 2, 3])).toBe(false); + expect(isFile(null)).toBe(false); + expect(isFile(undefined)).toBe(false); + const blob = new Blob(['content'], { type: 'text/plain' }); + expect(isFile(blob)).toBe(false); + }); + + it('can be used with TypeScript as a type predicate', () => { + const items: Array = [new File([''], 'example.txt'), 1, new File([''], 'example2.txt'), 2]; + const result = items.filter(isFile); + expect(result).toHaveLength(2); + expect(result[0]).toBeInstanceOf(File); + expect(result[1]).toBeInstanceOf(File); + }); + + it('returns false if File is not supported in the environment', () => { + const file = new File(['content'], 'example.txt', { type: 'text/plain' }); + const originalFile = globalThis.File; + // @ts-expect-error - we need to simulate the absence of File + globalThis.File = undefined; + expect(isFile(file)).toBe(false); + globalThis.File = originalFile; + }); + + it('returns false if Blob is not supported in the environment', () => { + const file = new File(['content'], 'example.txt', { type: 'text/plain' }); + const originalBlob = globalThis.Blob; + // @ts-expect-error - we need to simulate the absence of Blob + globalThis.Blob = undefined; + expect(isFile(file)).toBe(false); + globalThis.Blob = originalBlob; + }); + + it('returns false if Blob is passed as a File', () => { + const blob = new Blob(['content'], { type: 'text/plain' }); + expect(isFile(blob)).toBe(false); + }); +}); diff --git a/src/predicate/isFile.ts b/src/predicate/isFile.ts new file mode 100644 index 000000000..3c1de077a --- /dev/null +++ b/src/predicate/isFile.ts @@ -0,0 +1,28 @@ +import { isBlob } from './isBlob.ts'; + +/** + * Checks if the given value is a File. + * + * This function tests whether the provided value is an instance of `File`. + * It returns `true` if the value is an instance of `File`, and `false` otherwise. + * + * @param {unknown} x - The value to test if it is a File. + * @returns {x is File} True if the value is a File, false otherwise. + * + * @example + * const value1 = new File(["content"], "example.txt"); + * const value2 = {}; + * const value3 = new Blob(["content"], { type: "text/plain" }); + * + * console.log(isFile(value1)); // true + * console.log(isFile(value2)); // false + * console.log(isFile(value3)); // false + */ +export function isFile(x: unknown): x is File { + // Return false if File is not supported in the environment + if (typeof File === 'undefined') { + return false; + } + + return isBlob(x) && x instanceof File; +}