0

I am trying to type a function that does this

  • Takes a string corresponding to a number type,
  • returns a typed array
  • Upon execution the user receives information about the exact typed array returned

But after trying for a long while, I haven't been able to connect the input and output.

const typedArrays = {
  int8: Int8Array,
  uint8: Uint8Array,
  int16: Int16Array,
  uint16: Uint16Array,
};

type TypedArrays = typeof typedArrays

function doSomething<T extends keyof TypedArrays>(input:T): TypedArrays[T]{
    return new typedArrays[input]([1,2,3])
}

Edit: incorporated a few of the suggestions in answers (still do not solve the main problem.)

PLAYGROUND

2 Answers 2

1

Your TypedArrays type would work if it was just a simple typeof typedArrays

type TypedArrays = typeof typedArrays;

Since you want to return instances of the typed arrays and your object contains constructors you need to use InstanceType for the return type of your function

function doSomething<T extends keyof typeof typedArrays>(input: T): InstanceType<TypedArrays[T]> {
    return new typedArrays[input]() as InstanceType<TypedArrays[T]>;
}

Playground

Sign up to request clarification or add additional context in comments.

2 Comments

That still wont work, I just forgot the keyword new in the example.
@Minsky updated the answer with a solution that returns instances
1

The major problem is that TypedArrays is an interface declared as

{
  T: typeof typedArrays[T];
}

So input is typed as "T", but "T" is not assignable to keyof typeof typedArray

It is correct from the response above to type better TypedArrays, but you could even not use it:

const typedArrays = {
  int8: Int8Array,
  uint8: Uint8Array,
  int16: Int16Array,
  uint16: Uint16Array,
  int32: Int32Array,
  uint32: Uint32Array,
  uint64: BigUint64Array,
  int64: BigInt64Array,
  float32: Float32Array,
  float64: Float64Array,
};


function doSomething<T extends keyof typeof typedArrays>(
  input: T
): typeof typedArrays[T] {
  return typedArrays[input];
}

const a = doSomething("int8"); // Int8ArrayConstructor
const b = doSomething("float32"); // Float32ArrayConstructor

Also, please keep an eye about the use of new.

Take for example int8: Int8Array in typedArrays, remember that Int8Array is not a type, but a var:

var Int8Array: Int8ArrayConstructor

So this will result in an error:

function doSomething<T extends keyof TypedArray>(input: T): TypedArray[T] {
  return new typedArrays[input]; // Error
}

This is because we are returning a truly Int8Array from a function that should return Int8ArrayConstructor.

In order to avoid this, do the following:

const typedArrays = {
  int8: Int8Array,
  uint8: Uint8Array,
  int16: Int16Array,
  uint16: Uint16Array,
  int32: Int32Array,
  uint32: Uint32Array,
  uint64: BigUint64Array,
  int64: BigInt64Array,
  float32: Float32Array,
  float64: Float64Array,
};

type TypedArray = typeof typedArrays;

function doSomething<T extends keyof TypedArray>(input: T): TypedArray[T] {
  return typedArrays[input];
}

const a = new (doSomething("int8"))(); // Int8Array
const b = doSomething("float32"); // Float32ArrayConstructor

4 Comments

Thanks but we need to return new typedArrays[input] and that breaks.
@Minsky I just updated the example, tell me if this help you
It does but I am trying to get a clean execution as this is an API. This won't be useful.
@Minsky maybe a better solution is make a switch inside the body of the function, this would resolve in a more verbose function but should works

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.