user11384784
user11384784

Reputation:

Forcing array to have at least one value in Typescript

Is there a Typescript way to require that an array needs to have at least one value? e.g:

type value = "1" | "2";

export interface ISomething {
  values: value[] // < should be required and have at least one.
}

Upvotes: 9

Views: 3410

Answers (4)

Diego V
Diego V

Reputation: 6414

type value = "1" | "2";

export interface ISomething {
  values: [value, ...value[]] // ← this is the non-empty array type
}

const empty: ISomething = { values: [] }
// Type '[]' is not assignable to type '[value, ...value[]]'.
// Source has 0 element(s) but target requires 1.

const oneValue: ISomething = { values: ["1"] }
// all good :)

Optionally, you could extract it to be used as a generic utility type, as follows:

export type NonEmptyArray<T> = [T, ...Array<T>];

export interface ISomething {
  values: NonEmptyArray<value>
}

Upvotes: 9

Andrew
Andrew

Reputation: 556

Another way without interfaces:

export type NonEmptyArray<Type> = [Type, ...Array<Type>];

Usage:

const arrayOfStrings1: NonEmptyArray<string> = ['x']; // valid
const arrayOfStrings2: NonEmptyArray<string> = ['x', 'y']; // valid
const arrayOfStrings3: NonEmptyArray<string> = ['x', 'y', 'z']; // valid
const arrayOfStrings4: NonEmptyArray<string> = [] // invalid
// Type '[]' is not assignable to type '[string, ...string[]]'.
// Source has 0 element(s) but target requires 1.ts(2322)

Upvotes: 6

Jake Holzinger
Jake Holzinger

Reputation: 6063

You could also implement an interface that extends Array:

type value = "1" | "2";

interface IValueArray extends Array<value> {
  0: value; // ensure that at least one 'value' is present
}

export interface ISomething {
  values: IValueArray
}

const something1: ISomething = {
  values: ['1']
}

const something2: ISomething = {
  values: [] // type error
}

Upvotes: 0

Rannie Aguilar Peralta
Rannie Aguilar Peralta

Reputation: 1742

Try this

type value = "1" | "2";

export interface ISomething {
  values: {
    0: value,
    [key: number]: value,
  }
}``

Upvotes: 1

Related Questions