2

I'm learning about generics, and hitting this issue with the compiler:

type FloatArray = Float32Array | Float64Array;
type IntegerArray =
  | Int8Array
  | Uint8Array
  | Int16Array
  | Uint16Array
  | Int32Array
  | Uint32Array
  | Uint8ClampedArray;
type TypedArray = FloatArray | IntegerArray;

export function identityArray<T extends TypedArray>(array: T): T {
  return array.subarray(0);
}
// Type 'TypedArray' is not assignable to type 'T'

What am I doing wrong here?

2 Answers 2

1

Alternative solution without a type assertion:

type TypedArray = FloatArray | IntegerArray;
type WithSubArray<T extends TypedArray> = { subarray(begin?: number, end?: number): T };

export function identityArray<T extends TypedArray>(array: WithSubArray<T>): T {
    return array.subarray(0);
}

const res1 = identityArray(new Int8Array(2)) // Int8Array 👌
const res2 = identityArray(new Float32Array(2)) // Float32Array 👌
const res3 = identityArray([1, 2, 3]) // ✖

If T is declared as function return type, make sure to also return T exactly in the function body. By using WithSubArray we can make it clear to the compiler, that array.subarray returns T and not TypedArray.

TS Playground to try it out

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

Comments

1

From docs, just type cast your return line.

“trust me, I know what I’m doing.” A type assertion is like a type cast...

https://www.typescriptlang.org/docs/handbook/basic-types.html#type-assertions

type FloatArray = Float32Array | Float64Array;
type IntegerArray =
    | Int8Array
    | Uint8Array
    | Int16Array
    | Uint16Array
    | Int32Array
    | Uint32Array
    | Uint8ClampedArray;
type TypedArray = FloatArray | IntegerArray;

export function identityArray<T extends TypedArray>(array: T): T {
    return <T>array.subarray(0);
}

1 Comment

Thanks, that's helpful, but it still feels like I'm overriding the compiler. Shouldn't there be a way for this to work without the type assertion?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.