Poznajemy nieco o tablicach w TypeScript, względnie będzie to dla nas powtórka. Zaczynajmy.

Ok, tak definiujemy tablice określonego typu:

type NumericArray = number[];
type StringArray = string[];
type AnyArray = any[];

Tablice to typy generyczne i mamy też alternatywną składnię:

type NumericArray = Array<number>;
type StringArray = Array<string>;
type AnyArray = Array<any>;

Mamy też taki utility type jak readonly:

type ReadonlyNumericArray = Readonly<NumericArray>;
//type ReadonlyNumericArray = readonly number[]

Ok, zobaczmy na ten przykład:

const readonlyNums: Readonly<number[]> = [1,2,3];
//const readonlyNums: readonly number[]

A teraz zobaczmy na różnicę, jaką robi as const bez nawet anotacji typu:

const literalReadonly = [1,2,3] as const;
//const literalReadonly: readonly [1, 2, 3]

Inny sposób, aby to osiągnąć:

type ValidComparisonRetType = Readonly<[-1,0,1]>
//type ValidComparisonRetType = readonly [-1, 0, 1]

Ok, zobaczmy jak z tablic możemy wyciągać klucze w zagnieżdżeniu:

const myArray = [
    { name: "Alice", age: 15 },
    { name: "Bob", age: 23 },
    { name: "Eve", age: 38 },
  ];

type Age321 = typeof myArray[number]["age"];

Można też tak:

const myArray = [
    { name: "Alice", age: 15 },
    { name: "Bob", age: 23 },
    { name: "Eve", age: 38 },
  ];

type Age321 = typeof myArray[number]["age"];
//type Age321 = number

type ArrKey<T extends Array<object>, K extends keyof T[number]> = T[number][K];

type ageFromArr = ArrKey<typeof myArray, 'age'>;
// type ageFromArr = number

Pusta tablica potrafi nam zepsuć wiele, przykład klasy:

class Collection<T>  {

    constructor(private _data: T[]) {
      this._data = _data;
    }
  
    get length(): number {
      return this._data.length;
    }

    get(key: number): T | -1 {
        if(key >= this.length)
            return -1;
        return this._data[key];
    }

    get data() : T[]{
        return this._data;
    }

    set data(newData: T[]) {
        this._data = newData;
    }

    push(val: T) : void {
        this._data.push(val);
    }
  
    
  }

I teraz nie podajemy ani w ostrych nawiasach typu, ani z tablicy nie idzie wywnioskować:

let col1 = new Collection([]);

col1.push(4); //error

To mamy dwa wyjścia. Operator as:

let col1 = new Collection([] as number[]);

col1.push(4); //ok

Albo po prostu doprecyzować typ:

let col1 = new Collection<number>([]);

col1.push(4); //ok

Więcej tablic w TS już niedługo!