{"id":2219,"date":"2023-09-27T02:57:18","date_gmt":"2023-09-27T02:57:18","guid":{"rendered":"https:\/\/easycodingschool.com\/?p=2219"},"modified":"2023-09-27T03:08:12","modified_gmt":"2023-09-27T03:08:12","slug":"exploring-advanced-type-inference-in-typescript","status":"publish","type":"post","link":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/","title":{"rendered":"Exploring Advanced Type Inference in TypeScript"},"content":{"rendered":"<p>TypeScript, the statically-typed superset of JavaScript, is well-known for its powerful type system. As developers delve deeper into TypeScript, they discover advanced type inference techniques that can make code more expressive and robust. In this article, we&#8217;ll explore some of these advanced type inference features.<\/p>\n<h2>Conditional Types<\/h2>\n<p>Conditional types are a fascinating feature in TypeScript that allow us to conditionally select types based on some criteria. The <code>infer<\/code> keyword within conditional types is especially intriguing. Consider the following example:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type IsArray&lt;T&gt; = T extends Array&lt;any&gt; ? true : false;\r\ntype Result = IsArray&lt;number[]&gt;; \/\/ Result is true<\/code><\/pre>\n<\/div>\n<p><span>In this code, the <\/span><code>IsArray<\/code><span> type checks whether the provided type <\/span><code>T<\/code><span> is an array or not, returning <\/span><code>true<\/code><span> if it is and <\/span><code>false<\/code><span> otherwise. Conditional types are incredibly useful for creating complex type mappings.<\/span><\/p>\n<p>Example:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>function getUserInfo&lt;T extends 'id' | 'name'&gt;(key: T): T extends 'id' ? number : string {\r\nif (key === 'id') {\r\nreturn 123; \/\/ Assume this is a user ID (number)\r\n} else {\r\nreturn 'John Doe'; \/\/ Assume this is the user's name (string)\r\n}\r\n}\r\n\r\nconst userId: number = getUserInfo('id'); \/\/ Valid, userId is a number\r\nconst userName: string = getUserInfo('name'); \/\/ Valid, userName is a string<\/code><\/pre>\n<\/div>\n<p>In this example:<\/p>\n<ul>\n<li>The <code>getUserInfo<\/code> function takes a <code>key<\/code> parameter that can be either <code>'id'<\/code> or <code>'name'<\/code>.<\/li>\n<li>We use a conditional type to specify that if <code>key<\/code> is <code>'id'<\/code>, the function returns a <code>number<\/code> (the user&#8217;s ID), and if <code>key<\/code> is <code>'name'<\/code>, it returns a <code>string<\/code> (the user&#8217;s name).<\/li>\n<\/ul>\n<p>When you call <code>getUserInfo('id')<\/code>, TypeScript infers that the return type is <code>number<\/code>, and when you call <code>getUserInfo('name')<\/code>, it infers that the return type is <code>string<\/code>. This conditional typing allows you to have different return types based on the condition, making your code type-safe.<\/p>\n<h2>Mapped Types<\/h2>\n<p>Mapped types offer a way to create new types by transforming the properties of an existing type. Let&#8217;s take a common example: making all properties of an object optional.<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type Partial&lt;T&gt; = {\r\n[K in keyof T]?: T[K];\r\n};<\/code><\/pre>\n<\/div>\n<p>With this <code>Partial<\/code> type, you can easily make any object&#8217;s properties optional. This can be a game-changer when you&#8217;re working with APIs and want to describe optional parameters.<\/p>\n<p>Suppose you have an interface representing a basic user object:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>interface User {\r\nid: number;\r\nname: string;\r\nemail: string;\r\n}<\/code><\/pre>\n<\/div>\n<p><span>Now, you want to create a new type that makes all properties of this user object optional. You can use a mapped type for this:<\/span><\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type PartialUser = {\r\n[K in keyof User]?: User[K];\r\n};<\/code><\/pre>\n<\/div>\n<p>In this example:<\/p>\n<ul>\n<li><code>[K in keyof User]<\/code> iterates over all the keys (<code>id<\/code>, <code>name<\/code>, and <code>email<\/code>) in the <code>User<\/code> interface.<\/li>\n<li><code>?: User[K]<\/code> makes each property optional by adding the <code>?<\/code> modifier.<\/li>\n<\/ul>\n<p>Now, let&#8217;s use the <code>PartialUser<\/code> type:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const partialUser: PartialUser = {\r\nid: 1,\r\n};<\/code><\/pre>\n<\/div>\n<p><span>Here, <\/span><code>partialUser<\/code><span> is of type <\/span><code>PartialUser<\/code><span>, and you&#8217;re allowed to omit properties like <\/span><code>name<\/code><span> and <\/span><code>email<\/code><span> while retaining the <\/span><code>id<\/code><span> property. This demonstrates how mapped types can help you create new types that are based on the structure of existing types but with specific modifications.<\/span><\/p>\n<h2>Template Literal Types<\/h2>\n<p>Introduced in TypeScript 4.1, template literal types enable you to create string literal types by concatenating other string literals. Here&#8217;s an example:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type EventName = `on${string}`;\r\nconst onClick: EventName = 'onclick'; \/\/ Valid<\/code><\/pre>\n<\/div>\n<p>Template literal types are a powerful tool for creating types that match specific string patterns, such as event names or API endpoints.<\/p>\n<ol>\n<li><strong><code>type EventName = <\/code>on${string}<code>;<\/code><\/strong>: Here, you&#8217;re defining a new type called <code>EventName<\/code>. This type uses a template literal type to create string literal types. The template literal <code>on${string}<\/code> specifies that the <code>EventName<\/code> type should start with the string &#8220;on&#8221; and be followed by any string (<code>${string}<\/code>). This means that <code>EventName<\/code> can only represent string values that start with &#8220;on&#8221;.<\/li>\n<li><strong><code>const onClick: EventName = 'onclick';<\/code><\/strong>: You&#8217;re declaring a constant <code>onClick<\/code> with the type <code>EventName<\/code>. Since <code>EventName<\/code> is defined as a template literal type that starts with &#8220;on&#8221;, assigning the string literal <code>'onclick'<\/code> to it is valid because it matches the pattern defined by the type.<\/li>\n<\/ol>\n<p>Essentially, this code enforces that the <code>onClick<\/code> variable can only hold string values that start with &#8220;on&#8221;. Any attempt to assign a string that doesn&#8217;t conform to this pattern would result in a TypeScript type error.<\/p>\n<p>Here are some examples to illustrate the behavior:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const onClick1: EventName = 'onclick'; \/\/ Valid\r\nconst onClick2: EventName = 'onmousedown'; \/\/ Valid\r\nconst invalidEvent: EventName = 'hover'; \/\/ Error: Type '\"hover\"' is not assignable to type 'EventName'.<\/code><\/pre>\n<\/div>\n<p><span>In the last example, TypeScript correctly identifies that the string <\/span><code>'hover'<\/code><span> does not match the expected pattern defined by the <\/span><code>EventName<\/code><span> type and reports a type error. This demonstrates how template literal types can be used to create highly specific and constrained string literal types in TypeScript.<\/span><\/p>\n<h2>Infer in Conditional Types<\/h2>\n<p>The <code>infer<\/code> keyword can be used within conditional types to extract types from other types. A common use case is creating a utility type to extract the return type of a function:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>\/\/ Define a conditional type ReturnType&lt;T&gt; that extracts the return type of a function\r\ntype ReturnType&lt;T&gt; = T extends (...args: any[]) =&gt; infer R ? R : never;\r\n\r\n\/\/ Define a simple function\r\nfunction add(a: number, b: number): number {\r\nreturn a + b;\r\n}\r\n\r\n\/\/ Use the ReturnType type to infer the return type of the 'add' function\r\ntype Result = ReturnType&lt;typeof add&gt;; \/\/ Result is number<\/code><\/pre>\n<\/div>\n<ol>\n<li><strong><code>type ReturnType&lt;T&gt; = T extends (...args: any[]) =&gt; infer R ? R : never;<\/code><\/strong>: This defines a conditional type <code>ReturnType<\/code>. It checks if the type <code>T<\/code> extends a function type that takes any number of arguments (<code>(...args: any[])<\/code>) and uses the <code>infer<\/code> keyword to capture the inferred return type <code>R<\/code>. If the condition is met, it returns <code>R<\/code>; otherwise, it returns <code>never<\/code>.<\/li>\n<li><strong><code>function add(a: number, b: number): number { ... }<\/code><\/strong>: This is a simple addition function that takes two numbers and returns their sum.<\/li>\n<li><strong><code>type Result = ReturnType&lt;typeof add&gt;;<\/code><\/strong>: Here, you&#8217;re using the <code>ReturnType<\/code> type to infer the return type of the <code>add<\/code> function. Since <code>add<\/code> returns a <code>number<\/code>, the <code>Result<\/code> type is inferred as <code>number<\/code>.<\/li>\n<\/ol>\n<p>You can use this mechanism to automatically determine the return type of functions, which is especially helpful for cases where the return type depends on complex logic or input types.<\/p>\n<p>Here are some additional examples:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>function greet(name: string): string {\r\nreturn `Hello, ${name}!`;\r\n}\r\n\r\ntype GreetResult = ReturnType&lt;typeof greet&gt;; \/\/ GreetResult is string\r\n\r\nfunction divide(a: number, b: number): number {\r\nreturn a \/ b;\r\n}\r\n\r\ntype DivideResult = ReturnType&lt;typeof divide&gt;; \/\/ DivideResult is number<\/code><\/pre>\n<\/div>\n<p><span>In each case, TypeScript correctly infers the return type of the function, making your code more type-safe and maintainable.<\/span><\/p>\n<h2>Mapped Types with Conditional Types<\/h2>\n<p>Combining mapped types and conditional types can lead to advanced type transformations. For instance, you can create a mapped type that makes all methods of a class asynchronous:<\/p>\n<p><span>Suppose you have an interface <\/span><code>Person<\/code><span> representing individuals with different properties:<\/span><\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>interface Person {\r\nname: string;\r\nage: number;\r\nhasEmail: boolean;\r\n}<\/code><\/pre>\n<\/div>\n<p>Now, you want to create a new type that transforms all properties of Person to be optional if the property name starts with &#8220;has.&#8221; You can achieve this using mapped types with conditional types:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type TransformPerson&lt;T&gt; = {\r\n[K in keyof T]: K extends `has${infer U}` ? boolean : T[K];\r\n};<\/code><\/pre>\n<\/div>\n<p>In this example:<\/p>\n<ul>\n<li><code>[K in keyof T]<\/code> iterates over all the keys (<code>name<\/code>, <code>age<\/code>, and <code>hasEmail<\/code>) in the <code>Person<\/code> interface.<\/li>\n<li><code>K extends <\/code>has${infer U}<code> ? boolean : T[K]<\/code> checks whether each property key starts with &#8220;has.&#8221; If it does, the property is transformed to a boolean type; otherwise, it remains unchanged.<\/li>\n<\/ul>\n<p>Now, let&#8217;s use the <code>TransformPerson<\/code> type:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const person: TransformPerson&lt;Person&gt; = {\r\nname: 'Alice',\r\nage: 30,\r\nhasEmail: true,\r\n};\r\n\r\nconst optionalPerson: Partial&lt;Person&gt; = person; \/\/ This works because properties are optional now<\/code><\/pre>\n<\/div>\n<p>In this example:<\/p>\n<ul>\n<li><code>person<\/code> is of type <code>TransformPerson&lt;Person&gt;<\/code>, which means that all properties starting with &#8220;has&#8221; are of type <code>boolean<\/code>, and other properties retain their original types.<\/li>\n<li><code>optionalPerson<\/code> is of type <code>Partial&lt;Person&gt;<\/code> because all properties are now optional. This allows you to create an object where you can omit some or all properties safely.<\/li>\n<\/ul>\n<p><span>Mapped types with conditional types are incredibly useful when you need to transform or modify properties based on certain conditions while preserving the type safety of the original interface.<\/span><\/p>\n<h2>Keyof and Lookup Types<\/h2>\n<p>The <code>keyof<\/code> operator allows you to extract keys from an object and use them to access corresponding property types. For example:<\/p>\n<p>Suppose you have an object representing a user with various properties:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const user = {\r\nid: 1,\r\nusername: 'john_doe',\r\nemail: 'john@example.com',\r\n};<\/code><\/pre>\n<\/div>\n<p><span>Now, let&#8217;s say you want to create a utility function that allows you to access the values of specific properties using their names. You can use <\/span><code>keyof<\/code><span> to extract the keys of the object and lookup types to access their corresponding types:<\/span><\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>function getProperty&lt;T, K extends keyof T&gt;(obj: T, key: K): T[K] {\r\nreturn obj[key];\r\n}\r\n\r\nconst userId: number = getProperty(user, 'id'); \/\/ userId is inferred as number\r\nconst username: string = getProperty(user, 'username'); \/\/ username is inferred as string\r\nconst userEmail: string = getProperty(user, 'email'); \/\/ userEmail is inferred as string<\/code><\/pre>\n<\/div>\n<p>In this example:<\/p>\n<ul>\n<li>The <code>getProperty<\/code> function takes two type parameters: <code>T<\/code> (the type of the object) and <code>K<\/code> (the type of the property key).<\/li>\n<li>It accepts an object (<code>obj<\/code>) and a property key (<code>key<\/code>), and it returns the value of the specified property from the object.<\/li>\n<li>The <code>&lt;K extends keyof T&gt;<\/code> constraint ensures that the property key (<code>K<\/code>) is a valid key of the object&#8217;s type (<code>T<\/code>).<\/li>\n<\/ul>\n<p>By using <code>keyof T<\/code>, you can dynamically access the properties of the object while maintaining type safety. If you try to access a property that doesn&#8217;t exist on the object, TypeScript will catch the error at compile time.<\/p>\n<p>Here are some additional examples:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const invalidProperty = getProperty(user, 'age'); \/\/ Error: Property 'age' does not exist on type '{ id: number; username: string; email: string; }'.<\/code><\/pre>\n<\/div>\n<p>In this case, TypeScript correctly identifies that there is no &#8216;age&#8217; property on the <code>user<\/code> object and reports a type error.<\/p>\n<p>Keyof and lookup types are especially useful when you need to work with dynamic property access or when you want to ensure that you&#8217;re using valid property names and their corresponding types at compile time.<\/p>\n<h2>Inference for Array Element Types<\/h2>\n<p>You can infer the element type of an array using conditional types and <code>infer<\/code>:<\/p>\n<p>Suppose you have an array with various types of elements:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const mixedArray = [1, 'two', true, { name: 'Alice' }];<\/code><\/pre>\n<\/div>\n<p><span>Now, you want to create a utility function that infers the type of the elements within the array. You can use conditional types and inference for this purpose:<\/span><\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type ArrayElementType&lt;T&gt; = T extends (infer U)[] ? U : never;\r\n\r\nfunction getFirstElement&lt;T&gt;(arr: T[]): ArrayElementType&lt;T&gt; {\r\nreturn arr[0];\r\n}\r\n\r\nconst firstElement: number | string | boolean | { name: string } = getFirstElement(mixedArray);<\/code><\/pre>\n<\/div>\n<p>In this example:<\/p>\n<ul>\n<li>The <code>ArrayElementType&lt;T&gt;<\/code> type uses a conditional type to check if <code>T<\/code> extends an array of some type (<code>T extends (infer U)[]<\/code>). If it does, it infers the element type <code>U<\/code>; otherwise, it returns <code>never<\/code>.<\/li>\n<li>The <code>getFirstElement<\/code> function takes an array of type <code>T<\/code> and returns the inferred element type using <code>ArrayElementType&lt;T&gt;<\/code>.<\/li>\n<\/ul>\n<p>When you call <code>getFirstElement(mixedArray)<\/code>, TypeScript infers the type of <code>firstElement<\/code> based on the elements in the <code>mixedArray<\/code>. In this case, <code>firstElement<\/code> is inferred as <code>number | string | boolean | { name: string }<\/code>, which represents all possible types of elements in the array.<\/p>\n<p>Here are some additional examples:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>const numbers = [1, 2, 3, 4, 5];\r\nconst strings = ['apple', 'banana', 'cherry'];\r\n\r\nconst firstNumber: number = getFirstElement(numbers);\r\nconst firstString: string = getFirstElement(strings);<\/code><\/pre>\n<\/div>\n<p>In each case, the <code>getFirstElement<\/code> function dynamically infers the element type of the array and ensures type safety.<\/p>\n<p>This is particularly useful when you&#8217;re working with arrays of unknown or heterogeneous types and need to perform operations based on the inferred element type.<\/p>\n<h2>Recursive Types<\/h2>\n<p>In TypeScript, you can create recursive types to model structures like linked lists or trees:<\/p>\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-ts\" data-lang=\"TypeScript\"><code>type ListNode&lt;T&gt; = { value: T; next?: ListNode&lt;T&gt; };\r\ntype LinkedList&lt;T&gt; = ListNode&lt;T&gt; | undefined;\r\n\r\n\/\/ Create a linked list of numbers\r\nconst node1: ListNode&lt;number&gt; = { value: 1 };\r\nconst node2: ListNode&lt;number&gt; = { value: 2 };\r\nconst node3: ListNode&lt;number&gt; = { value: 3 };\r\n\r\nnode1.next = node2;\r\nnode2.next = node3;\r\n\r\n\/\/ Linked list traversal\r\nfunction printLinkedList&lt;T&gt;(head: LinkedList&lt;T&gt;) {\r\nlet current: LinkedList&lt;T&gt; = head;\r\nwhile (current) {\r\nconsole.log(current.value);\r\ncurrent = current.next;\r\n}\r\n}\r\n\r\n\/\/ Print the linked list\r\nprintLinkedList(node1); \/\/ Outputs: 1, 2, 3<\/code><\/pre>\n<\/div>\n<ul>\n<li><code>ListNode&lt;T&gt;<\/code> represents a node in the linked list, containing a <code>value<\/code> of type <code>T<\/code> and an optional <code>next<\/code> property pointing to the next node in the list.<\/li>\n<li><code>LinkedList&lt;T&gt;<\/code> is a type alias that can be either a <code>ListNode&lt;T&gt;<\/code> or <code>undefined<\/code>, representing the head of the linked list. It&#8217;s <code>undefined<\/code> when the list is empty.<\/li>\n<li>We create three nodes (<code>node1<\/code>, <code>node2<\/code>, and <code>node3<\/code>) and link them together to form a simple linked list of numbers.<\/li>\n<li>The <code>printLinkedList<\/code> function takes the head of the linked list and traverses it, printing each value.<\/li>\n<\/ul>\n<p>When we call <code>printLinkedList(node1)<\/code>, it prints the values <code>1<\/code>, <code>2<\/code>, and <code>3<\/code>, demonstrating how the recursive type <code>ListNode&lt;T&gt;<\/code> allows us to create and work with linked lists in a type-safe manner.<\/p>\n<div class=\"group w-full text-token-text-primary border-b border-black\/10 gizmo:border-0 dark:border-gray-900\/50 gizmo:dark:border-0 bg-gray-50 gizmo:bg-transparent dark:bg-[#444654] gizmo:dark:bg-transparent\" data-testid=\"conversation-turn-25\">\n<div class=\"p-4 justify-center text-base md:gap-6 md:py-6 m-auto\">\n<div class=\"flex flex-1 gap-4 text-base mx-auto md:gap-6 gizmo:gap-3 md:max-w-2xl lg:max-w-[38rem] xl:max-w-3xl }\">\n<div class=\"relative flex w-[calc(100%-50px)] flex-col gap-1 md:gap-3 lg:w-[calc(100%-115px)] agent-turn\">\n<div class=\"flex flex-grow flex-col gap-3 max-w-full\">\n<div class=\"min-h-[20px] flex flex-col items-start gap-3 overflow-x-auto whitespace-pre-wrap break-words\">\n<div class=\"markdown prose w-full break-words dark:prose-invert light\">\n<p>This example showcases the power of recursive types in modeling recursive data structures, providing type safety and clarity in your code.<br \/>\n<span style=\"font-size: 1rem;\"><\/span><\/p>\n<p><span style=\"font-size: 1rem;\">Recursive types enable you to define complex data structures with confidence.<\/span><\/p>\n<p><span>You can also discover a lot about\u00a0<\/span><a href=\"https:\/\/easycodingschool.com\/blog\/category\/javascript\/\">Javascript by exploring<span>\u00a0<\/span><\/a><span>different topics.<\/span><\/p>\n<p><strong>Note:<\/strong><span>\u00a0We welcome your feedback at\u00a0<\/span><a href=\"https:\/\/easycodingschool.com\/blog\/\">Easy Coding School<\/a><span>. Please don\u2019t hesitate to share your\u00a0<\/span><a href=\"https:\/\/easycodingschool.com\/blog\/contact\/\" target=\"_blank\" rel=\"noopener\">suggestions<\/a><span>\u00a0or any issues you might have with the article!<\/span><\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.<\/p>\n","protected":false},"author":1,"featured_media":2221,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_themeisle_gutenberg_block_has_review":false,"footnotes":""},"categories":[87,4,25,5,175],"tags":[127,108,126,64,207,184,182,193,178],"class_list":["post-2219","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development","category-lifestyle","category-programming","category-technology","category-typescript","tag-easy-coding","tag-easy-coding-school","tag-easycoding","tag-easycodingschool","tag-type-inference-in-typescript","tag-typescript","tag-typescript-basic","tag-typescript-programming","tag-typescript-tutorial"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Exploring Advanced Type Inference in TypeScript - Easy Coding School<\/title>\n<meta name=\"description\" content=\"Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Exploring Advanced Type Inference in TypeScript - Easy Coding School\" \/>\n<meta property=\"og:description\" content=\"Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\" \/>\n<meta property=\"og:site_name\" content=\"Easy Coding School\" \/>\n<meta property=\"article:published_time\" content=\"2023-09-27T02:57:18+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-09-27T03:08:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"660\" \/>\n\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"gauravkumarjha19@gmail.com\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"gauravkumarjha19@gmail.com\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\"},\"author\":{\"name\":\"gauravkumarjha19@gmail.com\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/#\/schema\/person\/9cabe8e90728da7f26676cbd1744558b\"},\"headline\":\"Exploring Advanced Type Inference in TypeScript\",\"datePublished\":\"2023-09-27T02:57:18+00:00\",\"dateModified\":\"2023-09-27T03:08:12+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\"},\"wordCount\":1551,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg\",\"keywords\":[\"Easy Coding\",\"Easy Coding School\",\"EasyCoding\",\"EasyCodingSchool\",\"Type Inference in TypeScript\",\"Typescript\",\"typescript basic\",\"Typescript Programming\",\"typescript tutorial\"],\"articleSection\":[\"Development\",\"Lifestyle\",\"Programming\",\"Technology\",\"TypeScript\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\",\"url\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\",\"name\":\"Exploring Advanced Type Inference in TypeScript - Easy Coding School\",\"isPartOf\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg\",\"datePublished\":\"2023-09-27T02:57:18+00:00\",\"dateModified\":\"2023-09-27T03:08:12+00:00\",\"description\":\"Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.\",\"breadcrumb\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage\",\"url\":\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg\",\"contentUrl\":\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg\",\"width\":660,\"height\":350,\"caption\":\"Exploring Advanced Type Inference in TypeScript\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/easycodingschool.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Exploring Advanced Type Inference in TypeScript\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/#website\",\"url\":\"https:\/\/easycodingschool.com\/blog\/\",\"name\":\"Easy Coding School\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/easycodingschool.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/#organization\",\"name\":\"Easy Coding School\",\"url\":\"https:\/\/easycodingschool.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/07\/New-Project-10.png\",\"contentUrl\":\"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/07\/New-Project-10.png\",\"width\":310,\"height\":114,\"caption\":\"Easy Coding School \"},\"image\":{\"@id\":\"https:\/\/easycodingschool.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/#\/schema\/person\/9cabe8e90728da7f26676cbd1744558b\",\"name\":\"gauravkumarjha19@gmail.com\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/easycodingschool.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6846a3cc9bd6cb5b779aef260fe379c4b93fa20e1a4c753eb023ff7c08d7c668?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6846a3cc9bd6cb5b779aef260fe379c4b93fa20e1a4c753eb023ff7c08d7c668?s=96&d=mm&r=g\",\"caption\":\"gauravkumarjha19@gmail.com\"},\"sameAs\":[\"https:\/\/easycodingschool.com\/blog\"],\"url\":\"https:\/\/easycodingschool.com\/blog\/author\/gauravkumarjha19gmail-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Exploring Advanced Type Inference in TypeScript - Easy Coding School","description":"Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/","og_locale":"en_US","og_type":"article","og_title":"Exploring Advanced Type Inference in TypeScript - Easy Coding School","og_description":"Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.","og_url":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/","og_site_name":"Easy Coding School","article_published_time":"2023-09-27T02:57:18+00:00","article_modified_time":"2023-09-27T03:08:12+00:00","og_image":[{"width":660,"height":350,"url":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg","type":"image\/jpeg"}],"author":"gauravkumarjha19@gmail.com","twitter_card":"summary_large_image","twitter_misc":{"Written by":"gauravkumarjha19@gmail.com","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#article","isPartOf":{"@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/"},"author":{"name":"gauravkumarjha19@gmail.com","@id":"https:\/\/easycodingschool.com\/blog\/#\/schema\/person\/9cabe8e90728da7f26676cbd1744558b"},"headline":"Exploring Advanced Type Inference in TypeScript","datePublished":"2023-09-27T02:57:18+00:00","dateModified":"2023-09-27T03:08:12+00:00","mainEntityOfPage":{"@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/"},"wordCount":1551,"commentCount":0,"publisher":{"@id":"https:\/\/easycodingschool.com\/blog\/#organization"},"image":{"@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage"},"thumbnailUrl":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg","keywords":["Easy Coding","Easy Coding School","EasyCoding","EasyCodingSchool","Type Inference in TypeScript","Typescript","typescript basic","Typescript Programming","typescript tutorial"],"articleSection":["Development","Lifestyle","Programming","Technology","TypeScript"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/","url":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/","name":"Exploring Advanced Type Inference in TypeScript - Easy Coding School","isPartOf":{"@id":"https:\/\/easycodingschool.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage"},"image":{"@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage"},"thumbnailUrl":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg","datePublished":"2023-09-27T02:57:18+00:00","dateModified":"2023-09-27T03:08:12+00:00","description":"Unlock the power of advanced type inference in TypeScript, enhancing type safety and expressiveness in your code.","breadcrumb":{"@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#primaryimage","url":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg","contentUrl":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/09\/Exploring-Advanced-Type-Inference-in-TypeScript.jpg","width":660,"height":350,"caption":"Exploring Advanced Type Inference in TypeScript"},{"@type":"BreadcrumbList","@id":"https:\/\/easycodingschool.com\/blog\/exploring-advanced-type-inference-in-typescript\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/easycodingschool.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Exploring Advanced Type Inference in TypeScript"}]},{"@type":"WebSite","@id":"https:\/\/easycodingschool.com\/blog\/#website","url":"https:\/\/easycodingschool.com\/blog\/","name":"Easy Coding School","description":"","publisher":{"@id":"https:\/\/easycodingschool.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/easycodingschool.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/easycodingschool.com\/blog\/#organization","name":"Easy Coding School","url":"https:\/\/easycodingschool.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/easycodingschool.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/07\/New-Project-10.png","contentUrl":"https:\/\/easycodingschool.com\/blog\/wp-content\/uploads\/2023\/07\/New-Project-10.png","width":310,"height":114,"caption":"Easy Coding School "},"image":{"@id":"https:\/\/easycodingschool.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/easycodingschool.com\/blog\/#\/schema\/person\/9cabe8e90728da7f26676cbd1744558b","name":"gauravkumarjha19@gmail.com","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/easycodingschool.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6846a3cc9bd6cb5b779aef260fe379c4b93fa20e1a4c753eb023ff7c08d7c668?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6846a3cc9bd6cb5b779aef260fe379c4b93fa20e1a4c753eb023ff7c08d7c668?s=96&d=mm&r=g","caption":"gauravkumarjha19@gmail.com"},"sameAs":["https:\/\/easycodingschool.com\/blog"],"url":"https:\/\/easycodingschool.com\/blog\/author\/gauravkumarjha19gmail-com\/"}]}},"_links":{"self":[{"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/posts\/2219","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/comments?post=2219"}],"version-history":[{"count":4,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/posts\/2219\/revisions"}],"predecessor-version":[{"id":2226,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/posts\/2219\/revisions\/2226"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/media\/2221"}],"wp:attachment":[{"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/media?parent=2219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/categories?post=2219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/easycodingschool.com\/blog\/wp-json\/wp\/v2\/tags?post=2219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}