question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Add Length Parameter to typed arrays

See original GitHub issue

The goal is pretty straight forward, since typed arrays have a fixed length it would be a more accurate and helpful type it you could specify length. Then you could get complaints if you try to assign or access a higher index or use a array of the incorrect length.

Code

type Vector2d = Int32Array<2>;
type Vector3d = Int32Array<3>;
type Matrix = Int32Array<16>;

const add =
  (vecA:Vector2d) =>
    (vecB:Vector2d, target:Vector2d = new Int32Array(2) ):Vector2d => {
      target[0] = vecA[0] + vecB[0];
      target[1] = vecA[1] + vecB[1];
      return target;
    };

const add3d =
  (vecA:Vector3d) =>
    (vecB:Vector3d, target:Vector3d = new Int32Array(3) ):Vector3d => {
      target[0] = vecA[0] + vecB[0];
      target[1] = vecA[1] + vecB[1];
      target[2] = vecA[2] + vecB[2];
      return target;
    };

const position = new Int32Array(2);
const position3d = new Int32Array(3);
const velocity = new Int32Array([1,1]);
const velocity3d = new Int32Array([1,2,3]);

add(position)(velocity, position);
const newPosition = add(position)(velocity);

add3d(position3d)(velocity3d, position3d);
add(position3d)(velocity3d, position3d); // Fails due to incorrect array length

Issue Analytics

  • State:open
  • Created 6 years ago
  • Reactions:15
  • Comments:8 (3 by maintainers)

github_iconTop GitHub Comments

5reactions
bitjsoncommented, Jun 15, 2018

A custom type guard (like @mhegazy’s above) is definitely a good immediate solution, but I think it would be a huge improvement for TypeScript to specifically track the length of typed arrays.

For normal arrays, this would expand the scope of type-checking significantly, since array lengths can be modified after creation. However, typed arrays have fixed sizes at creation and can then be treated as a unique primitive.

Current Example

Here’s an obvious bug which isn’t currently caught at compile time:

function specialTransform (array: Uint8Array) {
    if (array.length !== 4) {
        throw new Error('This function is only for 4-byte Uint8Arrays.')
    }
    return new Uint8Array([array[0] + 1, array[2], array[3] - 1, array[4]])
}

const bytes = new Uint8Array([1, 2, 3]);

// Will always throw an error at runtime, but can't be identified at compile time:
specialTransform(bytes);

This code could never work, and the thrown error in specialTransform should never happen in production. It’s only purpose is to inform the programmer during debugging that they are using specialTransform incorrectly.

This could be made harder-to-mess-up with a custom type guard:

interface SpecialType extends Uint8Array {
  readonly length: 4;
}

export function brandSpecialType(array: Uint8Array): SpecialType {
    if (array.length !== 4) {
        throw new Error('This function is only for 4-byte Uint8Arrays.')
    }
  return array as SpecialType;
}

function specialTransform (array: specialType) {
    return Uint8Array([array[0] + 1, array[2], array[3] - 1, array[4]])
}

// the user still needs to 
const bytes = Uint8Array([1, 2, 3]);

// Runtime error happens a little earlier, but still not at compile time:
const mySpecialType = brandSpecialType(bytes);

specialTransform(mySpecialType);

This is marginally better in some situations, but requires a lot more custom infrastructure. If I’m writing a library that operates on sets of specifically sized typed arrays (like a cryptographic library), I can’t provide both flexibility and strict typing. (See bitcoin-ts’s Secp256k1 for an example.)

(Please let me know if I’m missing a better solution here.)

I believe I can either allow the developer to pass my functions a simple Uint8Array (and type-check at runtime to make sure they did it right), or I can export infrastructure for “creating” SpecialTypes, which are just ways of tightening the type of the length parameter.

What I would like to see

IMO, it would be ideal if TypeScript had the ability to track the length of typed arrays, and check them using simple expressions. Something like:

function specialTransform (array: Uint8Array<length === 4>) {
    return new Uint8Array([array[0] + 1, array[2], array[3] - 1, array[4]])
}

// works
specialTransform(new Uint8Array([1, 2, 3, 4]));

// ts error: Argument of type 'Uint8Array<{length: 3}>' is not assignable to parameter of type 'Uint8Array<length === 4>'.
specialTransform(new Uint8Array([1, 2, 3]));

Along with allowing certain examples to be fully type-checked, this would allow significantly better interoperability between libraries which deal with typed arrays.


(Last note: I’m sure there’s a more general feature that could be implemented and used to add this functionality to TypedArrays, but I’m not knowledgable enough to discuss the general case. I think it may be similar to the Tag types discussion, though since typed arrays are first-class JavaScript features, and for the other reasons above, I think TypeScript should have this kind of checking for typed arrays built-in.)

2reactions
mhegazycommented, Sep 14, 2017

I am not sure of the utility of pushing this change into the standard library though.

Read more comments on GitHub >

github_iconTop Results From Across the Web

JavaScript typed arrays - MDN Web Docs
JavaScript typed arrays are array-like objects that provide a mechanism for reading and writing raw binary data in memory buffers.
Read more >
How to declare a Fixed length Array in TypeScript
This solution behaves as an augmentation of the Array type, accepting an additional second parameter(Array length).
Read more >
20. Typed Arrays - Exploring JS
Typed Arrays are much like normal Arrays: they have a length , elements can be accessed via the bracket operator [ ] and...
Read more >
JavaScript | typedArray.length() with Examples - GeeksforGeeks
The typedArray.length is an inbuilt property in JavaScript which is used to return the length of the given typedArray. ... Parameters: It does...
Read more >
Typed arrays - Binary data in the browser - web.dev
To use Typed Arrays, you need to create an ArrayBuffer and a view to it. The easiest way is to create a typed...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found