Home > Software design >  Array with different type when index is odd or even
Array with different type when index is odd or even

Time:12-23

I am looking for a type OddEvenArray<Odd,Even>, which can do the following thing typesafe as OddEvenArray<string,number>: ["a",1,"b",2].

I have no idea to distinguish between odd and even index during typing.

PS: I am sorry, but the JSON I am dealing with looks like that ^^'

CodePudding user response:

An array index is a number type, and number types can either be any number (as number) or specific numbers (as 1 | 2 | 47).

There aren't really any other options at the type level. This means that something like this not possible to annotate as of Typescript 4.9.

CodePudding user response:

You cannot do that with Typescript. I wish you could. It would be a cool language feature.

The closest thing to an "even number" type would look something like the following. Wrap it in a class. Do the same thing with even numbers. Work out the kinks.

class EvenNumber {
  public constructor(n: number) {
    if (n % 2 != 0) {
      throw new Error("argument is not even:", n);
    }
    this.num = n;
  }
}

CodePudding user response:

this is only possible with function generic, you cannot directly assign this type to a variable, you must check with function

this only works for tuple, not array

type Odd<
    X extends number,
    Y extends unknown[] = [1],
    Z extends number = never
> = Y['length'] extends X
    ? Z | Y['length']
    : Odd<X, [1, 1, ...Y], Z | Y['length']>

type OddNumbers = Odd<1999> // 1 | 3 | 5 | 7 | ....1997

type IsStringAndOddTuple<T extends unknown[], ACC extends any[]=[]> = 
    T extends [infer A, ...infer J] 
        ? T['length'] extends OddNumbers 
            ? IsStringAndOddTuple<J,[...ACC, A extends number? A : "expect number type at even index" ]>
            : IsStringAndOddTuple<J,[...ACC, A extends string? A : "expect string type at Odd index" ]>
        :ACC

const isStringAndOddTuple =<T extends unknown[]>(tuple: T extends never? T : IsStringAndOddTuple<T>)=>{
  // don't neeed anything here
}

type C = IsStringAndOddTuple<[1, 2, 3, 4]>
//   ^?

type D = IsStringAndOddTuple<["a","b","c","d"]>
//   ^?

type E = IsStringAndOddTuple<["a",1,"b",2]>
//   ^?

isStringAndOddTuple([1, 2, 3, 4]) 
isStringAndOddTuple(["a","b","c","d"]) 
isStringAndOddTuple<["a",1,"b",2]> 

enter image description here

enter image description here playground

reference:
Odd Number Type

  • Related