Lukas
Lukas

Reputation: 10340

TypeScript: Cannot assign empty array to array of my own type

I have an interface called Converter

export interface Converter<T> {
  uuid: CUUID;
  decode: (value: Buffer) => Promise<T>;
  encode?: (value: T) => Promise<Buffer>;
}

And I am using an array of that in another file:

import{ Converter } from "./characteristic";

export type Converters = Converter<any>[];

export default class Service<C extends Converters> {
  private converters: C;

  constructor(converters: C = []) {
           // ^^^^^^^^^^^^^^^^^^ error
    this.converters = converters;
  }
}

I am getting an error when I want to assign an empty array as an initial value to that property:

Type 'never[]' is not assignable to type 'C'.
  'never[]' is assignable to the constraint of type 'C', but 'C' could be instantiated with a different subtype of constraint 'Converter<any>[]'.ts(2322)

I have tried changing my type to

export type Converters = Converter<any>[] | [];

without any luck

I can do this:

export default class Service<C extends Converters> {
  private converters: C | [] = [];
}

but I am not sure why I have to or if that even is an appropriate solution and not just a anti-pattern workaround. I don't even understand what the problem is here.

Upvotes: 0

Views: 528

Answers (1)

Wilhelmina Lohan
Wilhelmina Lohan

Reputation: 3033

The following seems to work:

export interface Converter<T = any> {
  uuid: CUUID;
  decode: (value: Buffer) => Promise<T>;
  encode?: (value: T) => Promise<Buffer>;
}

export default class Service<C extends Converter> {
  private converters: C[];

  constructor(converters: C[] = []) {
    this.converters = converters;
  }
}

I think export type Converters = Converter<any>[]; must obscure that it is an array so it tries to compare never[] to Converters instead of [] (with possibility to .push(Converter)) to Converter[].

Edit: actually if the the Service is intended to only have Converters of a certain type not mixed (I don't know) it might be better to do:

export interface Converter<T> {
  uuid: CUUID;
  decode: (value: Buffer) => Promise<T>;
  encode?: (value: T) => Promise<Buffer>;
}

export default class Service<T> {
  private converters: Converter<T>[];

  constructor(converters: Converter<T>[] = []) {
    this.converters = converters;
  }
}

Upvotes: 1

Related Questions