Kyle Barron
Kyle Barron

Reputation: 2649

TypeScript Generics TypedArray: TypedArray is not assignable to T

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?

Upvotes: 2

Views: 459

Answers (2)

ford04
ford04

Reputation: 74620

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

Upvotes: 1

koalaok
koalaok

Reputation: 5760

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);
}

Upvotes: 1

Related Questions