Home > other >  Type '(string | undefined)[]' is not assignable to type '[string | undefined]'
Type '(string | undefined)[]' is not assignable to type '[string | undefined]'

Time:08-07

I am developing a typescript project. Currently, my challenge is the ts(2322) error.

Here is my code.

import {
  BASE_URL,
  AIRTABLE_BASE_ID,
  AIRTABLE_TABLE_STUDENT,
  AIRTABLE_TABLE_CLASSES,
  API_KEY,
} from './../../config/config';
// A mock function to mimic making an async request for data
export function fetchCount(amount = 1) {
  return new Promise<{ data: number }>((resolve) =>
    setTimeout(() => resolve({ data: amount }), 500)
  );
}

// Result object
interface Result {
  records: [
    {
      id: string;
      createdTime: string;
      fields: {
        Name?: string;
        Students?: [string];
        Classes?: [string];
      };
    }
  ];
}

// Class info object
interface ClassInfo {
  Name: string | undefined;
  Students: [string | undefined];
}

// fetch airtable data by url
const fetchData = (endpoint: string) => {
  return fetch(endpoint, {
    headers: new Headers({
      'Content-Type': 'application/json',
      Authorization: `Bearer ${API_KEY}`,
    }),
  }).then((res) => res.json());
};

// fetch classes record ids by student name
const fetchClassesByStudent = (name = '') => {
  const endpoint = `${BASE_URL}${AIRTABLE_BASE_ID}${AIRTABLE_TABLE_STUDENT}?filterByFormula=Name="${name}"&fields[]=Classes`;
  return fetchData(endpoint);
};

// fetch classes names and students ids from classes record ids
const fetchClassesInfo = (classids: [string]) => {
  const endpoint = `${BASE_URL}${AIRTABLE_BASE_ID}${AIRTABLE_TABLE_CLASSES}?filterByFormula=OR(${classids
    .map((val) => `RECORD_ID() = "${val}"`)
    .join(', ')})`;
  return fetchData(endpoint);
};

// fetch students names from students ids
const fetchStudentsNames = (studentids: [string]) => {
  const endpoint = `${BASE_URL}${AIRTABLE_BASE_ID}${AIRTABLE_TABLE_STUDENT}?filterByFormula=OR(${studentids
    .map((val) => `RECORD_ID() = "${val}"`)
    .join(', ')})&fields[]=Name`;
  return fetchData(endpoint);
};

// fetch class and its students list
export function fetchList(name = '') {
  const classList: [ClassInfo?] = [];
  fetchClassesByStudent(name).then((res: Result) => {
    const classids = res.records?.[0].fields.Classes;
    if (classids) {
      fetchClassesInfo(classids).then((res: Result) => {
        res.records.map((value) => {
          if (value.fields.Students && value.fields.Name) {
            fetchStudentsNames(value.fields.Students).then((res: Result) => {
              const eachClass: ClassInfo = {
                Name: value.fields.Name,
                Students: res.records.map((value) => value.fields.Name),
              };
            });
          }
        });
      });
    }
  });
}

If I change the ClassInfo interface to

interface ClassInfo {
  Name: string | undefined;
  Students: (string | undefined)[];
}

Then no error. I just want to know what is difference between (T)[] and [T]. Also want to know if the array could have no value, and what I should put in the interface.

CodePudding user response:

From an introductory chapter of TypeScript’s handbook:

Arrays

To specify the type of an array like [1, 2, 3], you can use the syntax number[]; this syntax works for any type (e.g. string[] is an array of strings, and so on). […]

Note that [number] is a different thing; refer to the section on Tuples.

TypeScript can ascribe types to arrays in two ways: T[] denotes an array of arbitrary length (possibly zero), which may vary at runtime, and whose elements are all of type T.

But TypeScript also supports arrays of fixed length whose individual elements are assigned independent types, which are written [T], [T, U], [T, U, V], etc. The latter kind of array is termed a tuple in TypeScript, but expect that terminology to change as the JavaScript Record and Tuple proposal advances and becomes integrated into the language. Here’s how the handbook describes them:

Tuple Types

A tuple type is another sort of Array type that knows exactly how many elements it contains, and exactly which types it contains at specific positions.

type StringNumberPair = [string, number];

Here, StringNumberPair is a tuple type of string and number. […] To the type system, StringNumberPair describes arrays whose 0 index contains a string and whose 1 index contains a number.

To apply it to your specific example: (string | undefined)[] is an array of any number of elements, each of which may be either a string or undefined independently of the others. [string | undefined] is an array containing exactly one element, which is either a string or undefined. As such, the latter is assignable to the former, but not vice versa.

CodePudding user response:

[T] is a tuple type. It denotes an array with one element of type T. T[] means an array with elements of type T.

  • Related