Skip to content

Commit

Permalink
feat(types): Add isTypedArray() and isNumericArray() (#314)
Browse files Browse the repository at this point in the history
  • Loading branch information
ibgreen authored Jan 1, 2023
1 parent d799ea1 commit aa529d7
Show file tree
Hide file tree
Showing 13 changed files with 128 additions and 8 deletions.
8 changes: 7 additions & 1 deletion docs/table-of-contents.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,13 @@
{
"title": "API Reference",
"chapters": [
{
"title": "@math.gl/types",
"entries": [
{"entry": "modules/types/docs"},
{"entry": "modules/types/docs/api-reference/is-array"}
]
},
{
"title": "@math.gl/core",
"entries": [
{"entry": "modules/core/docs"},
Expand Down
8 changes: 7 additions & 1 deletion docs/whats-new.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,13 @@
</tbody>
</table>

## v3.6 (In Development)
## v3.7 (In Development)

**`@math.gl/types`

- Add `isTypedArray()` and `isNumericArray()` utilities that both check values and return properly restricted types to help write strictly typed code (avoids the `DataView` issue with `ArrayBuffer.isView()`).

## v3.6

Target Release Date: Q4, 2021

Expand Down
2 changes: 2 additions & 0 deletions modules/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// types
export type {TypedArray, NumericArray} from '@math.gl/types';

export type {isTypedArray, isNumericArray} from '@math.gl/types';

// classes
export {default as Vector2} from './classes/vector2';
export {default as Vector3} from './classes/vector3';
Expand Down
8 changes: 4 additions & 4 deletions modules/core/src/lib/common.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Copyright (c) 2017 Uber Technologies, Inc.
// MIT License
import {NumericArray} from '@math.gl/types';
// math.gl, MIT license

import type {NumericArray} from '@math.gl/types';

import type MathArray from '../classes/base/math-array';

Expand Down Expand Up @@ -50,8 +50,8 @@ export function formatValue(
/**
* Check if value is an "array"
* Returns `true` if value is either an array or a typed array
*
* Note: returns `false` for `ArrayBuffer` and `DataView` instances
* @note isTypedArray and isNumericArray are often more useful in TypeScript
*/
export function isArray(value: unknown): boolean {
return Array.isArray(value) || (ArrayBuffer.isView(value) && !(value instanceof DataView));
Expand Down
10 changes: 10 additions & 0 deletions modules/types/docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Overview

Minimal set of math types, intended to be used with very low cost (bundle size impact)
across other frameworks.

## Installation

```bash
npm install @math.gl/types
```
23 changes: 23 additions & 0 deletions modules/types/docs/api-reference/array-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Array Types

## Types

### `TypedArray`

Any javascript typed array

### `NumericArray`

Any javascript typed array, or any javascript array containing numbers

## Utilities

### `isTypedArray(value: unknown): TypedArray | null`

Avoids type problems with the `ArrayBuffer.isView()` check.

### `isNumericArray(value: unknown): TypedArray | null`

Avoids type problems with the `ArrayBuffer.isView()` check.

Note: only the type of the first element in a standard array is checked to be a `number`.
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ export type NumericArray = TypedArray | number[];

/**
* TypeScript type covering all typed arrays and classic arrays consisting of numbers
* @note alias for NumericArray
*/
export type NumberArray = TypedArray | number[];
export type NumberArray = NumericArray;
3 changes: 2 additions & 1 deletion modules/types/src/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export {TypedArray, NumberArray, NumericArray} from './number-array';
export type {TypedArray, NumericArray, NumberArray} from './array-types';
export {isTypedArray, isNumericArray} from './is-array';
22 changes: 22 additions & 0 deletions modules/types/src/is-array.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {TypedArray, NumericArray} from './array-types';

/**
* Check is an array is a typed array
* @param value value to be tested
* @returns input as TypedArray, or null
*/
export function isTypedArray(value: unknown): TypedArray | null {
return ArrayBuffer.isView(value) && !(value instanceof DataView) ? (value as TypedArray) : null;
}

/**
* Check is an array is a numeric array (typed array or array of numbers)
* @param value value to be tested
* @returns input as NumericArray, or null
*/
export function isNumericArray(value: unknown): NumericArray | null {
if (Array.isArray(value)) {
return value.length === 0 || typeof value[0] === 'number' ? (value as number[]) : null;
}
return isTypedArray(value);
}
3 changes: 3 additions & 0 deletions modules/types/test/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// math.gl, MIT license

import './is-array.spec';
44 changes: 44 additions & 0 deletions modules/types/test/is-array.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// math.gl, MIT license

import test, {Test} from 'tape-promise/tape';
import {isTypedArray, isNumericArray} from '@math.gl/types';

const TEST_CASES: {value: unknown; isTypedArray: boolean; isNumericArray: boolean}[] = [
{value: new Float32Array(1), isTypedArray: true, isNumericArray: true},
{value: new Uint8Array(2), isTypedArray: true, isNumericArray: true},
{value: [], isTypedArray: false, isNumericArray: true},
{value: [100, 100], isTypedArray: false, isNumericArray: true},
{value: ['a'], isTypedArray: false, isNumericArray: false},
{value: new ArrayBuffer(4), isTypedArray: false, isNumericArray: false},
{value: new DataView(new ArrayBuffer(16)), isTypedArray: false, isNumericArray: false},
{value: undefined, isTypedArray: false, isNumericArray: false},
{value: null, isTypedArray: false, isNumericArray: false},
{value: {}, isTypedArray: false, isNumericArray: false},
{value: {length: 0}, isTypedArray: false, isNumericArray: false},
{value: 1, isTypedArray: false, isNumericArray: false},
{value: NaN, isTypedArray: false, isNumericArray: false},
{value: 'NaN', isTypedArray: false, isNumericArray: false},
{value: '', isTypedArray: false, isNumericArray: false}
];

test('math.gl#isTypedArray', (t) => {
for (const tc of TEST_CASES) {
t.equal(
Boolean(isTypedArray(tc.value)),
tc.isTypedArray,
`isTypedArray(${JSON.stringify(tc.value)}) => ${tc.isTypedArray}`
);
}
t.end();
});

test('math.gl#isNumericArray', (t) => {
for (const tc of TEST_CASES) {
t.equal(
Boolean(isNumericArray(tc.value)),
tc.isNumericArray,
`isNumericArray(${JSON.stringify(tc.value)}) => ${tc.isNumericArray}`
);
}
t.end();
});
1 change: 1 addition & 0 deletions test/modules.spec.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import '../modules/types/test';
import '../modules/core/test';
import '../modules/culling/test';
import '../modules/geoid/test';
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"@math.gl/sun/*": ["modules/sun/src/*"],
"@math.gl/sun/test/*": ["modules/sun/test/*"],
"@math.gl/types/*": ["modules/types/src/*"],
"@math.gl/types/test/*": ["modules/types/test/*"],
"@math.gl/web-mercator/*": ["modules/web-mercator/src/*"],
"@math.gl/web-mercator/test/*": ["modules/web-mercator/test/*"],
"test/*": ["test/*"]
Expand Down

0 comments on commit aa529d7

Please sign in to comment.