Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

228
Visualizações
JS to TS: Type 'null' is not assignable to type 'number'

I am new to TypeScript and have just started migrating my application from JavaScript to TypeScript.

  1. First function: calcAvg, takes an array of numbers and returns their average.
  2. Second function: avgRoasDiscrepancy, takes two arrays, if the two arrays are of equal length and with no null values, it will subtract each element from one list with the element in the same index from the second array.

The issue is in the following map function (see full code below):

const discArray = clientRoasArray.map((value: number, index: number) => value - roasArray[index]);

I get the following error:

Argument of type '(value: number, index: number) => number' is not assignable to parameter of type '(value: number | null, index: number, array: (number | null)[]) => number'.
Types of parameters 'value' and 'value' are incompatible.
Type 'number | null' is not assignable to type 'number'.
Type 'null' is not assignable to type 'number'

I don't know how to "convince" TypeScript that both value and roasArray[index] are in fact numbers and not nulls.

Here is the complete code :

interface DailyData {
  id: number
  clientCost:number
  conValue:number
  clientConvValue:number
  margin: number

}

const calcAvg = (dataList: number[]) => {
  const reducer = (accumulator: number, curr: number) => accumulator + curr;
  const dataSum = dataList.reduce(reducer, 0);
  return dataSum / dataList.length;
};


const avgRoasDiscrepancy = (advertiserStats: DailyData[]) => {
  const clientRoasArray = advertiserStats.map((obj: DailyData) => obj.clientCost > 0 ? obj.clientConvValue/obj.clientCost: null);
  const roasArray = advertiserStats.map((obj: DailyData) => obj.clientCost > 0 ? obj.conValue/obj.clientCost: null);
  if (clientRoasArray.length === 0 || roasArray.length === 0) {
    return 'no data'
  }
  if (!!clientRoasArray.every((el: number|null) => el!== null) || (!roasArray.every((el: number|null) => el!== null) )) {
    //if one of the arrays has null values don't calculate
    return 'no data';
  }
  if (clientRoasArray.length === roasArray.length) {
    const discArray = clientRoasArray.map((value: number, index: number) => value - roasArray[index]);
    return calcAvg(discArray as number[]);
  }
  return 'no data';

};
over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

In this line

  const clientRoasArray = advertiserStats.map((obj: DailyData) => obj.clientCost > 0 ? obj.clientConvValue/obj.clientCost: null);

You are assuming that the elements of clientRoasArray could be number or could be null and this is clear in your condition : null

And in this line, you are identifying the value of the clientRoasArray as number only which is wrong because you told your code that the value could be number|null

All you need is to change this line

const discArray = clientRoasArray.map((value: number, index: number) => value - roasArray[index]);

to this

const discArray = clientRoasArray.map((value: number | null, index: number) => value - roasArray[index]);

but you will face an issue with roasArray[index] because it also could be null

over 4 years ago · Santiago Trujillo Relatório

0

I wasn't able to get type inference to work properly using the every calls on the arrays, however you can make a type guard to help the compiler understand that the arrays are of type number[] instead of (number | null)[]. This will also help with refactoring a bit.

Note that there's also an issue with your current type checking logic, but looks like it's just a typo: the !! before the first condition should just be a single !.

Here's a simple type guard:

function isNonNullNumberArray(x: (number | null)[]): x is number[] {
    return x.every(e => e !== null);
}

Then you can use isNonNullNumberArray like this:

  if (!(isNonNullNumberArray(clientRoasArray) && isNonNullNumberArray(roasArray))) {
    //if one of the arrays has null values don't calculate
    return 'no data';
  }
  // now the compiler knows that neither array contains null values
  if (clientRoasArray.length === roasArray.length) {
    const discArray = clientRoasArray.map((value: number, index: number) => value - roasArray[index]);
    return calcAvg(discArray);
  }
  return 'no data';

You could make a more general type guard like this too if you wanted using generics so that it works for types other than number:

function isNonNullArray<T>(x: T[]): x is Exclude<T, null>[] {
    return x.every(e => e !== null);
}

By the way, you don't need to explicitly declare parameter types in functions passed to map and other array method as the compiler can infer the types based on the signature of the array method (e.g. map).

over 4 years ago · Santiago Trujillo Relatório

0

You could check if your variable is not null and use ! (non-null assertion operator) to tell TypeScript the expression can not be null. Also the type for value is number | null.

if (clientRoasArray.length === roasArray.length) {
  const discArray = clientRoasArray.map((value: number | null, index: number) => {
    return value && roasArray[index] ? value - roasArray[index]! : null
  });
  return calcAvg(discArray as number[]);
}
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda