0

I'm refactoring a JS code into TS (actually jsx/tsx) and I'm facing a problem with functions.

To simplify the issue... let's suppose I get this function "checkIt", which can receive a string or number as parameter and returns a boolean.

This is the JS function:

const FIRST_ROW = 'Initial';
const SECOND_ROW = new Set([1, 2, 3, 4]);

const checkIt = id => {
if (FIRST_ROW.includes(id) || SECOND_ROW.includes(id)) {
    return true;
  }
  return false;
}

Here is my trial... (as I'm learning TS, I like to declare inferred variables to be consistent)

const FIRST_ROW: string = 'Initial';
const SECOND_ROW: Set<number> = new Set([1, 2, 3, 4]);

const checkIt = <T,>(id: T): boolean => {
  if (FIRST_ROW.includes(id) || SECOND_ROW.includes(id)) {
    return true;
  }
  return false;
}

This gets me an error on my my "id" references inside the function: Argument of type 'T' is not assignable to parameter of type 'string' (or 'number'). I've tried using function expression, the Union string | number (as explained here), different forms of writing Generics, and Overloads (like here and I just can't make it work.

Any help here?? Thank you!

Анна
  • 1,248
  • 15
  • 26

1 Answers1

4

How about using type casting? Just to hint the compiler:

const FIRST_ROW: string = 'Initial';
const SECOND_ROW: Set<number> = new Set([1, 2, 3, 4]);

const checkIt = (id: string | number): boolean => {
  if (FIRST_ROW.includes(id as string) || SECOND_ROW.has(id as number)) {
    return true;
  }
  return false;
}

playground

Also, Set does not have an include method.

To make it completely appropriate you first check if it's really a string. Because you use the union string|number the compiler knows that if typeof id === 'string' returns false, then id has to be a number, so casting is not necessary:

const FIRST_ROW: string = 'Initial';
const SECOND_ROW: Set<number> = new Set([1, 2, 3, 4]);

const checkIt = (id: string | number): boolean =>
  typeof id === 'string' ? FIRST_ROW.includes(id) : SECOND_ROW.has(id)
;

playground

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • Great! Thanks. About the *Set.includes* it was an error while writing it down here. – Анна Apr 23 '21 at 19:26
  • One question though @Poul ... Is it normal in TS to use plenties of *typeof* to constrain types? I've seen on the docs the use of it, but it didn´t sound natural to me, as it looked like I was overflowing my code with more text and logic that could be avoided with another way more simple and elegant... – Анна Apr 23 '21 at 19:30
  • 1
    @Анна if you have a union parameter, then you should definitely check before doing :) – Poul Kruijt Apr 23 '21 at 20:00