# ARTICLE: Generic functions are everywhere

In our last lesson, we doubled down on generic types - adding constraints and defaults to them. In this lesson, we're going to start our exploration of generic functions.

## What Are Generic Functions?

The phrase 'generic function' can feel extremely scary. But it has a pretty simple definition.

A 'normal' function is one that takes zero or more _runtime_ arguments. An `add` function, for example, takes two numbers and returns their sum:

```ts twoslash
const add = (a: number, b: number) => a + b;
```

A generic function is exactly the same, with one additional feature: it can receive _type arguments_.

```ts twoslash
const uniqueArray = <T>(array: T[]) => {
  return Array.from(new Set(array));
};
```

In this example, `uniqueArray` is a generic function. It defines a single type parameter, `T`, and a single runtime argument, `array`.

Without the type parameter, `uniqueArray` would be a normal function.

So, the same rules apply to generic types as they do to generic functions. Got a type parameter? It's a _generic_ function/type. No type parameter? It's a _non-generic_ (I usually say "normal") function/type.

## Passing Type Arguments To Generic Functions

You might not realize it, but you've likely used generic functions a lot. TypeScript's built-in typings for JavaScript, which ship with every TypeScript installation, are full of generic functions.

A classic example is a `Set`. A `Set` is a collection of unique values. Let's say you wanted to create a `Set` without passing it an initial value:

```ts twoslash
const set = new Set();
```

How does TypeScript know what type of values are in the `Set`? It doesn't!

This means we can pass any sort of value to the `Set`:

```ts twoslash
const set = new Set();

// ---cut---
set.add(1);
set.add("hello");
set.add({ key: "value" });
```

As it turns out, `Set` is a generic function. It has a type parameter, `T`, which defaults to `unknown`. If we want to specify what types should be included in our `Set`, we can pass a type argument:

```ts twoslash
const numberSet = new Set<number>();
```

We use the angle brackets (`<` and `>`) to pass the type argument inside. Now, TypeScript knows that `numberSet` can only contain numbers:

```ts twoslash
// @errors: 2345
const numberSet = new Set<number>();

// ---cut---
numberSet.add(1);
numberSet.add("hello");
```

## Non-Generic Functions

There are many other examples of commonly-used functions. `document.getElementById`. `Map`, `Array`. `useState` in React.

But some functions are _not_ generic. `JSON.parse` is a good example. If we try to tell `JSON.parse` what type we expect it to return, TypeScript will throw an error:

```ts twoslash
// @errors: 2558
const parsed = JSON.parse<number>("42");
```

It 'expected 0 type arguments, but got 1'. This is because `JSON.parse` is not a generic function - it doesn't accept type arguments.

Another example is `fetch`. A common pattern when fetching from a server is to parse the response as JSON:

```ts twoslash
// @errors: 2558
// @moduleDetection: force
// @module: esnext
// @target: esnext

type Todo = {
  id: number;
  title: string;
  completed: boolean;
};

// ---cut---
const result = await fetch("/todos/1").then((response) =>
  response.json(),
);
```

But, if we attempt to pass a type argument to `response.json`, TypeScript will throw an error:

```ts twoslash
// @errors: 2558
// @moduleDetection: force
// @module: esnext
// @target: esnext

type Todo = {
  id: number;
  title: string;
  completed: boolean;
};

// ---cut---
const result = await fetch("/todos/1").then((response) =>
  response.json<Todo>(),
);
```

The way to handle these functions is either to cast their results (using `as Todo` or `as number`) or, since they return `any`, type their results using a variable annotation:

```ts twoslash
// @moduleDetection: force
// @module: esnext
// @target: esnext

type Todo = {
  id: number;
  title: string;
  completed: boolean;
};

// ---cut---
// Casting
const result1 = JSON.parse("42") as number;

// Variable annotation
const result: Todo = await fetch("/todos/1").then(
  (response) => response.json(),
);
```

You might be wondering why these functions aren't generic. We'll look at that in a future lesson.

## Summary

- All functions can receive runtime arguments. Generic functions can also receive type arguments.
- Type arguments can be used to specify the types of values that a function should work with.
- You can pass type arguments to generic functions using angle brackets (`<` and `>`).
- Not all functions are generic. Some functions, like `JSON.parse` and `fetch` do not receive type arguments.

In our next lesson, we'll start writing our own generic functions, and figure out what they're useful for.

Want to get the next lesson now? Click the link below.
