Skip to content

Commit

Permalink
feat(isFile): add isFile (#704)
Browse files Browse the repository at this point in the history
* feat(isFile): added support for isFile

* fix(isFile): added missing .ts extensions

* Update docs/ko/reference/predicate/isFile.md

---------

Co-authored-by: Sojin Park <[email protected]>
  • Loading branch information
lukaszkowalik2 and raon0211 authored Oct 13, 2024
1 parent be5ba71 commit dc100cc
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 0 deletions.
31 changes: 31 additions & 0 deletions docs/ja/reference/predicate/isFile.md
Original file line number Diff line number Diff line change
@@ -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
```
31 changes: 31 additions & 0 deletions docs/ko/reference/predicate/isFile.md
Original file line number Diff line number Diff line change
@@ -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
```
31 changes: 31 additions & 0 deletions docs/reference/predicate/isFile.md
Original file line number Diff line number Diff line change
@@ -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
```
31 changes: 31 additions & 0 deletions docs/zh_hans/reference/predicate/isFile.md
Original file line number Diff line number Diff line change
@@ -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
```
1 change: 1 addition & 0 deletions src/predicate/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
70 changes: 70 additions & 0 deletions src/predicate/isFile.spec.ts
Original file line number Diff line number Diff line change
@@ -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<File | number> = [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);
});
});
28 changes: 28 additions & 0 deletions src/predicate/isFile.ts
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit dc100cc

Please sign in to comment.