All Tracks/lecture working with generics and type narrowing/
Đang tải...
Hướng dẫn thử thách
1 / 2

What Are Generics, and How Do They Work?

You have actually seen a generic type in a previous lesson: `Array<string>`. But you'll usually use generic types in functions. In fact, they can be thought of as a special parameter you provide to a function to control the behavior of the function's type definition. Let's go back to our previous example of a function to get a random value from an array: ```js const getRandomValue = (array: string[]): string => { return array[Math.floor(Math.random() * array.length)]; } ``` Our function accepts an array of strings and returns a string. But what if we wanted to pass in an array of numbers and return a number? You could use a union type: ```js const getRandomValue = (array: (string|number)[]): (string|number) => { return array[Math.floor(Math.random() * array.length)]; } const val = getRandomValue([1, 2, 4]) ``` But with this approach, even though we have passed in an array of only numbers, TypeScript determines that the `val` variable could be a number OR a string. Instead, you can define a generic type for the function: ```js const getRandomValue = <T>(array: T[]): T => { return array[Math.floor(Math.random() * array.length)]; } const val = getRandomValue([1, 2, 4]) ``` There are a couple of important components in our new example. First, the `<T>` syntax tells TypeScript that you are defining a generic type `T` for the function. `T` is a common name for generic types, but you can actually name it whatever you want (within JavaScript's variable conventions). Then, we tell TypeScript that the array parameter is an array of values matching the generic type, and that the returned value is a single element of that same type. This allows TypeScript to properly detect that `val` will be a number, because the array we passed consists solely of numbers. But what about functions you don't control? Let's take a look at the `document.querySelector()` method: ```js const email = document.querySelector("#email"); console.log(email.value); ``` Because we're querying with an ID selector, TypeScript doesn't know what kind of element we are querying. It knows it's an `Element` of some sort, but our attempt to access the `value` property will throw an error because the top-level element interface does not have that property. Thankfully, we can pass a type argument to the function call: ```js const email = document.querySelector<HTMLInputElement>("#email"); console.log(email.value); ``` Notice how we're using the angle bracket syntax again (`<HTMLInputElement>`), but this time in a function call. This tells TypeScript that the element we expect to find will be an `input` element, and we no longer get an error on the value property because input elements do have that property. Of course, `querySelector` can return `null` if an element is not found, and TypeScript will throw a compiler error here because we do not handle that case. But you'll learn about that in the next lesson.
Vượt qua bài kiểm tra hiện tại để mở khóa bài tiếp theo.
main.ts
UTF-8 • Tab Size: 2Kiểm tra bài:⌘↵
Test Output
Thử thách này không có bài test tự động. Hãy quan sát kết quả trực tiếp ở khung Preview.