Zou Jeff
Zou Jeff

Reputation: 883

How to type a fixed-length generator in typescript?

I have a Vector2 class in typescript below.

// Vector2.ts
class Vector2 {
  constructor (public x, public y) {
    this.x = x;
    this.y = y;
  }

  //... A bunch of vector methods

  public* [Symbol.iterator]: Generator<number, void, unkown> {
    yield this.x;
    yield this.y;
  }
}

// main.js
const canvas = document.querySelector('#canvas');
const ctx = canvas.getContext('2d');

const a = new Vector2(0, 0);
const b = new Vector2(10, 10);

ctx.beginPath();
ctx.moveTo(...a);
// works correctly, but with this warning: 
// Expected 2 arguments, but got 0 or more.ts(2556)
ctx.lineTo(...b);
ctx.stroke();
ctx.closePath();

This code works perfectly fine according to my design. However typescript doesn't seem to know how many arguments are supplied and keeps warning me about it; unless I directly cast it to a tuple of 2 numbers like this:

ctx.moveTo(...(a as unknown as [number, number]))

Questions:

  1. Is there a way to tell typescript that my Vector2 instances will be deconstructed into a fixed-length tuple when I use the spread operator?
  2. Is there a way to type a generator with a fixed length?

Upvotes: 0

Views: 248

Answers (1)

old greg
old greg

Reputation: 897

I don't know if a generator function is the correct abstraction here. Usually you'd use one where the length of items you're yielding is variable or unknown.

Why not work with an implementation like this:

class Vector2 {
  public toArray(): [number, number] {
    return [this.x, this.x];
  }
}

ctx.moveTo(...myVector.toArray());

This way the TypeScript compiler knows the type returned by toArray, and knows it will be valid when applied to ctx.moveTo

Upvotes: 1

Related Questions