{"componentChunkName":"component---src-templates-documentation-tsx","path":"/docs/handbook/advanced-types.html","result":{"data":{"allSitePage":{"nodes":[{"path":"/dev-404-page/"},{"path":"/docs/handbook/nightly-builds.html"},{"path":"/docs/handbook/declaration-files/by-example.html"},{"path":"/docs/handbook/declaration-files/consumption.html"},{"path":"/docs/handbook/declaration-files/deep-dive.html"},{"path":"/docs/handbook/declaration-files/do-s-and-don-ts.html"},{"path":"/docs/handbook/declaration-files/introduction.html"},{"path":"/docs/handbook/declaration-files/library-structures.html"},{"path":"/docs/handbook/declaration-files/publishing.html"},{"path":"/docs/handbook/declaration-files/templates.html"},{"path":"/docs/handbook/typescript-in-5-minutes-func.html"},{"path":"/docs/handbook/typescript-in-5-minutes.html"},{"path":"/docs/handbook/typescript-in-5-minutes-oop.html"},{"path":"/docs/handbook/typescript-from-scratch.html"},{"path":"/docs/handbook/basic-types.html"},{"path":"/docs/handbook/classes.html"},{"path":"/docs/handbook/enums.html"},{"path":"/docs/handbook/functions.html"},{"path":"/docs/handbook/generics.html"},{"path":"/docs/handbook/interfaces.html"},{"path":"/docs/handbook/literal-types.html"},{"path":"/docs/handbook/intro.html"},{"path":"/docs/handbook/unions-and-intersections.html"},{"path":"/docs/handbook/declaration-files/dts-from-js.html"},{"path":"/docs/handbook/intro-to-js-ts.html"},{"path":"/docs/handbook/jsdoc-supported-types.html"},{"path":"/docs/handbook/type-checking-javascript-files.html"},{"path":"/docs/handbook/compiler-options-in-msbuild.html"},{"path":"/docs/handbook/compiler-options.html"},{"path":"/docs/handbook/configuring-watch.html"},{"path":"/docs/handbook/integrating-with-build-tools.html"},{"path":"/docs/handbook/project-references.html"},{"path":"/docs/handbook/tsconfig-json.html"},{"path":"/docs/handbook/advanced-types.html"},{"path":"/docs/handbook/declaration-merging.html"},{"path":"/docs/handbook/decorators.html"},{"path":"/docs/handbook/iterators-and-generators.html"},{"path":"/docs/handbook/jsx.html"},{"path":"/docs/handbook/mixins.html"},{"path":"/docs/handbook/module-resolution.html"},{"path":"/docs/handbook/modules.html"},{"path":"/docs/handbook/namespaces-and-modules.html"},{"path":"/docs/handbook/namespaces.html"},{"path":"/docs/handbook/symbols.html"},{"path":"/docs/handbook/triple-slash-directives.html"},{"path":"/docs/handbook/type-compatibility.html"},{"path":"/docs/handbook/type-inference.html"},{"path":"/docs/handbook/utility-types.html"},{"path":"/docs/handbook/variable-declarations.html"},{"path":"/docs/handbook/release-notes/typescript-1-1.html"},{"path":"/docs/handbook/release-notes/typescript-1-3.html"},{"path":"/docs/handbook/release-notes/typescript-1-4.html"},{"path":"/docs/handbook/release-notes/typescript-1-5.html"},{"path":"/docs/handbook/release-notes/typescript-1-6.html"},{"path":"/docs/handbook/release-notes/typescript-1-7.html"},{"path":"/docs/handbook/release-notes/typescript-1-8.html"},{"path":"/docs/handbook/release-notes/typescript-2-0.html"},{"path":"/docs/handbook/release-notes/typescript-2-1.html"},{"path":"/docs/handbook/release-notes/typescript-2-2.html"},{"path":"/docs/handbook/release-notes/typescript-2-3.html"},{"path":"/docs/handbook/release-notes/typescript-2-4.html"},{"path":"/docs/handbook/release-notes/typescript-2-5.html"},{"path":"/docs/handbook/release-notes/typescript-2-6.html"},{"path":"/docs/handbook/release-notes/typescript-2-7.html"},{"path":"/docs/handbook/release-notes/typescript-2-8.html"},{"path":"/docs/handbook/release-notes/typescript-2-9.html"},{"path":"/docs/handbook/release-notes/typescript-3-0.html"},{"path":"/docs/handbook/release-notes/typescript-3-1.html"},{"path":"/docs/handbook/release-notes/typescript-3-2.html"},{"path":"/docs/handbook/release-notes/typescript-3-3.html"},{"path":"/docs/handbook/release-notes/typescript-3-4.html"},{"path":"/docs/handbook/release-notes/typescript-3-5.html"},{"path":"/docs/handbook/release-notes/typescript-3-6.html"},{"path":"/docs/handbook/release-notes/typescript-3-7.html"},{"path":"/docs/handbook/release-notes/typescript-3-8.html"},{"path":"/docs/handbook/release-notes/typescript-3-9.html"},{"path":"/docs/handbook/asp-net-core.html"},{"path":"/docs/handbook/angular.html"},{"path":"/docs/handbook/babel-with-typescript.html"},{"path":"/docs/handbook/dom-manipulation.html"},{"path":"/docs/handbook/gulp.html"},{"path":"/docs/handbook/migrating-from-javascript.html"},{"path":"/docs/handbook/react.html"},{"path":"/docs/handbook/typescript-tooling-in-5-minutes.html"},{"path":"/vo/docs/handbook/basic-types.html"},{"path":"/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/global-plugin-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/global-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-class-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-function-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-plugin-d-ts.html"},{"path":"/docs/handbook/declaration-files/templates/module-d-ts.html"},{"path":"/docs/handbook/release-notes/overview.html"},{"path":"/tsconfig"},{"path":"/en/tsconfig"},{"path":"/vo/tsconfig"},{"path":"/ja/tsconfig"},{"path":"/pt/tsconfig"},{"path":"/play"},{"path":"/en/play"},{"path":"/es/play"},{"path":"/ja/play"},{"path":"/pt/play"},{"path":"/vo/play"},{"path":"/zh/play"},{"path":"/fa/play"},{"path":"/play/3-7/fixits/big-number-literals.ts"},{"path":"/play/3-7/fixits/const-to-let.ts"},{"path":"/play/3-7/fixits/infer-from-usage-changes.ts"},{"path":"/play/3-7/syntax-and-messaging/flattened-error-reporting.ts"},{"path":"/play/3-7/syntax-and-messaging/nullish-coalescing.ts"},{"path":"/play/3-7/syntax-and-messaging/optional-chaining.ts"},{"path":"/play/3-7/types-and-code-flow/assertion-functions.ts"},{"path":"/play/3-7/types-and-code-flow/recursive-type-references.ts"},{"path":"/play/3-7/types-and-code-flow/uncalled-function-checks.ts"},{"path":"/play/3-8/breaking-changes/checking-unions-with-index-signatures.ts"},{"path":"/play/3-8/jsdoc-improvements/accessibility-modifiers.js"},{"path":"/play/3-8/syntax-and-messaging/export-modules-from.ts"},{"path":"/play/3-8/syntax-and-messaging/private-class-fields.ts"},{"path":"/play/4-0/new-checks/class-constructor-code-flow.ts"},{"path":"/play/4-0/new-js-features/jsdoc-deprecated.ts"},{"path":"/play/4-0/new-js-features/logical-operators-and-assignment.ts"},{"path":"/play/4-0/new-js-features/nullish-coalescing.ts"},{"path":"/play/4-0/new-ts-features/named-tuples.ts"},{"path":"/play/4-0/new-ts-features/unknown-in-catch.ts"},{"path":"/play/4-0/new-ts-features/variadic-tuples.ts"},{"path":"/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/play/javascript/external-apis/typescript-with-node.js"},{"path":"/play/javascript/external-apis/typescript-with-web.js"},{"path":"/play/javascript/external-apis/typescript-with-webgl.js"},{"path":"/play/javascript/functions-with-javascript/function-chaining.ts"},{"path":"/play/javascript/functions-with-javascript/generic-functions.ts"},{"path":"/play/javascript/functions-with-javascript/typing-functions.ts"},{"path":"/play/javascript/helping-with-javascript/errors.ts"},{"path":"/play/javascript/helping-with-javascript/quick-fixes.ts"},{"path":"/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/play/javascript/javascript-essentials/functions.ts"},{"path":"/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/play/javascript/modern-javascript/async-await.ts"},{"path":"/play/javascript/modern-javascript/immutability.ts"},{"path":"/play/javascript/modern-javascript/import-export.ts"},{"path":"/play/javascript/modern-javascript/jsdoc-support.js"},{"path":"/play/javascript/working-with-classes/classes-101.ts"},{"path":"/play/javascript/working-with-classes/generic-classes.ts"},{"path":"/play/javascript/working-with-classes/mixins.ts"},{"path":"/play/javascript/working-with-classes/this.ts"},{"path":"/play/playground/config/javascript-playgrounds.js"},{"path":"/play/playground/config/new-compiler-defaults.ts"},{"path":"/play/playground/language/automatic-type-acquisition.ts"},{"path":"/play/playground/language/fixits.ts"},{"path":"/play/playground/tooling/mobile-support.ts"},{"path":"/play/playground/tooling/sharable-urls.ts"},{"path":"/play/playground/tooling/typescript-versions.ts"},{"path":"/play/typescript/language/soundness.ts"},{"path":"/play/typescript/language/structural-typing.ts"},{"path":"/play/typescript/language/type-guards.ts"},{"path":"/play/typescript/language/type-widening-and-narrowing.ts"},{"path":"/play/typescript/language-extensions/enums.ts"},{"path":"/play/typescript/language-extensions/nominal-typing.ts"},{"path":"/play/typescript/language-extensions/types-vs-interfaces.ts"},{"path":"/play/typescript/meta-types/conditional-types.ts"},{"path":"/play/typescript/meta-types/discriminate-types.ts"},{"path":"/play/typescript/meta-types/indexed-types.ts"},{"path":"/play/typescript/meta-types/mapped-types.ts"},{"path":"/play/typescript/primitives/any.ts"},{"path":"/play/typescript/primitives/literals.ts"},{"path":"/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/play/typescript/primitives/unknown-and-never.ts"},{"path":"/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/play/typescript/type-primitives/nullable-types.ts"},{"path":"/play/typescript/type-primitives/tuples.ts"},{"path":"/es/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/es/play/javascript/external-apis/typescript-with-node.js"},{"path":"/es/play/javascript/external-apis/typescript-with-web.js"},{"path":"/es/play/javascript/functions-with-javascript/function-chaining.ts"},{"path":"/es/play/javascript/functions-with-javascript/generic-functions.ts"},{"path":"/es/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/es/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/es/play/typescript/language/soundness.ts"},{"path":"/es/play/typescript/language/structural-typing.ts"},{"path":"/es/play/typescript/language/type-guards.ts"},{"path":"/es/play/typescript/language/type-widening-and-narrowing.ts"},{"path":"/es/play/typescript/meta-types/conditional-types.ts"},{"path":"/es/play/typescript/meta-types/discriminate-types.ts"},{"path":"/es/play/typescript/meta-types/indexed-types.ts"},{"path":"/es/play/typescript/meta-types/mapped-types.ts"},{"path":"/es/play/typescript/primitives/any.ts"},{"path":"/es/play/typescript/primitives/literals.ts"},{"path":"/es/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/es/play/typescript/primitives/unknown-and-never.ts"},{"path":"/es/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/es/play/typescript/type-primitives/nullable-types.ts"},{"path":"/es/play/typescript/type-primitives/tuples.ts"},{"path":"/fa/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/ja/play/3-7/fixits/big-number-literals.ts"},{"path":"/ja/play/3-7/syntax-and-messaging/nullish-coalescing.ts"},{"path":"/ja/play/3-7/syntax-and-messaging/optional-chaining.ts"},{"path":"/ja/play/3-8/breaking-changes/checking-unions-with-index-signatures.ts"},{"path":"/ja/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/ja/play/typescript/language-extensions/enums.ts"},{"path":"/ja/play/typescript/language-extensions/nominal-typing.ts"},{"path":"/ja/play/typescript/language-extensions/types-vs-interfaces.ts"},{"path":"/ja/play/typescript/primitives/any.ts"},{"path":"/ja/play/typescript/primitives/literals.ts"},{"path":"/ja/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/ja/play/typescript/primitives/unknown-and-never.ts"},{"path":"/ja/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/ja/play/typescript/type-primitives/nullable-types.ts"},{"path":"/ja/play/typescript/type-primitives/tuples.ts"},{"path":"/pt/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/pt/play/javascript/javascript-essentials/functions.ts"},{"path":"/pt/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/pt/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/vo/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/vo/play/javascript/javascript-essentials/functions.ts"},{"path":"/vo/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/vo/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/zh/play/javascript/external-apis/typescript-with-deno.ts"},{"path":"/zh/play/javascript/external-apis/typescript-with-node.js"},{"path":"/zh/play/javascript/external-apis/typescript-with-web.js"},{"path":"/zh/play/javascript/external-apis/typescript-with-webgl.js"},{"path":"/zh/play/javascript/functions-with-javascript/function-chaining.ts"},{"path":"/zh/play/javascript/functions-with-javascript/generic-functions.ts"},{"path":"/zh/play/javascript/functions-with-javascript/typing-functions.ts"},{"path":"/zh/play/javascript/helping-with-javascript/errors.ts"},{"path":"/zh/play/javascript/helping-with-javascript/quick-fixes.ts"},{"path":"/zh/play/javascript/javascript-essentials/code-flow.ts"},{"path":"/zh/play/javascript/javascript-essentials/functions.ts"},{"path":"/zh/play/javascript/javascript-essentials/hello-world.ts"},{"path":"/zh/play/javascript/javascript-essentials/objects-and-arrays.ts"},{"path":"/zh/play/javascript/modern-javascript/async-await.ts"},{"path":"/zh/play/javascript/modern-javascript/immutability.ts"},{"path":"/zh/play/javascript/modern-javascript/import-export.ts"},{"path":"/zh/play/javascript/modern-javascript/jsdoc-support.js"},{"path":"/zh/play/javascript/working-with-classes/classes-101.ts"},{"path":"/zh/play/javascript/working-with-classes/generic-classes.ts"},{"path":"/zh/play/javascript/working-with-classes/mixins.ts"},{"path":"/zh/play/javascript/working-with-classes/this.ts"},{"path":"/zh/play/playground/config/javascript-playgrounds.js"},{"path":"/zh/play/playground/config/new-compiler-defaults.ts"},{"path":"/zh/play/playground/language/automatic-type-acquisition.ts"},{"path":"/zh/play/playground/language/fixits.ts"},{"path":"/zh/play/playground/tooling/mobile-support.ts"},{"path":"/zh/play/playground/tooling/sharable-urls.ts"},{"path":"/zh/play/playground/tooling/typescript-versions.ts"},{"path":"/zh/play/typescript/language/soundness.ts"},{"path":"/zh/play/typescript/language/structural-typing.ts"},{"path":"/zh/play/typescript/language/type-guards.ts"},{"path":"/zh/play/typescript/language/type-widening-and-narrowing.ts"},{"path":"/zh/play/typescript/language-extensions/enums.ts"},{"path":"/zh/play/typescript/language-extensions/nominal-typing.ts"},{"path":"/zh/play/typescript/language-extensions/types-vs-interfaces.ts"},{"path":"/zh/play/typescript/meta-types/conditional-types.ts"},{"path":"/zh/play/typescript/meta-types/discriminate-types.ts"},{"path":"/zh/play/typescript/meta-types/indexed-types.ts"},{"path":"/zh/play/typescript/meta-types/mapped-types.ts"},{"path":"/zh/play/typescript/primitives/any.ts"},{"path":"/zh/play/typescript/primitives/literals.ts"},{"path":"/zh/play/typescript/primitives/union-and-intersection-types.ts"},{"path":"/zh/play/typescript/primitives/unknown-and-never.ts"},{"path":"/zh/play/typescript/type-primitives/built-in-utility-types.ts"},{"path":"/zh/play/typescript/type-primitives/nullable-types.ts"},{"path":"/zh/play/typescript/type-primitives/tuples.ts"},{"path":"/ja/play/3-7/syntax-and-messaging/flattened-error-reporting.ts"},{"path":"/ja/play/3-7/fixits/infer-from-usage-changes.ts"},{"path":"/ja/play/3-7/fixits/const-to-let.ts"},{"path":"/community"},{"path":"/es/community"},{"path":"/ja/community"},{"path":"/vo/community"},{"path":"/zh/community"},{"path":"/download"},{"path":"/es/download"},{"path":"/ja/download"},{"path":"/vo/download"},{"path":"/zh/download"},{"path":"/empty"},{"path":"/es/empty"},{"path":"/ja/empty"},{"path":"/vo/empty"},{"path":"/zh/empty"},{"path":"/"},{"path":"/es/"},{"path":"/ja/"},{"path":"/vo/"},{"path":"/zh/"},{"path":"/tools"},{"path":"/es/tools"},{"path":"/ja/tools"},{"path":"/vo/tools"},{"path":"/zh/tools"},{"path":"/why-create-typescript"},{"path":"/es/why-create-typescript"},{"path":"/ja/why-create-typescript"},{"path":"/vo/why-create-typescript"},{"path":"/zh/why-create-typescript"},{"path":"/docs/bootstrap"},{"path":"/es/docs/bootstrap"},{"path":"/ja/docs/bootstrap"},{"path":"/vo/docs/bootstrap"},{"path":"/zh/docs/bootstrap"},{"path":"/docs/"},{"path":"/es/docs/"},{"path":"/ja/docs/"},{"path":"/vo/docs/"},{"path":"/zh/docs/"},{"path":"/docs/handbook/"},{"path":"/es/docs/handbook/"},{"path":"/ja/docs/handbook/"},{"path":"/vo/docs/handbook/"},{"path":"/zh/docs/handbook/"},{"path":"/branding/"},{"path":"/dev/bug-workbench/"},{"path":"/dev/playground-plugins/"},{"path":"/dev/sandbox/"},{"path":"/dev/twoslash/"},{"path":"/dev/typescript-vfs/"},{"path":"/upcoming/"}]},"markdownRemark":{"id":"84d53932-375e-5f7d-8d32-b83c1b7b22d4","excerpt":"This page lists some of the more advanced ways in which you can model types, it works in tandem with the Utility Types doc which includes types which are…","html":"<p>This page lists some of the more advanced ways in which you can model types, it works in tandem with the <a href=\"/docs/handbook/utility-types.html\">Utility Types</a> doc which includes types which are included in TypeScript and available globally.</p>\n<h2 id=\"type-guards-and-differentiating-types\" style=\"position:relative;\"><a href=\"#type-guards-and-differentiating-types\" aria-label=\"type guards and differentiating types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Type Guards and Differentiating Types</h2>\n<p>Union types are useful for modeling situations when values can overlap in the types they can take on.\nWhat happens when we need to know specifically whether we have a <code>Fish</code>?\nA common idiom in JavaScript to differentiate between two possible values is to check for the presence of a member.\nAs we mentioned, you can only access members that are guaranteed to be in all the constituents of a union type.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getSmallPet(): Fish | Bird'>getSmallPet</data-lsp>();</span>\n\n<span style=\"color: #008000\">// You can use the &apos;in&apos; operator to check</span>\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #A31515\">\"swim\"</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish'>pet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) swim: () => void'>swim</data-lsp>();</span>\n<span style=\"color: #000000\">}</span>\n<span style=\"color: #008000\">// However, you cannot use property access</span>\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='any'>fly</data-lsp></data-err></span><span style=\"color: #000000\">) {</span>\n<span class=\"error\"><span>Property 'fly' does not exist on type 'Fish | Bird'.\n  Property 'fly' does not exist on type 'Fish'.</span><span class=\"code\">2339</span></span><span class=\"error-behind\">Property 'fly' does not exist on type 'Fish | Bird'.\n  Property 'fly' does not exist on type 'Fish'.</span><span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\"><data-err>.<data-lsp lsp='any'>fly</data-lsp>();</data-err></span>\n<span class=\"error\"><span>Property 'fly' does not exist on type 'Fish | Bird'.\n  Property 'fly' does not exist on type 'Fish'.</span><span class=\"code\">2339</span></span><span class=\"error-behind\">Property 'fly' does not exist on type 'Fish | Bird'.\n  Property 'fly' does not exist on type 'Fish'.</span><span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYME4BQAXATwAdJQAxAS0QAtQBeUAb1EQHdKBbVACgEoGAPlAA3OJQAmoAL4BuAiTIAhStCmMWAMwA2hXgPrCxkmfImQAxtoCG0MpoCuAOwv5KcJ6ADmkfAGVOa21tAAVfflQqWlAAH1AVNXkQUABaNIsHfDSU3G1fUFJ8Bm9fAKDQ8L55XGSATTgHUAtrTwdEMnwaMgBySidu0DhSaGt8BFAxpq6LAGtcSk1QHgAidi5l0D6C3wEmXFBt-AA6Nc5+eWkasAAJODZIERgAGlBCBqaWpzgitrJieGGRFA1gsFkgiEQ80WPEKRx0hF2+0OcN051w0iAA'>Try</a></div></pre>\n<p>To get the same code working via property accessors, we’ll need to use a type assertion:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getSmallPet(): Fish | Bird'>getSmallPet</data-lsp>();</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let fishPet: Fish'>fishPet</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> <data-lsp lsp='type Fish = {&amp;#13;    swim: () => void;&amp;#13;}'>Fish</data-lsp>;</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let birdPet: Bird'>birdPet</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> <data-lsp lsp='type Bird = {&amp;#13;    fly: () => void;&amp;#13;}'>Bird</data-lsp>;</span>\n\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let fishPet: Fish'>fishPet</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) swim: () => void'>swim</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let fishPet: Fish'>fishPet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) swim: () => void'>swim</data-lsp>();</span>\n<span style=\"color: #000000\">} </span><span style=\"color: #0000FF\">else</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let birdPet: Bird'>birdPet</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) fly: () => void'>fly</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let birdPet: Bird'>birdPet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) fly: () => void'>fly</data-lsp>();</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYglgZwBZQLxQN5QQdzgWwC4oAKASjQD4oA3AezgBMoBfAbgChRIoAhOAE7N0WAGYAbEMXJVaDZuw6MIAY3EBDAdFEBXAHYrgcOnqgBzCMADK+dePEAFS+WLxkUAD59BjTgHo-KABaEJUdYBCgjnFLKEhgNHNLGztHZzJOGITRRCQnBPR4qHUEWFzM2IAjH3zEopLvIU4OOFFSHOR8gDpcAgoMDigoDrzLHrx8ck4WKAhxBGhW0mqhbokQfsGoFcY1ySmOFiA'>Try</a></div></pre>\n<p>This isn’t the sort of code you would want in your codebase however.</p>\n<h2 id=\"user-defined-type-guards\" style=\"position:relative;\"><a href=\"#user-defined-type-guards\" aria-label=\"user defined type guards permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>User-Defined Type Guards</h2>\n<p>It would be much better if once we performed the check, we could know the type of <code>pet</code> within each branch.</p>\n<p>It just so happens that TypeScript has something called a <em>type guard</em>.\nA type guard is some expression that performs a runtime check that guarantees the type in some scope.</p>\n<h4 id=\"using-type-predicates\" style=\"position:relative;\"><a href=\"#using-type-predicates\" aria-label=\"using type predicates permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using type predicates</h4>\n<p>To define a type guard, we simply need to define a function whose return type is a <em>type predicate</em>:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function isFish(pet: Fish | Bird): pet is Fish'>isFish</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='type Fish = {&amp;#13;    swim: () => void;&amp;#13;}'>Fish</data-lsp> | <data-lsp lsp='type Bird = {&amp;#13;    fly: () => void;&amp;#13;}'>Bird</data-lsp>): <data-lsp lsp='(parameter) pet: Fish | Bird'>pet</data-lsp> </span><span style=\"color: #0000FF\">is</span><span style=\"color: #000000\"> <data-lsp lsp='type Fish = {&amp;#13;    swim: () => void;&amp;#13;}'>Fish</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> <data-lsp lsp='type Fish = {&amp;#13;    swim: () => void;&amp;#13;}'>Fish</data-lsp>).</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) swim: () => void'>swim</data-lsp></span><span style=\"color: #000000\"> !== </span><span style=\"color: #0000FF\"><data-lsp lsp='var undefined'>undefined</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYglgZwBZQLxQN5QQdzgWwC4oAKASjQD4oA3AezgBMoBfAbgChRIoAhOAE7N0WAGYAbEMXJVaDZuw6MIAY3EBDAdFEBXAHYrgcOnqgBzCMADK+dePEAFS+WLxkUAD59BjTgHo-KABaEJUdYBCgjl0DIxMoRDckEkhgV0QUL34hMmJUhIRYDMwOKCgtYB0BUxTLKHVCpLIAOlwCKABCVHR9ZVE4PQhfDhYgA'>Try</a></div></pre>\n<p><code>pet is Fish</code> is our type predicate in this example.\nA predicate takes the form <code>parameterName is Type</code>, where <code>parameterName</code> must be the name of a parameter from the current function signature.</p>\n<p>Any time <code>isFish</code> is called with some variable, TypeScript will <em>narrow</em> that variable to that specific type if the original type is compatible.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Both calls to &apos;swim&apos; and &apos;fly&apos; are now okay.</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getSmallPet(): Fish | Bird'>getSmallPet</data-lsp>();</span>\n\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (<data-lsp lsp='function isFish(pet: Fish | Bird): pet is Fish'>isFish</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\">)) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Fish'>pet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) swim: () => void'>swim</data-lsp>();</span>\n<span style=\"color: #000000\">} </span><span style=\"color: #0000FF\">else</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let pet: Bird'>pet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) fly: () => void'>fly</data-lsp>();</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYglgZwBZQLxQN5QQdzgWwC4oAKASjQD4oA3AezgBMoBfAbgChRIoAhOAE7N0WAGYAbEMXJVaDZuw6MIAY3EBDAdFEBXAHYrgcOnqgBzCMADK+dePEAFS+WLxkUAD59BjTroNGJlCIbkgkkMCuiChe-EJkxBHBCLDRmBxQUFrAOgKm4ZZQ6imhZAB0uARQAISo6PrKonB6EL4cLBwA9J1QALT9KjrA-b1dPbx0wCgqduIpwHRQAOSV+EtFesxLEiDrmtB6dDhQdADW6iBlHOKFSegW1rb2TsDknBxwoqQh0QXAZBQMBkoBEKnh8G92lAIHNoEDMqCdpCWEA'>Try</a></div></pre>\n<p>Notice that TypeScript not only knows that <code>pet</code> is a <code>Fish</code> in the <code>if</code> branch;\nit also knows that in the <code>else</code> branch, you <em>don’t</em> have a <code>Fish</code>, so you must have a <code>Bird</code>.</p>\n<h3 id=\"using-the-in-operator\" style=\"position:relative;\"><a href=\"#using-the-in-operator\" aria-label=\"using the in operator permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Using the <code>in</code> operator</h3>\n<p>The <code>in</code> operator also acts as a narrowing expression for types.</p>\n<p>For a <code>n in x</code> expression, where <code>n</code> is a string literal or string literal type and <code>x</code> is a union type, the “true” branch narrows to types which have an optional or required property <code>n</code>, and the “false” branch narrows to types which have an optional or missing property <code>n</code>.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function move(pet: Fish | Bird): void'>move</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='type Fish = {&amp;#13;    swim: () => void;&amp;#13;}'>Fish</data-lsp> | <data-lsp lsp='type Bird = {&amp;#13;    fly: () => void;&amp;#13;}'>Bird</data-lsp>) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #A31515\">\"swim\"</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) pet: Fish | Bird'>pet</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) pet: Fish'>pet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) swim: () => void'>swim</data-lsp>();</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) pet: Bird'>pet</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) fly: () => void'>fly</data-lsp>();</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYglgZwBZQLxQN5QQdzgWwC4oAKASjQD4oA3AezgBMoBfAbgChRIoAhOAE7N0WAGYAbEMXJVaDZuw4B6JVAC0GgMYBXYBrUdR2gHabgcOsaj46NCCUjBi8ZFAA+fQYwoYOUKHCipABEuATBAVaOPn7+UAIQwNoCUYkAdGH45Jz+LLEJSSlQjmkSINkcLEA'>Try</a></div></pre>\n<h2 id=\"typeof-type-guards\" style=\"position:relative;\"><a href=\"#typeof-type-guards\" aria-label=\"typeof type guards permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code>typeof</code> type guards</h2>\n<p>Let’s go back and write the code for a version of <code>padLeft</code> which uses union types.\nWe could write it with type predicates as follows:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function isNumber(x: any): x is number'>isNumber</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: any'>x</data-lsp></span><span style=\"color: #000000\">: any): <data-lsp lsp='(parameter) x: any'>x</data-lsp> </span><span style=\"color: #0000FF\">is</span><span style=\"color: #000000\"> number {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: any'>x</data-lsp></span><span style=\"color: #000000\"> === </span><span style=\"color: #A31515\">\"number\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function isString(x: any): x is string'>isString</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: any'>x</data-lsp></span><span style=\"color: #000000\">: any): <data-lsp lsp='(parameter) x: any'>x</data-lsp> </span><span style=\"color: #0000FF\">is</span><span style=\"color: #000000\"> string {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: any'>x</data-lsp></span><span style=\"color: #000000\"> === </span><span style=\"color: #A31515\">\"string\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function padLeft(value: string, padding: string | number): string'>padLeft</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: string'>value</data-lsp></span><span style=\"color: #000000\">: string, </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string | number'>padding</data-lsp></span><span style=\"color: #000000\">: string | number) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (<data-lsp lsp='function isNumber(x: any): x is number'>isNumber</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string | number'>padding</data-lsp></span><span style=\"color: #000000\">)) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> <data-lsp lsp='var Array: ArrayConstructor&amp;#13;(arrayLength?: number | undefined) => any[] (+2 overloads)'>Array</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: number'>padding</data-lsp></span><span style=\"color: #000000\"> + </span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">).<data-lsp lsp='(method) Array&amp;lt;any>.join(separator?: string | undefined): string'>join</data-lsp>(</span><span style=\"color: #A31515\">\" \"</span><span style=\"color: #000000\">) + </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: string'>value</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (<data-lsp lsp='function isString(x: any): x is string'>isString</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string'>padding</data-lsp></span><span style=\"color: #000000\">)) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string'>padding</data-lsp></span><span style=\"color: #000000\"> + </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: string'>value</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">throw</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='var Error: ErrorConstructor&amp;#13;new (message?: string | undefined) => Error'>Error</data-lsp>(</span><span style=\"color: #A31515\">`Expected string or number, got &apos;</span><span style=\"color: #0000FF\">${</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: never'>padding</data-lsp></span><span style=\"color: #0000FF\">}</span><span style=\"color: #A31515\">&apos;.`</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABDAzgORAWwEYFMBOAFAB4BciAhmAJ4CU5xyKiYWe+iA3gFCKL64oIfEijUADrjjBEjALwLEAIlY4CSgNzcAvt26hIsBEwDKUfDDABzEuSp0GTRCnOWrXXv0HDREqTPlFJRcLa00dPQNoeCRxCgATABlcYChCADcKABsQXHIQtwAaRDj4+Ld812tEAB8WNgJaDz4YGUJUDDUiUvLrWiaePj4BIRFEAEF8fApqQh63RABqRABGWgA6ACs4S0IlZSblzJzcLT5dFrbUM1Cbeb6Bz2HvMfv3I+zcs8QLxCgAC3wcAA7ixcKCAKJTOBEAAGEOIkmguHiziq7hh9S6xSscCgiAA5AASThvbQE9aw2habRAA'>Try</a></div></pre>\n<p>However, having to define a function to figure out if a type is a primitive is kind of a pain.\nLuckily, you don’t need to abstract <code>typeof x === \"number\"</code> into its own function because TypeScript will recognize it as a type guard on its own.\nThat means we could just write these checks inline.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function padLeft(value: string, padding: string | number): string'>padLeft</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: string'>value</data-lsp></span><span style=\"color: #000000\">: string, </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string | number'>padding</data-lsp></span><span style=\"color: #000000\">: string | number) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string | number'>padding</data-lsp></span><span style=\"color: #000000\"> === </span><span style=\"color: #A31515\">\"number\"</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> <data-lsp lsp='var Array: ArrayConstructor&amp;#13;(arrayLength?: number | undefined) => any[] (+2 overloads)'>Array</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: number'>padding</data-lsp></span><span style=\"color: #000000\"> + </span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">).<data-lsp lsp='(method) Array&amp;lt;any>.join(separator?: string | undefined): string'>join</data-lsp>(</span><span style=\"color: #A31515\">\" \"</span><span style=\"color: #000000\">) + </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: string'>value</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string'>padding</data-lsp></span><span style=\"color: #000000\"> === </span><span style=\"color: #A31515\">\"string\"</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: string'>padding</data-lsp></span><span style=\"color: #000000\"> + </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: string'>value</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">throw</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='var Error: ErrorConstructor&amp;#13;new (message?: string | undefined) => Error'>Error</data-lsp>(</span><span style=\"color: #A31515\">`Expected string or number, got &apos;</span><span style=\"color: #0000FF\">${</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) padding: never'>padding</data-lsp></span><span style=\"color: #0000FF\">}</span><span style=\"color: #A31515\">&apos;.`</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABABwIYBMAyBTYUAUAbqgDYjYBciAzlAE4xgDmANChuo01bQ84gB9EYEAFsARtjoBKRAG8AUIkQxgifFACeybHDVp0nfgF5TiAEQiJU87MXLldbFBB0kAQTp1Um-AaNMiADUiACM0gB0AFZwjPjmFrIhxGTYANxKiAC+marqWjp67IZciKbGFrxctvKZjs6uSP6lyaTkGco5ylAAFnRwAO7C2EMAol5wdPgABqMAHjrQ2Og09KWTwmKSdGxMcFCIAOQAJHLNzFmHEdPSGVlAA'>Try</a></div></pre>\n<p>These <em><code>typeof</code> type guards</em> are recognized in two different forms: <code>typeof v === \"typename\"</code> and <code>typeof v !== \"typename\"</code>, where <code>\"typename\"</code> must be <code>\"number\"</code>, <code>\"string\"</code>, <code>\"boolean\"</code>, or <code>\"symbol\"</code>.\nWhile TypeScript won’t stop you from comparing to other strings, the language won’t recognize those expressions as type guards.</p>\n<h2 id=\"instanceof-type-guards\" style=\"position:relative;\"><a href=\"#instanceof-type-guards\" aria-label=\"instanceof type guards permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a><code>instanceof</code> type guards</h2>\n<p>If you’ve read about <code>typeof</code> type guards and are familiar with the <code>instanceof</code> operator in JavaScript, you probably have some idea of what this section is about.</p>\n<p><em><code>instanceof</code> type guards</em> are a way of narrowing types using their constructor function.\nFor instance, let’s borrow our industrial strength string-padder example from earlier:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Padder'>Padder</data-lsp> {</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(method) Padder.getPaddingString(): string'>getPaddingString</data-lsp>(): string;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">class</span><span style=\"color: #000000\"> <data-lsp lsp='class SpaceRepeatingPadder'>SpaceRepeatingPadder</data-lsp> </span><span style=\"color: #0000FF\">implements</span><span style=\"color: #000000\"> <data-lsp lsp='interface Padder'>Padder</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">constructor</span><span style=\"color: #000000\">(</span><span style=\"color: #0000FF\">private</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) SpaceRepeatingPadder.numSpaces: number'>numSpaces</data-lsp></span><span style=\"color: #000000\">: number) {}</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(method) SpaceRepeatingPadder.getPaddingString(): string'>getPaddingString</data-lsp>() {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> <data-lsp lsp='var Array: ArrayConstructor&amp;#13;(arrayLength?: number | undefined) => any[] (+2 overloads)'>Array</data-lsp>(</span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) SpaceRepeatingPadder.numSpaces: number'>numSpaces</data-lsp></span><span style=\"color: #000000\"> + </span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">).<data-lsp lsp='(method) Array&amp;lt;any>.join(separator?: string | undefined): string'>join</data-lsp>(</span><span style=\"color: #A31515\">\" \"</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">class</span><span style=\"color: #000000\"> <data-lsp lsp='class StringPadder'>StringPadder</data-lsp> </span><span style=\"color: #0000FF\">implements</span><span style=\"color: #000000\"> <data-lsp lsp='interface Padder'>Padder</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">constructor</span><span style=\"color: #000000\">(</span><span style=\"color: #0000FF\">private</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) StringPadder.value: string'>value</data-lsp></span><span style=\"color: #000000\">: string) {}</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(method) StringPadder.getPaddingString(): string'>getPaddingString</data-lsp>() {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.<data-lsp lsp='(property) StringPadder.value: string'>value</data-lsp>;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function getRandomPadder(): SpaceRepeatingPadder | StringPadder'>getRandomPadder</data-lsp>() {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> <data-lsp lsp='var Math: Math'>Math</data-lsp>.<data-lsp lsp='(method) Math.random(): number'>random</data-lsp>() &lt; </span><span style=\"color: #09835A\">0.5</span>\n<span style=\"color: #000000\">    ? </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='constructor SpaceRepeatingPadder(numSpaces: number): SpaceRepeatingPadder'>SpaceRepeatingPadder</data-lsp>(</span><span style=\"color: #09835A\">4</span><span style=\"color: #000000\">)</span>\n<span style=\"color: #000000\">    : </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='constructor StringPadder(value: string): StringPadder'>StringPadder</data-lsp>(</span><span style=\"color: #A31515\">\"  \"</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let padder: Padder'>padder</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Padder'>Padder</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getRandomPadder(): SpaceRepeatingPadder | StringPadder'>getRandomPadder</data-lsp>();</span>\n<span class='query'>//       ^ = let padder: Padder</span>\n\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let padder: Padder'>padder</data-lsp></span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">instanceof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='class SpaceRepeatingPadder'>SpaceRepeatingPadder</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let padder: SpaceRepeatingPadder'>padder</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">//     ^?</span>\n<span style=\"color: #000000\">}</span>\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let padder: Padder'>padder</data-lsp></span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">instanceof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='class StringPadder'>StringPadder</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let padder: StringPadder'>padder</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">//     ^?</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgApwCYesg3gKGWQHMIx0tRiBlMKKgCgEoAuZAZzqoG58BffPgQAbOO3bJqAB0QQAShCkQ4YKhWxRkwALZThEbRHAT1OAkQQB7EJygBXBGEtQGU+gDcVKEHe3TZ7Gw+2gBG0Ex4AkSk5JgYVLT0IMTMeIREyFBkdlAgyACCUFBwAJ4MYAAWwOwAdMH+SBIA1MgAjEw1AFaWoAwARMh9TLxEAgJCouKSXMmmmjp6BkZgJnFm6VY2dA5OLm7AnpDInsJ2EGy2VBG4USRk6gkzKdfpRFlgOXmV1TUnZyPIMaCGB2ECOYDWO5gORwEAYSzaOapcyZbK5ZAAWRUFRqxThCNSAB5kAAGGoAVleyAA-MgQBAAO6SGRIBRKFRqNYuAAsTCpQUZ0ySxCRA0Gw34gn0YGQMiw0DYc2QAF4oTD8YiucxeAB6HUZA0APWpgmAMGQri5Wi2sKQlnNDXkimUqlmXJeRDlGgBeoNyGNkrNFq9OFAnFtEHtQs58qgHtlXJ9+qNJr4QA'>Try</a></div></pre>\n<p>The right side of the <code>instanceof</code> needs to be a constructor function, and TypeScript will narrow down to:</p>\n<ol>\n<li>the type of the function’s <code>prototype</code> property if its type is not <code>any</code></li>\n<li>the union of types returned by that type’s construct signatures</li>\n</ol>\n<p>in that order.</p>\n<h2 id=\"nullable-types\" style=\"position:relative;\"><a href=\"#nullable-types\" aria-label=\"nullable types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Nullable types</h2>\n<p>TypeScript has two special types, <code>null</code> and <code>undefined</code>, that have the values null and undefined respectively.\nWe mentioned these briefly in <a href=\"/docs/handbook/basic-types.html\">the Basic Types section</a>.</p>\n<p>By default, the type checker considers <code>null</code> and <code>undefined</code> assignable to anything.\nEffectively, <code>null</code> and <code>undefined</code> are valid values of every type.\nThat means it’s not possible to <em>stop</em> them from being assigned to any type, even when you would like to prevent it.\nThe inventor of <code>null</code>, Tony Hoare, calls this his <a href=\"https://wikipedia.org/wiki/Null_pointer#History\">“billion dollar mistake”</a>.</p>\n<p>The <a href=\"/tsconfig#strictNullChecks\"><code>--strictNullChecks</code></a> flag fixes this: when you declare a variable, it doesn’t automatically include <code>null</code> or <code>undefined</code>.\nYou can include them explicitly using a union type:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let examapleString: string'>examapleString</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #A31515\">\"foo\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='let examapleString: string'>examapleString</data-lsp></data-err></span><span style=\"color: #000000\"> = </span><span style=\"color: #0000FF\">null</span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'null' is not assignable to type 'string'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'null' is not assignable to type 'string'.</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let stringOrNull: string | null'>stringOrNull</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string </span><span style=\"color: #000000\">|</span><span style=\"color: #1A1A1A\"> null </span><span style=\"color: #000000\">= </span><span style=\"color: #A31515\">\"bar\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let stringOrNull: string | null'>stringOrNull</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #0000FF\">null</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='let stringOrNull: string | null'>stringOrNull</data-lsp></data-err></span><span style=\"color: #000000\"> = </span><span style=\"color: #0000FF\"><data-lsp lsp='var undefined'>undefined</data-lsp></span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'undefined' is not assignable to type 'string | null'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'undefined' is not assignable to type 'string | null'.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGY1oFABtIAXUSADwEMBbcgBwIGVDoBLAOwHNQBeUAIgDM4cXgG4cZKrQZM2nHqwCuePGPxFQiGRwDy0AHJK8qTSw6gAPqEXLufAEbloonCdm6DN+YdWud+w7YKrAAmkPxskMEiQA'>Try</a></div></pre>\n<p>Note that TypeScript treats <code>null</code> and <code>undefined</code> differently in order to match JavaScript semantics.\n<code>string | null</code> is a different type than <code>string | undefined</code> and <code>string | undefined | null</code>.</p>\n<p>From TypeScript 3.7 and onwards, you can use <a href=\"/docs/handbook/release-notes/typescript-3-7.html#optional-chaining\">optional chaining</a> to simplify working with nullable types.</p>\n<h3 id=\"optional-parameters-and-properties\" style=\"position:relative;\"><a href=\"#optional-parameters-and-properties\" aria-label=\"optional parameters and properties permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Optional parameters and properties</h3>\n<p>With <a href=\"/tsconfig#strictNullChecks\"><code>--strictNullChecks</code></a>, an optional parameter automatically adds <code>| undefined</code>:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f(x: number, y?: number | undefined): number'>f</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: number'>x</data-lsp></span><span style=\"color: #000000\">: number, </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: number | undefined'>y</data-lsp></span><span style=\"color: #000000\">?: number) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: number'>x</data-lsp></span><span style=\"color: #000000\"> + (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: number | undefined'>y</data-lsp></span><span style=\"color: #000000\"> || </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #000000\"><data-lsp lsp='function f(x: number, y?: number | undefined): number'>f</data-lsp>(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">, </span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\"><data-lsp lsp='function f(x: number, y?: number | undefined): number'>f</data-lsp>(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\"><data-lsp lsp='function f(x: number, y?: number | undefined): number'>f</data-lsp>(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">, </span><span style=\"color: #0000FF\"><data-lsp lsp='var undefined'>undefined</data-lsp></span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\"><data-lsp lsp='function f(x: number, y?: number | undefined): number'>f</data-lsp>(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">, </span><span style=\"color: #0000FF\"><data-err>null</data-err></span><span style=\"color: #000000\">);</span>\n<span class=\"error\"><span>Argument of type 'null' is not assignable to parameter of type 'number | undefined'.</span><span class=\"code\">2345</span></span><span class=\"error-behind\">Argument of type 'null' is not assignable to parameter of type 'number | undefined'.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAGYCuAdgMYAuAlnCaAQBQAeqJRAtgEYwA0oAngH5WHbtACUoAN55QoaJApFodJqADUoBv1AAfXaAAM4gNx4AvnkIMAjHzSnrNx4zuhSAE0gEqJSB5dbPjYAGxDTIA'>Try</a></div></pre>\n<p>The same is true for optional properties:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">class</span><span style=\"color: #000000\"> <data-lsp lsp='class C'>C</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.a: number'>a</data-lsp></span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.b?: number | undefined'>b</data-lsp></span><span style=\"color: #000000\">?: number;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let c: C'>c</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='constructor C(): C'>C</data-lsp>();</span>\n\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let c: C'>c</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.a: number'>a</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #09835A\">12</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let c: C'>c</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.a: number'>a</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #0000FF\"><data-lsp lsp='var undefined'>undefined</data-lsp></span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'undefined' is not assignable to type 'number'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'undefined' is not assignable to type 'number'.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let c: C'>c</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.b?: number | undefined'>b</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #09835A\">13</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let c: C'>c</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.b?: number | undefined'>b</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #0000FF\"><data-lsp lsp='var undefined'>undefined</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let c: C'>c</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) C.b?: number | undefined'>b</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #0000FF\">null</span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'null' is not assignable to type 'number | undefined'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'null' is not assignable to type 'number | undefined'.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEGcBcCcEsDG0BcoBmBDANpApgFAgQwLIByArttgMIAWeiA1pGnJYceHrLAPaw2oAEwBmESIKJsmSJFC1QAbwKhQmNADtKAWwBGvANxrQ+gPza9h2CYC+BAtjzRQiUAF5QWvAHdFABQAlCbSAHSYnqAAjCImiBFRlFoAJnjo8D4p8WH6UdFiOXleyWkZWUVROjRGQA'>Try</a></div></pre>\n<h3 id=\"type-guards-and-type-assertions\" style=\"position:relative;\"><a href=\"#type-guards-and-type-assertions\" aria-label=\"type guards and type assertions permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Type guards and type assertions</h3>\n<p>Since nullable types are implemented with a union, you need to use a type guard to get rid of the <code>null</code>.\nFortunately, this is the same code you’d write in JavaScript:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f(stringOrNull: string | null): string'>f</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) stringOrNull: string | null'>stringOrNull</data-lsp></span><span style=\"color: #000000\">: string | null): string {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) stringOrNull: string | null'>stringOrNull</data-lsp></span><span style=\"color: #000000\"> === </span><span style=\"color: #0000FF\">null</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #A31515\">\"default\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  } </span><span style=\"color: #0000FF\">else</span><span style=\"color: #000000\"> {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) stringOrNull: string'>stringOrNull</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABMAFAZygJxmA5geUwDkQAbUgLkQ2z0QB9EwzSBKKmnXRAbwChEiGMETosXQiXKIAvHKYtWvAYMSYAplBCYkAIgAm64AEMyUXQG4VAX0TrSadctVrN2pJzySWVwdb7WQA'>Try</a></div></pre>\n<p>The <code>null</code> elimination is pretty obvious here, but you can use terser operators too:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f(stringOrNull: string | null): string'>f</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) stringOrNull: string | null'>stringOrNull</data-lsp></span><span style=\"color: #000000\">: string | null): string {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) stringOrNull: string | null'>stringOrNull</data-lsp></span><span style=\"color: #000000\"> || </span><span style=\"color: #A31515\">\"default\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABMAFAZygJxmA5geUwDkQAbUgLkQ2z0QB9EwzSBKKmnXRAbwChEiTAFMoITEk55CJcg0YAiACbDgAQzJQFAbj4BfIA'>Try</a></div></pre>\n<p>In cases where the compiler can’t eliminate <code>null</code> or <code>undefined</code>, you can use the type assertion operator to manually remove them.\nThe syntax is postfix <code>!</code>: <code>identifier!</code> removes <code>null</code> and <code>undefined</code> from the type of <code>identifier</code>:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface UserAccount'>UserAccount</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) UserAccount.id: number'>id</data-lsp></span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) UserAccount.email?: string | undefined'>email</data-lsp></span><span style=\"color: #000000\">?: string;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='const user: UserAccount | undefined'>user</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getUser(id: string): UserAccount | undefined'>getUser</data-lsp>(</span><span style=\"color: #A31515\">\"admin\"</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='const user: UserAccount | undefined'>user</data-lsp></data-err></span><span style=\"color: #000000\">.<data-lsp lsp='(property) UserAccount.id: number'>id</data-lsp>;</span>\n<span class=\"error\"><span>Object is possibly 'undefined'.</span><span class=\"code\">2532</span></span><span class=\"error-behind\">Object is possibly 'undefined'.</span>\n<span style=\"color: #0000FF\">if</span><span style=\"color: #000000\"> (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='const user: UserAccount | undefined'>user</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='const user: UserAccount'>user</data-lsp></span><span style=\"color: #000000\">.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) UserAccount.email?: string | undefined'>email</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) String.length: number'>length</data-lsp>;</span>\n<span class=\"error\"><span>Object is possibly 'undefined'.</span><span class=\"code\">2532</span></span><span class=\"error-behind\">Object is possibly 'undefined'.</span><span style=\"color: #000000\">}</span>\n\n<span style=\"color: #008000\">// Instead if you are sure that these objects or fields exist, the</span>\n<span style=\"color: #008000\">// postfix ! lets you short circuit the nullability</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='const user: UserAccount | undefined'>user</data-lsp></span><span style=\"color: #000000\">!.</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) UserAccount.email?: string | undefined'>email</data-lsp></span><span style=\"color: #000000\">!.<data-lsp lsp='(property) String.length: number'>length</data-lsp>;</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYDMaBQAzAVwDsBjAFwEs5jQBzScgVURgApKATVRc6S4nQCUqFjACCpUnBLlQAH1AlOkfAMidQAb1yhQ0RoWi0tAX1ABDRJeIBPANy5TuEKAC0H0oXIe3uAeQw+BakkKBi0JLSstq6oFyoxIQAtgBGMI56kMkWlAA2APw8fAJ0js640sS8SqzQoAC89IwRbABEFpzJAm1CjoR1AHRcjv74oGwDMEKxelPQg9m5eYN5kILkABbluC5gAJLVgZ3x47YylgagiEZhWxZyW5CsoHCpAFaQFNYIoGqQeU41kgAA9KLwADSgJ57UAABzgvDUINAAEJQGtyNZzoRrpsEHJSJRoF5KI9NmEknk8hZUvkybZcPNUYscvkWWsNtsgA'>Try</a></div></pre>\n<h2 id=\"type-aliases\" style=\"position:relative;\"><a href=\"#type-aliases\" aria-label=\"type aliases permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Type Aliases</h2>\n<p>Type aliases create a new name for a type.\nType aliases are sometimes similar to interfaces, but can name primitives, unions, tuples, and any other types that you’d otherwise have to write by hand.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Second = number'>Second</data-lsp> = number;</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let timeInSecond: number'>timeInSecond</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> number </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">10</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let time: number'>time</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='type Second = number'>Second</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #09835A\">10</span><span style=\"color: #000000\">;</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAyhDGB7AdgEygXisgrgWwCMIAnAbgChyAbCYKYASzwgElk4k0AubfI4zFACMABgo06jZjw4p0WUaSA'>Try</a></div></pre>\n<p>Aliasing doesn’t actually create a new type - it creates a new <em>name</em> to refer to that type.\nAliasing a primitive is not terribly useful, though it can be used as a form of documentation.</p>\n<p>Just like interfaces, type aliases can also be generic - we can just add type parameters and use them on the right side of the alias declaration:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Container&lt;T&gt; = { </span><span style=\"color: #1A1A1A\">value</span><span style=\"color: #000000\">: T };</span></code></div></pre>\n<p>We can also have a type alias refer to itself in a property:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Tree&lt;T&gt; = {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">value</span><span style=\"color: #000000\">: T;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">left</span><span style=\"color: #000000\">?: Tree&lt;T&gt;;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">right</span><span style=\"color: #000000\">?: Tree&lt;T&gt;;</span>\n<span style=\"color: #000000\">};</span></code></div></pre>\n<p>Together with <a href=\"/docs/handbook/unions-and-intersections.html\">intersection</a> types, we can make some pretty mind-bending types:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type LinkedList&amp;lt;Type> = Type &amp;amp; {&amp;#13;    next: LinkedList&amp;lt;Type>;&amp;#13;}'>LinkedList</data-lsp>&lt;<data-lsp lsp='(type parameter) Type in type LinkedList&amp;lt;Type>'>Type</data-lsp>> = <data-lsp lsp='(type parameter) Type in type LinkedList&amp;lt;Type>'>Type</data-lsp> &amp; { </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) next: LinkedList&amp;lt;Type>'>next</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='type LinkedList&amp;lt;Type> = Type &amp;amp; {&amp;#13;    next: LinkedList&amp;lt;Type>;&amp;#13;}'>LinkedList</data-lsp>&lt;<data-lsp lsp='(type parameter) Type in type LinkedList&amp;lt;Type>'>Type</data-lsp>> };</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Person'>Person</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Person.name: string'>name</data-lsp></span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let people: LinkedList&amp;lt;Person>'>people</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getDriversLicenseQueue(): LinkedList&amp;lt;Person>'>getDriversLicenseQueue</data-lsp>();</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let people: LinkedList&amp;lt;Person>'>people</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) Person.name: string'>name</data-lsp>;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let people: LinkedList&amp;lt;Person>'>people</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) next: LinkedList&amp;lt;Person>'>next</data-lsp>.<data-lsp lsp='(property) Person.name: string'>name</data-lsp>;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let people: LinkedList&amp;lt;Person>'>people</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) next: LinkedList&amp;lt;Person>'>next</data-lsp>.<data-lsp lsp='(property) next: LinkedList&amp;lt;Person>'>next</data-lsp>.<data-lsp lsp='(property) Person.name: string'>name</data-lsp>;</span>\n<span style=\"color: #1A1A1A\"><data-lsp lsp='let people: LinkedList&amp;lt;Person>'>people</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(property) next: LinkedList&amp;lt;Person>'>next</data-lsp>.<data-lsp lsp='(property) next: LinkedList&amp;lt;Person>'>next</data-lsp>.<data-lsp lsp='(property) next: LinkedList&amp;lt;Person>'>next</data-lsp>.<data-lsp lsp='(property) Person.name: string'>name</data-lsp>;</span>\n<span class='query'>//                  ^ = (property) next: LinkedList<Person></span></code><a href='https://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXwHMQMARGLANxBgGcAZLMEVGkARWRE4AoBKALngNUAaxDAGNDAB4ACtRp4AfAG4AUAHoN8ALR6wyDHp1qMATwAOCYWIlYp0gCqWQS+AF54zq-ABk8AG94VBAADwxBG3FJGW9XeABfdTUsVAxqRCgmeHlaPEC1eGCoAFsQQSlyVAJ1BLU1CGJ4KxwLRo9CYjJKBQYmFnZOHl51FraQADpUUpBRkFbGqbCMKZm5hcmQ8KXt6bL18Z2VrePl1f3NbSLrm9vrgD0AfiA'>Try</a></div></pre>\n<h2 id=\"interfaces-vs-type-aliases\" style=\"position:relative;\"><a href=\"#interfaces-vs-type-aliases\" aria-label=\"interfaces vs type aliases permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Interfaces vs. Type Aliases</h2>\n<p>As we mentioned, type aliases can act sort of like interfaces; however, there are some subtle differences.</p>\n<p>Almost all features of an <code>interface</code> are available in <code>type</code>, the key distinction is that a type cannot be re-opened to add new properties vs a interface which is always extendable.</p>\n<table class='full-width-table'>\n  <tbody>\n    <tr>\n      <th><code>Interface</code></th>\n      <th><code>Type</code></th>\n    </tr>\n    <tr>\n      <td>\n        <p>Extending an interface</p>\n        <code><pre>\ninterface Animal {\n  name: string\n}<br/>\ninterface Bear extends Animal {\n  honey: boolean\n}<br/>\nconst bear = getBear() \nbear.name\nbear.honey\n        </pre></code>\n      </td>\n      <td>\n        <p>Extending a type via intersections</p>\n        <code><pre>\ntype Animal = {\n  name: string\n}<br/>\ntype Bear = Animal & { \n  honey: Boolean \n}<br/>\nconst bear = getBear();\nbear.name;\nbear.honey;\n        </pre></code>\n      </td>\n    </tr>\n    <tr>\n      <td>\n        <p>Adding new fields to an existing interface</p>\n        <code><pre>\ninterface Window {\n  title: string\n}<br/>\ninterface Window {\n  ts: import(\"typescript\")\n}<br/>\nconst src = 'const a = \"Hello World\"';\nwindow.ts.transpileModule(src, {});\n        </pre></code>\n      </td>\n      <td>\n        <p>A type cannot be changed after being created</p>\n        <code><pre>\ntype Window = {\n  title: string\n}<br/>\ntype Window = {\n  ts: import(\"typescript\")\n}<br/>\n// Error: Duplicate identifier 'Window'.<br/>\n        </pre></code>\n      </td>\n    </tr>\n    </tbody>\n</table>\n<p>Because an interface more closely maps how JavaScript object work <a href=\"https://wikipedia.org/wiki/Open/closed_principle\">by being open to extension</a>, we recommend using an interface over a type alias when possible.</p>\n<p>On the other hand, if you can’t express some shape with an interface and you need to use a union or tuple type, type aliases are usually the way to go.</p>\n<h2 id=\"enum-member-types\" style=\"position:relative;\"><a href=\"#enum-member-types\" aria-label=\"enum member types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Enum Member Types</h2>\n<p>As mentioned in <a href=\"./enums.html#union-enums-and-enum-member-types\">our section on enums</a>, enum members have types when every member is literal-initialized.</p>\n<p>Much of the time when we talk about “singleton types”, we’re referring to both enum member types as well as numeric/string literal types, though many users will use “singleton types” and “literal types” interchangeably.</p>\n<h2 id=\"polymorphic-this-types\" style=\"position:relative;\"><a href=\"#polymorphic-this-types\" aria-label=\"polymorphic this types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Polymorphic <code>this</code> types</h2>\n<p>A polymorphic <code>this</code> type represents a type that is the <em>subtype</em> of the containing class or interface.\nThis is called <em>F</em>-bounded polymorphism, a lot of people know it as the <a href=\"https://en.wikipedia.org/wiki/Fluent_interface\">fluent API</a> pattern.\nThis makes hierarchical fluent interfaces much easier to express, for example.\nTake a simple calculator that returns <code>this</code> after each operation:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">class</span><span style=\"color: #000000\"> <data-lsp lsp='class BasicCalculator'>BasicCalculator</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">public</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">constructor</span><span style=\"color: #000000\">(</span><span style=\"color: #0000FF\">protected</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) BasicCalculator.value: number'>value</data-lsp></span><span style=\"color: #000000\">: number = </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">) {}</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">public</span><span style=\"color: #000000\"> <data-lsp lsp='(method) BasicCalculator.currentValue(): number'>currentValue</data-lsp>(): number {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.<data-lsp lsp='(property) BasicCalculator.value: number'>value</data-lsp>;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">public</span><span style=\"color: #000000\"> <data-lsp lsp='(method) BasicCalculator.add(operand: number): this'>add</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) operand: number'>operand</data-lsp></span><span style=\"color: #000000\">: number): this {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.<data-lsp lsp='(property) BasicCalculator.value: number'>value</data-lsp> += </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) operand: number'>operand</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">public</span><span style=\"color: #000000\"> <data-lsp lsp='(method) BasicCalculator.multiply(operand: number): this'>multiply</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) operand: number'>operand</data-lsp></span><span style=\"color: #000000\">: number): this {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.<data-lsp lsp='(property) BasicCalculator.value: number'>value</data-lsp> *= </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) operand: number'>operand</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// ... other operations go here ...</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let v: number'>v</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='constructor BasicCalculator(value?: number): BasicCalculator'>BasicCalculator</data-lsp>(</span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">).<data-lsp lsp='(method) BasicCalculator.multiply(operand: number): this'>multiply</data-lsp>(</span><span style=\"color: #09835A\">5</span><span style=\"color: #000000\">).<data-lsp lsp='(method) BasicCalculator.add(operand: number): this'>add</data-lsp>(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">).<data-lsp lsp='(method) BasicCalculator.currentValue(): number'>currentValue</data-lsp>();</span></code><a href='https://www.typescriptlang.org/play/#code/MYGwhgzhAEBCkEtgGEwmAV3AFwPYCdoBvAKGmgAcMAjEJaYXAOwm3w2D3wAoL9dsAU06CAJtABuaDIIBc0JhgC21QYQC80AAwBKYgF8ylGnWAMM+fIKbYAatMHcd8xSrXEj5K9gtNo2AAsECAA6KRAZAG4jQ3IqWnowUVFuXAo1MCZRF2VVfGd-IJhScnJA4LCHaABqTTSMrOjS6G9fQuCm6FjjBLMlLGwEChAAT1T0-EzshVy1AvLiz3bQ8JloACo6ianOr0EffD8Fzu6AelPoEKvoAQD3esnB5hgAc1xoO6tLq5JDEhB9pJoJomIIAO5wRAoNCYHAEbgAJh0IX6IEGwzGAFZkUkUgBGZGYSzWOwOJyRIA'>Try</a></div></pre>\n<p>Since the class uses <code>this</code> types, you can extend it and the new class can use the old methods with no changes.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">class</span><span style=\"color: #000000\"> <data-lsp lsp='class ScientificCalculator'>ScientificCalculator</data-lsp> </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> <data-lsp lsp='class BasicCalculator'>BasicCalculator</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">public</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">constructor</span><span style=\"color: #000000\">(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: number'>value</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #09835A\">0</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">super</span><span style=\"color: #000000\">(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: number'>value</data-lsp></span><span style=\"color: #000000\">);</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">public</span><span style=\"color: #000000\"> <data-lsp lsp='(method) ScientificCalculator.sin(): this'>sin</data-lsp>() {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.<data-lsp lsp='(property) BasicCalculator.value: number'>value</data-lsp> = <data-lsp lsp='var Math: Math'>Math</data-lsp>.<data-lsp lsp='(method) Math.sin(x: number): number'>sin</data-lsp>(</span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">.<data-lsp lsp='(property) BasicCalculator.value: number'>value</data-lsp>);</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">this</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// ... other operations go here ...</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let v: number'>v</data-lsp> </span><span style=\"color: #000000\">= </span><span style=\"color: #0000FF\">new</span><span style=\"color: #000000\"> <data-lsp lsp='constructor ScientificCalculator(value?: number): ScientificCalculator'>ScientificCalculator</data-lsp>(</span><span style=\"color: #09835A\">2</span><span style=\"color: #000000\">).<data-lsp lsp='(method) BasicCalculator.multiply(operand: number): this'>multiply</data-lsp>(</span><span style=\"color: #09835A\">5</span><span style=\"color: #000000\">).<data-lsp lsp='(method) ScientificCalculator.sin(): ScientificCalculator'>sin</data-lsp>().<data-lsp lsp='(method) BasicCalculator.add(operand: number): this'>add</data-lsp>(</span><span style=\"color: #09835A\">1</span><span style=\"color: #000000\">).<data-lsp lsp='(method) BasicCalculator.currentValue(): number'>currentValue</data-lsp>();</span></code><a href='https://www.typescriptlang.org/play/#code/MYGwhgzhAEBCkEtgGEwmAV3AFwPYCdoBvAKGmgAcMAjEJaYXAOwm3w2D3wAoL9dsAU06CAJtABuaDIIBc0JhgC21QYQC80AAwBKYgF8ylGnWAMM+fIKbYAatMHcd8xSrXEj5K9gtNo2AAsECAA6KRAZAG4jQ3IqWnowUVFuXAo1MCZRF2VVfGd-IJhScnJA4LCHaABqTTSMrOjS6G9fQuCm6FjjBLMlLGwEChAAT1T0-EzshVy1AvLiz3bQ8JloACo6ianOr0EffD8Fzu6AelPoEKvoAQD3esnB5hgAc1xoO6tLq5JDc+gALRAzDYIEAkigSAwADKwAQ1kGADMkKh0FgwFxoIIAB5CLIweAQFFoTA4AgeOImeiMFhsDhcbirQTQTS6CmlCAYCaMhw6E5GeKmaBEphOdllIqVCLMzQAWQxARCIu4CylMj5S1ah2W-PI-yuIRugXu2yeLGgbw+amZBt+JBIIH2khZCkEAHdoLD4TYEMiUCT0QyAEw6EL9ECDYZjACsoeVoaSKQAjKHMJYEfZpU5IkA'>Try</a></div></pre>\n<p>Without <code>this</code> types, <code>ScientificCalculator</code> would not have been able to extend <code>BasicCalculator</code> and keep the fluent interface.\n<code>multiply</code> would have returned <code>BasicCalculator</code>, which doesn’t have the <code>sin</code> method.\nHowever, with <code>this</code> types, <code>multiply</code> returns <code>this</code>, which is <code>ScientificCalculator</code> here.</p>\n<h2 id=\"index-types\" style=\"position:relative;\"><a href=\"#index-types\" aria-label=\"index types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Index types</h2>\n<p>With index types, you can get the compiler to check code that uses dynamic property names.\nFor example, a common JavaScript pattern is to pick a subset of properties from an object:</p>\n<pre class=\"shiki\"><div class=\"language-id\">js</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> pluck(</span><span style=\"color: #1A1A1A\">o</span><span style=\"color: #000000\">, </span><span style=\"color: #1A1A1A\">propertyNames</span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">propertyNames</span><span style=\"color: #000000\">.map((</span><span style=\"color: #1A1A1A\">n</span><span style=\"color: #000000\">) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">o</span><span style=\"color: #000000\">[</span><span style=\"color: #1A1A1A\">n</span><span style=\"color: #000000\">]);</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>Here’s how you would write and use this function in TypeScript, using the <strong>index type query</strong> and <strong>indexed access</strong> operators:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>pluck</data-lsp>&lt;<data-lsp lsp='(type parameter) T in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>T</data-lsp>, <data-lsp lsp='(type parameter) K in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>K</data-lsp> </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>T</data-lsp>>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) o: T'>o</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>T</data-lsp>, </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) propertyNames: K[]'>propertyNames</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) K in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>K</data-lsp>[]): <data-lsp lsp='(type parameter) T in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>T</data-lsp>[<data-lsp lsp='(type parameter) K in pluck&amp;lt;T, K extends keyof T>(o: T, propertyNames: K[]): T[K][]'>K</data-lsp>][] {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) propertyNames: K[]'>propertyNames</data-lsp></span><span style=\"color: #000000\">.<data-lsp lsp='(method) Array&amp;lt;K>.map&amp;lt;T[K]>(callbackfn: (value: K, index: number, array: K[]) => T[K], thisArg?: any): T[K][]'>map</data-lsp>((</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) n: K extends keyof T'>n</data-lsp></span><span style=\"color: #000000\">) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) o: T'>o</data-lsp></span><span style=\"color: #000000\">[</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) n: K extends keyof T'>n</data-lsp></span><span style=\"color: #000000\">]);</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Car'>Car</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Car.manufacturer: string'>manufacturer</data-lsp></span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Car.model: string'>model</data-lsp></span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Car.year: number'>year</data-lsp></span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let taxi: Car'>taxi</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Car'>Car</data-lsp> </span><span style=\"color: #000000\">= {</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(property) Car.manufacturer: string'>manufacturer</data-lsp>: </span><span style=\"color: #A31515\">\"Toyota\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(property) Car.model: string'>model</data-lsp>: </span><span style=\"color: #A31515\">\"Camry\"</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(property) Car.year: number'>year</data-lsp>: </span><span style=\"color: #09835A\">2014</span><span style=\"color: #000000\">,</span>\n<span style=\"color: #000000\">};</span>\n\n<span style=\"color: #008000\">// Manufacturer and model are both of type string,</span>\n<span style=\"color: #008000\">// so we can pluck them both into a typed string array</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let makeAndModel: string[]'>makeAndModel</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string[] </span><span style=\"color: #000000\">= <data-lsp lsp='function pluck&amp;lt;Car, &amp;quot;manufacturer&amp;quot; | &amp;quot;model&amp;quot;>(o: Car, propertyNames: (&amp;quot;manufacturer&amp;quot; | &amp;quot;model&amp;quot;)[]): string[]'>pluck</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let taxi: Car'>taxi</data-lsp></span><span style=\"color: #000000\">, [</span><span style=\"color: #A31515\">\"manufacturer\"</span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"model\"</span><span style=\"color: #000000\">]);</span>\n\n<span style=\"color: #008000\">// If we try to pluck model and year, we get an</span>\n<span style=\"color: #008000\">// array of a union type: (string | number)[]</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let modelYear: (string | number)[]'>modelYear</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function pluck&amp;lt;Car, &amp;quot;model&amp;quot; | &amp;quot;year&amp;quot;>(o: Car, propertyNames: (&amp;quot;model&amp;quot; | &amp;quot;year&amp;quot;)[]): (string | number)[]'>pluck</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let taxi: Car'>taxi</data-lsp></span><span style=\"color: #000000\">, [</span><span style=\"color: #A31515\">\"model\"</span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"year\"</span><span style=\"color: #000000\">]);</span></code><a href='https://www.typescriptlang.org/play/#code/GYVwdgxgLglg9mABABwDYggawDwBUA0iA0ogKYAeUpYAJgM6KakCecwiuAfABRwBcHQsgBOcZKWFRmAOQCGAW1J0BRANoBdAJQDcqouo2IA3gChEiYaSghhSEWIlS5iugDp5s5N25hNiALyciHCqYFoA3CYAviYmMGBUwsCyEKSIAMKywsZmiB5gIMnQNhICdFDC8QDmkebycDSkqGUV1bWIzKRZAgXyAEYSkTEmqFaIULLkMAKZ2f45dbIFRdaWwgIARLhwrBMb+Ln1jc2IG5nywsz7uZ3diABMAAwAjAAsB1GRJgD034gAsktCilVhJEEsaHkGk1wZZEH04FAABbBdhScSIcqVMBVA6-TFwRAAdzSECWKHQWHGSNI8nhiJR8SghNk42Y4khWOqsOEsmYIzGHiYAEFaP9oScuTjDPM0BhMNwJlNCKoNvlgcU1vtTkcmhsIrF8QBJdgk8aXcaEuVU3WocG0DpdYSEM1VMZLH5-LK85io8GIcDwJDo0gCbhSqqIAA+iF6A2Emg0AqgUOOAE0nQEKfLFZMYCq1RLtRtbsJ9ZpwkA'>Try</a></div></pre>\n<p>The compiler checks that <code>manufacturer</code> and <code>model</code> are actually properties on <code>Car</code>.\nThe example introduces a couple of new type operators.\nFirst is <code>keyof T</code>, the <strong>index type query operator</strong>.\nFor any type <code>T</code>, <code>keyof T</code> is the union of known, public property names of <code>T</code>.\nFor example:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let carProps: &amp;quot;manufacturer&amp;quot; | &amp;quot;model&amp;quot; | &amp;quot;year&amp;quot;'>carProps</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Car'>Car</data-lsp></span><span style=\"color: #000000\">;</span>\n<span class='query'>//         ^ = let carProps: \"manufacturer\" | \"model\" | \"year\"</span></code><a href='https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgMJysg3gKGcgWzhAFd4EwSpoAuZAZzClAHMBuPQgewBMIAbOo2Yh2nAJ4QMdUgQBG0DgF8cAelXIAtNoQkw2zTn4QwyBBgAKULgAd6dANYRxXGGgwd1+bz4B6AfiA'>Try</a></div></pre>\n<p><code>keyof Car</code> is completely interchangeable with <code>\"manufacturer\" | \"model\" | \"year\"</code>.\nThe difference is that if you add another property to <code>Car</code>, say <code>ownersAddress: string</code>, then <code>keyof Car</code> will automatically update to be <code>\"manufacturer\" | \"model\" | \"year\" | \"ownersAddress\"</code>.\nAnd you can use <code>keyof</code> in generic contexts like <code>pluck</code>, where you can’t possibly know the property names ahead of time.\nThat means the compiler will check that you pass the right set of property names to <code>pluck</code>:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// error, Type '\"unknown\"' is not assignable to type '\"manufacturer\" | \"model\" | \"year\"'</span>\n<span style=\"color: #000000\">pluck(</span><span style=\"color: #1A1A1A\">taxi</span><span style=\"color: #000000\">, [</span><span style=\"color: #A31515\">\"year\"</span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"unknown\"</span><span style=\"color: #000000\">]);</span></code></div></pre>\n<p>The second operator is <code>T[K]</code>, the <strong>indexed access operator</strong>.\nHere, the type syntax reflects the expression syntax.\nThat means that <code>taxi[\"name\"]</code> has the type <code>Car[\"name\"]</code> — which in our example is just <code>string</code>.\nHowever, just like index type queries, you can use <code>T[K]</code> in a generic context, which is where its real power comes to life.\nYou just have to make sure that the type variable <code>K extends keyof T</code>.\nHere’s another example with a function named <code>getProperty</code>.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> getProperty&lt;T, K </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #000000\"> T&gt;(</span><span style=\"color: #1A1A1A\">o</span><span style=\"color: #000000\">: T, </span><span style=\"color: #1A1A1A\">propertyName</span><span style=\"color: #000000\">: K): T[K] {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">o</span><span style=\"color: #000000\">[</span><span style=\"color: #1A1A1A\">propertyName</span><span style=\"color: #000000\">]; </span><span style=\"color: #008000\">// o[propertyName] is of type T[K]</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>In <code>getProperty</code>, <code>o: T</code> and <code>propertyName: K</code>, so that means <code>o[propertyName]: T[K]</code>.\nOnce you return the <code>T[K]</code> result, the compiler will instantiate the actual type of the key, so the return type of <code>getProperty</code> will vary according to which property you request.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let manufacturer: string'>manufacturer</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string </span><span style=\"color: #000000\">= <data-lsp lsp='function getProperty&amp;lt;Car, &amp;quot;manufacturer&amp;quot;>(o: Car, propertyName: &amp;quot;manufacturer&amp;quot;): string'>getProperty</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let taxi: Car'>taxi</data-lsp></span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"manufacturer\"</span><span style=\"color: #000000\">);</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let year: number'>year</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> number </span><span style=\"color: #000000\">= <data-lsp lsp='function getProperty&amp;lt;Car, &amp;quot;year&amp;quot;>(o: Car, propertyName: &amp;quot;year&amp;quot;): number'>getProperty</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let taxi: Car'>taxi</data-lsp></span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"year\"</span><span style=\"color: #000000\">);</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let unknown: string | number'>unknown</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function getProperty&amp;lt;Car, &amp;quot;manufacturer&amp;quot; | &amp;quot;model&amp;quot; | &amp;quot;year&amp;quot;>(o: Car, propertyName: &amp;quot;manufacturer&amp;quot; | &amp;quot;model&amp;quot; | &amp;quot;year&amp;quot;): string | number'>getProperty</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let taxi: Car'>taxi</data-lsp></span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\"><data-err>&quot;unknown&quot;</data-err></span><span style=\"color: #000000\">);</span>\n<span class=\"error\"><span>Argument of type '\"unknown\"' is not assignable to parameter of type '\"manufacturer\" | \"model\" | \"year\"'.</span><span class=\"code\">2345</span></span><span class=\"error-behind\">Argument of type '\"unknown\"' is not assignable to parameter of type '\"manufacturer\" | \"model\" | \"year\"'.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAGYCuAdgMYAuAlnCaAOaQUAK8ADjBQJ4A8AKgBpQAaVCQAHhUgkAJolABrSFzgFQfAHwAKOKkGg27TlwByAQwC2kVMICUegNrCAuqADeeUKGhMi0OnAOhnAc0NzmVs4A3KAgoIHBoeGWkK5U8qqg3BzqTs54AL54VCRS0ARmZJCgAMJm0O6eoBZmJEQVlH4wqIgU0CX0UU0WcDKQADY9fQNDXlyQ9ahtFgBGMENF40xZZuJUqHUNALyNXi1tHRRd0KgARHxwKhRmtwLDoxN3dRbQXK9N80W6AADABGLBvApDOIAWjhZCIFDhMLwWwozVa7UqVx8N1AvX6JHooBOjBYRjCXC0zz2Qlu5yxnVxt1sQzRoEBeOWa2ODCYrBCxmpuyodM5LKGqO2pAUJDgAHc6KT+RTuMLaaBbjK5YqJUA'>Try</a></div></pre>\n<h2 id=\"index-types-and-index-signatures\" style=\"position:relative;\"><a href=\"#index-types-and-index-signatures\" aria-label=\"index types and index signatures permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Index types and index signatures</h2>\n<p><code>keyof</code> and <code>T[K]</code> interact with index signatures. An index signature parameter type must be ‘string’ or ‘number’.\nIf you have a type with a string index signature, <code>keyof T</code> will be <code>string | number</code>\n(and not just <code>string</code>, since in JavaScript you can access an object property either\nby using strings (<code>object[\"42\"]</code>) or numbers (<code>object[42]</code>)).\nAnd <code>T[string]</code> is just the type of the index signature:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;<data-lsp lsp='(type parameter) T in Dictionary&amp;lt;T>'>T</data-lsp>> {</span>\n<span style=\"color: #000000\">  [</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) key: string'>key</data-lsp></span><span style=\"color: #000000\">: string]: <data-lsp lsp='(type parameter) T in Dictionary&amp;lt;T>'>T</data-lsp>;</span>\n<span style=\"color: #000000\">}</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let keys: string | number'>keys</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;number></span><span style=\"color: #000000\">;</span>\n<span class='query'>//     ^ = let keys: string | number</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let value: number'>value</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;number>[</span><span style=\"color: #A31515\">\"foo\"</span><span style=\"color: #1A1A1A\">]</span><span style=\"color: #000000\">;</span>\n<span class='query'>//      ^ = let value: number</span></code><a href='https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgCLAWYB7EcoCeAPACoB8yA3gFDLIDaA1hAQFzIDOYUoA5gLrsSAbmoBfagBsIYZMwId287DDQYsufMRABXALYAjaGVEB6U3UsA9APxSZyAG5xJOiO3SYceQkV2HjegAiGGxsIP4zC0s6WyA'>Try</a></div></pre>\n<p>If you have a type with a number index signature, <code>keyof T</code> will just be <code>number</code>.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;<data-lsp lsp='(type parameter) T in Dictionary&amp;lt;T>'>T</data-lsp>> {</span>\n<span style=\"color: #000000\">  [</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) key: number'>key</data-lsp></span><span style=\"color: #000000\">: number]: <data-lsp lsp='(type parameter) T in Dictionary&amp;lt;T>'>T</data-lsp>;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let keys: number'>keys</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;number></span><span style=\"color: #000000\">;</span>\n<span class='query'>//     ^ = let keys: number</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let numberValue: number'>numberValue</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;number>[</span><span style=\"color: #09835A\">42</span><span style=\"color: #1A1A1A\">]</span><span style=\"color: #000000\">;</span>\n<span class='query'>//     ^ = let numberValue: number</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let value: any'>value</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> <data-lsp lsp='interface Dictionary&amp;lt;T>'>Dictionary</data-lsp>&lt;number>[</span><span style=\"color: #A31515\"><data-err>&quot;foo&quot;</data-err></span><span style=\"color: #1A1A1A\">]</span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Property 'foo' does not exist on type 'Dictionary&lt;number&gt;'.</span><span class=\"code\">2339</span></span><span class=\"error-behind\">Property 'foo' does not exist on type 'Dictionary&lt;number&gt;'.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYME4BQBLAOwBcYAzAQwGNJQARfK4-OQi6ATwB4AVAPlABvXKFABtANaQOqQgFcAtgCMYAXVQ8A3LgC+uXABtIxUFI4pT0uGXqNmrdt3nKYfbSFGeAegH5Dx0GcVaAA1CgM5SFQGJhY2Ti4g1zEAFjRVdzBPUF9-EwA3cMjouzjHRMVgvjEAIjI4OBqMoA'>Try</a></div></pre>\n<h2 id=\"mapped-types\" style=\"position:relative;\"><a href=\"#mapped-types\" aria-label=\"mapped types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Mapped types</h2>\n<p>A common task is to take an existing type and make each of its properties optional:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> PersonSubset {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">name</span><span style=\"color: #000000\">?: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\">age</span><span style=\"color: #000000\">?: number;</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>Or we might want a readonly version:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> PersonReadonly {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">name</span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">age</span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">}</span></code></div></pre>\n<p>This happens often enough in JavaScript that TypeScript provides a way to create new types based on old types — <strong>mapped types</strong>.\nIn a mapped type, the new type transforms each property in the old type in the same way.\nFor example, you can make all properties of a type <code>readonly</code> or optional.\nHere are a couple of examples:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Readonly&amp;lt;T> = { readonly [P in keyof T]: T[P]; }'>Readonly</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Readonly&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">readonly</span><span style=\"color: #000000\"> [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type Readonly&amp;lt;T>'>T</data-lsp>]: <data-lsp lsp='(type parameter) T in type Readonly&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>];</span>\n<span style=\"color: #000000\">};</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Partial&amp;lt;T> = { [P in keyof T]?: T[P] | undefined; }'>Partial</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Partial&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type Partial&amp;lt;T>'>T</data-lsp>]?: <data-lsp lsp='(type parameter) T in type Partial&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>];</span>\n<span style=\"color: #000000\">};</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEDsHsFECd7XgZwFABcCeAHApqAEp4CGAJtJADZYA8AKgHygC8oA3mqKPKRdVlABtAAqgAlpFABrPFmgAzUPQC6ALmWiVAbjQBfXZlwERJeBnEkqDZm07dREqbPlLVAfg30tug0A'>Try</a></div></pre>\n<p>And to use it:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type PersonPartial = {&amp;#13;    name?: string | undefined;&amp;#13;    age?: number | undefined;&amp;#13;}'>PersonPartial</data-lsp> = <data-lsp lsp='type Partial&amp;lt;T> = { [P in keyof T]?: T[P] | undefined; }'>Partial</data-lsp>&lt;<data-lsp lsp='type Person = {&amp;#13;    name: string;&amp;#13;    age: number;&amp;#13;}'>Person</data-lsp>>;</span>\n<span class='query'>//   ^ = type PersonPartial = {\n    name?: string | undefined;\n    age?: number | undefined;\n}</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type ReadonlyPerson = {&amp;#13;    readonly name: string;&amp;#13;    readonly age: number;&amp;#13;}'>ReadonlyPerson</data-lsp> = <data-lsp lsp='type Readonly&amp;lt;T> = { readonly [P in keyof T]: T[P]; }'>Readonly</data-lsp>&lt;<data-lsp lsp='type Person = {&amp;#13;    name: string;&amp;#13;    age: number;&amp;#13;}'>Person</data-lsp>>;</span>\n<span class='query'>//   ^ = type ReadonlyPerson = {\n    readonly name: string;\n    readonly age: number;\n}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAChBOBnA9gOygXigbwFBSlQEMBbCALikWHgEtUBzAbnyiIYsIFcSAjBFgF8WAehFQAtFIDGXYFIm5QkWAhSoYReMFpEANplhad+gDxwkaAHyjxBAHoB+JeGgAlCEQAmaPSAvqhh7eviDmata2BFBOQA'>Try</a></div></pre>\n<p>Note that this syntax describes a type rather than a member.\nIf you want to add members, you can use an intersection type:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Use this:</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type PartialWithNewMember&amp;lt;T> = { [P in keyof T]?: T[P] | undefined; } &amp;amp; {&amp;#13;    newMember: boolean;&amp;#13;}'>PartialWithNewMember</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type PartialWithNewMember&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type PartialWithNewMember&amp;lt;T>'>T</data-lsp>]?: <data-lsp lsp='(type parameter) T in type PartialWithNewMember&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>];</span>\n<span style=\"color: #000000\">} & { </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) newMember: boolean'>newMember</data-lsp></span><span style=\"color: #000000\">: boolean }</span>\n\n<span style=\"color: #008000\">// This is an error!</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type WrongPartialWithNewMember&amp;lt;T> = { [P in keyof T]?: T[P] | undefined; }'>WrongPartialWithNewMember</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type WrongPartialWithNewMember&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type WrongPartialWithNewMember&amp;lt;T>'>T</data-lsp>]?: <data-lsp lsp='(type parameter) T in type WrongPartialWithNewMember&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>];</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-err>newMember</data-err></span><span style=\"color: #000000\"><data-err>: <data-lsp lsp='any'>boolean</data-lsp>;</data-err></span>\n<span class=\"error\"><span>'boolean' only refers to a type, but is being used as a value here.</br>'}' expected.</span><span class=\"code\">2693<br/>1005</span></span><span class=\"error-behind\">'boolean' only refers to a type, but is being used as a value here.</br>'}' expected.</span><span style=\"color: #000000\"><data-err>}</data-err></span>\n<span class=\"error\"><span>Declaration or statement expected.</span><span class=\"code\">1128</span></span><span class=\"error-behind\">Declaration or statement expected.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwDYCcBmUBGABkIFYD80AOAKBFAFVFJQAXACwEsVqWBPAB2YAFAIbQWHEQBsA6h3YA5SAHcAspAC2AIxgAeACoA+UAF5QAb2qhQAbSGgOAO1ABrSLzgAzUPoC6AflR9O18AbmoAX1AAMgtQRxV1bRhULTg4KUgRZwjqWjB9TkQHYuzQGHhoAEIeAWYZeEcAc1FxSVl5NiU1TR1oA2MzS2s7B2c3D28-QJ8Q8OsEnuToVPTM7PCIoA'>Try</a></div></pre>\n<p>Let’s take a look at the simplest mapped type and its parts:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Keys = &amp;quot;option1&amp;quot; | &amp;quot;option2&amp;quot;'>Keys</data-lsp> = </span><span style=\"color: #A31515\">\"option1\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"option2\"</span><span style=\"color: #000000\">;</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Flags = {&amp;#13;    option1: boolean;&amp;#13;    option2: boolean;&amp;#13;}'>Flags</data-lsp> = { [<data-lsp lsp='(type parameter) K'>K</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='type Keys = &amp;quot;option1&amp;quot; | &amp;quot;option2&amp;quot;'>Keys</data-lsp></span><span style=\"color: #000000\">]: boolean };</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBA0hIGcoF4oCID2ZgEsMDsBGNKAH3S1wICY0BuAKFEigDEAbAQwHMlUBvKAG0YUHPljwEAXQBcUAEYYM7CJwkBfOkA'>Try</a></div></pre>\n<p>The syntax resembles the syntax for index signatures with a <code>for .. in</code> inside.\nThere are three parts:</p>\n<ol>\n<li>The type variable <code>K</code>, which gets bound to each property in turn.</li>\n<li>The string literal union <code>Keys</code>, which contains the names of properties to iterate over.</li>\n<li>The resulting type of the property.</li>\n</ol>\n<p>In this simple example, <code>Keys</code> is a hard-coded list of property names and the property type is always <code>boolean</code>, so this mapped type is equivalent to writing:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Flags = {&amp;#13;    option1: boolean;&amp;#13;    option2: boolean;&amp;#13;}'>Flags</data-lsp> = {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) option1: boolean'>option1</data-lsp></span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) option2: boolean'>option2</data-lsp></span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">};</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYgNgQwOYGcoF4oG8BQUoD2YwAlgQHYCMAXFAEYEFwQLkDcehxZ5ATLQyYt2OAL5sgA'>Try</a></div></pre>\n<p>Real applications, however, look like <code>Readonly</code> or <code>Partial</code> above.\nThey’re based on some existing type, and they transform the properties in some way.\nThat’s where <code>keyof</code> and indexed access types come in:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type NullablePerson = {&amp;#13;    name: string | null;&amp;#13;    age: number | null;&amp;#13;}'>NullablePerson</data-lsp> = { [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='type Person = {&amp;#13;    name: string;&amp;#13;    age: number;&amp;#13;}'>Person</data-lsp></span><span style=\"color: #000000\">]: <data-lsp lsp='type Person = {&amp;#13;    name: string;&amp;#13;    age: number;&amp;#13;}'>Person</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>] | null };</span>\n<span class='query'>//   ^ = type NullablePerson = {\n    name: string | null;\n    age: number | null;\n}</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type PartialPerson = {&amp;#13;    name?: string | undefined;&amp;#13;    age?: number | undefined;&amp;#13;}'>PartialPerson</data-lsp> = { [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='type Person = {&amp;#13;    name: string;&amp;#13;    age: number;&amp;#13;}'>Person</data-lsp></span><span style=\"color: #000000\">]?: <data-lsp lsp='type Person = {&amp;#13;    name: string;&amp;#13;    age: number;&amp;#13;}'>Person</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>] };</span>\n<span class='query'>//   ^ = type PartialPerson = {\n    name?: string | undefined;\n    age?: number | undefined;\n}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAChBOBnA9gOygXigbwFBSlQEMBbCALikWHgEtUBzAbnyiIYsIFcSAjBFgF8WAehFQAtFIDGXYFIm5QkKADkuAGw1FeGiHCRpMOKAG0YUelADWEEMgBmsBClQBdSgdfm3UAD7cWlDCuGIEUAB6APxK4NAwRPDAtEQaXkZY2GYWVrb2TunuUZ4uaD7BouIE0UA'>Try</a></div></pre>\n<p>But it’s more useful to have a general version.</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Nullable&lt;T&gt; = { [P </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> T]: T[P] | null };</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Partial&lt;T&gt; = { [P </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> T]?: T[P] };</span></code></div></pre>\n<p>In these examples, the properties list is <code>keyof T</code> and the resulting type is some variant of <code>T[P]</code>.\nThis is a good template for any general use of mapped types.\nThat’s because this kind of transformation is <a href=\"https://wikipedia.org/wiki/Homomorphism\">homomorphic</a>, which means that the mapping applies only to properties of <code>T</code> and no others.\nThe compiler knows that it can copy all the existing property modifiers before adding any new ones.\nFor example, if <code>Person.name</code> was readonly, <code>Partial&#x3C;Person>.name</code> would be readonly and optional.</p>\n<p>Here’s one more example, in which <code>T[P]</code> is wrapped in a <code>Proxy&#x3C;T></code> class:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Proxy&amp;lt;T> = {&amp;#13;    get(): T;&amp;#13;    set(value: T): void;&amp;#13;}'>Proxy</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Proxy&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(method) get(): T'>get</data-lsp>(): <data-lsp lsp='(type parameter) T in type Proxy&amp;lt;T>'>T</data-lsp>;</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(method) set(value: T): void'>set</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) value: T'>value</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in type Proxy&amp;lt;T>'>T</data-lsp>): void;</span>\n<span style=\"color: #000000\">};</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Proxify&amp;lt;T> = { [P in keyof T]: Proxy&amp;lt;T[P]>; }'>Proxify</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Proxify&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  [<data-lsp lsp='(type parameter) P'>P</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type Proxify&amp;lt;T>'>T</data-lsp>]: <data-lsp lsp='type Proxy&amp;lt;T> = {&amp;#13;    get(): T;&amp;#13;    set(value: T): void;&amp;#13;}'>Proxy</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Proxify&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) P'>P</data-lsp>]>;</span>\n<span style=\"color: #000000\">};</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function proxify&amp;lt;T>(o: T): Proxify&amp;lt;T>'>proxify</data-lsp>&lt;<data-lsp lsp='(type parameter) T in proxify&amp;lt;T>(o: T): Proxify&amp;lt;T>'>T</data-lsp>>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) o: T'>o</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in proxify&amp;lt;T>(o: T): Proxify&amp;lt;T>'>T</data-lsp>): <data-lsp lsp='type Proxify&amp;lt;T> = { [P in keyof T]: Proxy&amp;lt;T[P]>; }'>Proxify</data-lsp>&lt;<data-lsp lsp='(type parameter) T in proxify&amp;lt;T>(o: T): Proxify&amp;lt;T>'>T</data-lsp>> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// ... wrap proxies ...</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let props: {&amp;#13;    rooms: number;&amp;#13;}'>props</data-lsp> </span><span style=\"color: #000000\">= { <data-lsp lsp='(property) rooms: number'>rooms</data-lsp>: </span><span style=\"color: #09835A\">4</span><span style=\"color: #000000\"> };</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let proxyProps: Proxify&amp;lt;{&amp;#13;    rooms: number;&amp;#13;}>'>proxyProps</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function proxify&amp;lt;{&amp;#13;    rooms: number;&amp;#13;}>(o: {&amp;#13;    rooms: number;&amp;#13;}): Proxify&amp;lt;{&amp;#13;    rooms: number;&amp;#13;}>'>proxify</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let props: {&amp;#13;    rooms: number;&amp;#13;}'>props</data-lsp></span><span style=\"color: #000000\">);</span>\n<span class='query'>//  ^ = let proxyProps: Proxify<{\n    rooms: number;\n}></span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEDsHsFECd7XgZwFABcCeAHApqAApIAeWAPACoB8oAvKAN5qigDmeGAFAJQBcoSgG4WoFJy4A3AIYAbAK54BlfqEnQAlgBMRAXxGZcBYtBIaAZhRr0mogNqFQGyKADWeLNHOCAugJNkVA4+1HoG5vKQAMYYGtAuOKQWVtRc0MqqAclUtMysIKAAdMWgAO7w0jigiaYaeChFxWi6aGiynNVIOA0MjKBI0AC2KAIALKD6bR01ZCbdNjPJXDXdPCIFoAB6APxAA'>Try</a></div></pre>\n<p>Note that <code>Readonly&#x3C;T></code> and <code>Partial&#x3C;T></code> are so useful, they are included in TypeScript’s standard library along with <code>Pick</code> and <code>Record</code>:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Pick&lt;T, K </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #000000\"> T&gt; = {</span>\n<span style=\"color: #000000\">  [P </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> K]: T[P];</span>\n<span style=\"color: #000000\">};</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> Record&lt;K </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #000000\"> any, T&gt; = {</span>\n<span style=\"color: #000000\">  [P </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> K]: T;</span>\n<span style=\"color: #000000\">};</span></code></div></pre>\n<p><code>Readonly</code>, <code>Partial</code> and <code>Pick</code> are homomorphic whereas <code>Record</code> is not.\nOne clue that <code>Record</code> is not homomorphic is that it doesn’t take an input type to copy properties from:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type ThreeStringProps = {&amp;#13;    prop1: string;&amp;#13;    prop2: string;&amp;#13;    prop3: string;&amp;#13;}'>ThreeStringProps</data-lsp> = <data-lsp lsp='type Record&amp;lt;K extends string | number | symbol, T> = { [P in K]: T; }'>Record</data-lsp>&lt;</span><span style=\"color: #A31515\">\"prop1\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"prop2\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"prop3\"</span><span style=\"color: #000000\">, string&gt;;</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAKgFgJwhAysBBLAdgcwAoID2YAzlALxQBKEAxoQgCYA8ARGEWAIytQA+UdpwBMvAUOIBmVgBooJdNhwA+ANxA'>Try</a></div></pre>\n<p>Non-homomorphic types are essentially creating new properties, so they can’t copy property modifiers from anywhere.</p>\n<h2 id=\"inference-from-mapped-types\" style=\"position:relative;\"><a href=\"#inference-from-mapped-types\" aria-label=\"inference from mapped types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Inference from mapped types</h2>\n<p>Now that you know how to wrap the properties of a type, the next thing you’ll want to do is unwrap them.\nFortunately, that’s pretty easy:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function unproxify&amp;lt;T>(t: Proxify&amp;lt;T>): T'>unproxify</data-lsp>&lt;<data-lsp lsp='(type parameter) T in unproxify&amp;lt;T>(t: Proxify&amp;lt;T>): T'>T</data-lsp>>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) t: Proxify&amp;lt;T>'>t</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='type Proxify&amp;lt;T> = { [P in keyof T]: Proxy&amp;lt;T[P]>; }'>Proxify</data-lsp>&lt;<data-lsp lsp='(type parameter) T in unproxify&amp;lt;T>(t: Proxify&amp;lt;T>): T'>T</data-lsp>>): <data-lsp lsp='(type parameter) T in unproxify&amp;lt;T>(t: Proxify&amp;lt;T>): T'>T</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let result: T'>result</data-lsp> </span><span style=\"color: #000000\">= {} </span><span style=\"color: #0000FF\">as</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in unproxify&amp;lt;T>(t: Proxify&amp;lt;T>): T'>T</data-lsp>;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">for</span><span style=\"color: #000000\"> (</span><span style=\"color: #0000FF\">const</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='const k: Extract&amp;lt;keyof T, string>'>k</data-lsp></span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) t: Proxify&amp;lt;T>'>t</data-lsp></span><span style=\"color: #000000\">) {</span>\n<span style=\"color: #000000\">    </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let result: T'>result</data-lsp></span><span style=\"color: #000000\">[</span><span style=\"color: #1A1A1A\"><data-lsp lsp='const k: Extract&amp;lt;keyof T, string>'>k</data-lsp></span><span style=\"color: #000000\">] = </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) t: Proxify&amp;lt;T>'>t</data-lsp></span><span style=\"color: #000000\">[</span><span style=\"color: #1A1A1A\"><data-lsp lsp='const k: Extract&amp;lt;keyof T, string>'>k</data-lsp></span><span style=\"color: #000000\">].<data-lsp lsp='(method) get(): T[Extract&amp;lt;keyof T, string>]'>get</data-lsp>();</span>\n<span style=\"color: #000000\">  }</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">return</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let result: T'>result</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let originalProps: {&amp;#13;    rooms: number;&amp;#13;}'>originalProps</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function unproxify&amp;lt;{&amp;#13;    rooms: number;&amp;#13;}>(t: Proxify&amp;lt;{&amp;#13;    rooms: number;&amp;#13;}>): {&amp;#13;    rooms: number;&amp;#13;}'>unproxify</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='let proxyProps: Proxify&amp;lt;{&amp;#13;    rooms: number;&amp;#13;}>'>proxyProps</data-lsp></span><span style=\"color: #000000\">);</span>\n<span class='query'>//  ^ = let originalProps: {\n    rooms: number;\n}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBACgTgewB4gDwBUB8UC8UDeAUFFAOYTAAUAlAFxToDcxUAzhZQG4CGANgK4R66OlE4IAlgBNmAX2aFQkWIiQSAZmiy4CLANowoEgHZQA1hBAJ1DALr14yLQduY5C9f2MBjYBISmYKoaWpiUCMKijmqaGNhEJHAU-HCm+LJQ3KyZxiByhIS8FFBBCGDZePhQiAgAtqz0ACxQ8oXFpSiO5TodIZSl5dTMAPTDUAC0k978wJPjhJ4+fgFQXr2xWJTADsEbmKLouiRFwNUQrPy8p5UZWQzMJOoIcFCU3gGsp2ZGpsDURyQzhcrnozLYdMBQbYAHTkKhDFiyFhJYApUxJYHAfJtU7PCSkEx8LoVVbGdYgfqqEDEhGjEgAPQA-EA'>Try</a></div></pre>\n<p>Note that this unwrapping inference only works on homomorphic mapped types.\nIf the mapped type is not homomorphic you’ll have to give an explicit type parameter to your unwrapping function.</p>\n<h2 id=\"conditional-types\" style=\"position:relative;\"><a href=\"#conditional-types\" aria-label=\"conditional types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Conditional Types</h2>\n<p>A conditional type selects one of two possible types based on a condition expressed as a type relationship test:</p>\n<pre class=\"shiki\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #000000\">T </span><span style=\"color: #1A1A1A\">extends</span><span style=\"color: #000000\"> U ? X : Y</span></code></div></pre>\n<p>The type above means when <code>T</code> is assignable to <code>U</code> the type is <code>X</code>, otherwise the type is <code>Y</code>.</p>\n<p>A conditional type <code>T extends U ? X : Y</code> is either <em>resolved</em> to <code>X</code> or <code>Y</code>, or <em>deferred</em> because the condition depends on one or more type variables.\nWhen <code>T</code> or <code>U</code> contains type variables, whether to resolve to <code>X</code> or <code>Y</code>, or to defer, is determined by whether or not the type system has enough information to conclude that <code>T</code> is always assignable to <code>U</code>.</p>\n<p>As an example of some types that are immediately resolved, we can take a look at the following example:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f&amp;lt;T extends boolean>(x: T): T extends true ? string : number'>f</data-lsp>&lt;<data-lsp lsp='(type parameter) T in f&amp;lt;T extends boolean>(x: T): T extends true ? string : number'>T</data-lsp> </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> boolean&gt;(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T extends boolean'>x</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in f&amp;lt;T extends boolean>(x: T): T extends true ? string : number'>T</data-lsp>): <data-lsp lsp='(type parameter) T in f&amp;lt;T extends boolean>(x: T): T extends true ? string : number'>T</data-lsp> extends true ? string : number;</span>\n\n<span style=\"color: #008000\">// Type is &apos;string | number&apos;</span>\n<span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let x: string | number'>x</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function f&amp;lt;boolean>(x: boolean): string | number'>f</data-lsp>(<data-lsp lsp='var Math: Math'>Math</data-lsp>.<data-lsp lsp='(method) Math.random(): number'>random</data-lsp>() &lt; </span><span style=\"color: #09835A\">0.5</span><span style=\"color: #000000\">);</span>\n<span class='query'>//  ^ = let x: string | number</span></code><a href='https://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEAzArgOzAFwJYHtVIB4AVeEADwxFWAGd4AjHHCEKVAPgAoyAueIgJR8S5StToYYyBAH54NSVlQBzeH1TIAtvRAwA3ACgDAemP8AngAcEWOgHIFMJaoA+8Ddt12DLDPDLwALxInACyUBgAFgB0MGzAOJqcAvAE8AAM0QCsAoam8PAAejJAA'>Try</a></div></pre>\n<p>Another example would be the <code>TypeName</code> type alias, which uses nested conditional types:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type TypeName&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type TypeName&amp;lt;T>'>T</data-lsp> extends string</span>\n<span style=\"color: #000000\">  ? </span><span style=\"color: #A31515\">\"string\"</span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type TypeName&amp;lt;T>'>T</data-lsp> extends number</span>\n<span style=\"color: #000000\">  ? </span><span style=\"color: #A31515\">\"number\"</span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type TypeName&amp;lt;T>'>T</data-lsp> extends boolean</span>\n<span style=\"color: #000000\">  ? </span><span style=\"color: #A31515\">\"boolean\"</span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type TypeName&amp;lt;T>'>T</data-lsp> extends undefined</span>\n<span style=\"color: #000000\">  ? </span><span style=\"color: #A31515\">\"undefined\"</span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type TypeName&amp;lt;T>'>T</data-lsp> extends <data-lsp lsp='interface Function'>Function</data-lsp></span>\n<span style=\"color: #000000\">  ? </span><span style=\"color: #A31515\">\"function\"</span>\n<span style=\"color: #000000\">  : </span><span style=\"color: #A31515\">\"object\"</span><span style=\"color: #000000\">;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T0 = &amp;quot;string&amp;quot;'>T0</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;string>;</span>\n<span class='query'>//   ^ = type T0 = \"string\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = &amp;quot;string&amp;quot;'>T1</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;</span><span style=\"color: #A31515\">\"a\"</span><span style=\"color: #000000\">&gt;;</span>\n<span class='query'>//   ^ = type T1 = \"string\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = &amp;quot;boolean&amp;quot;'>T2</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;true>;</span>\n<span class='query'>//   ^ = type T2 = \"boolean\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T3 = &amp;quot;function&amp;quot;'>T3</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;() </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void&gt;;</span>\n<span class='query'>//   ^ = type T3 = \"function\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T4 = &amp;quot;object&amp;quot;'>T4</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;string[]>;</span>\n<span class='query'>//   ^ = type T4 = \"object\"</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAKuEDkCGBbCAeGA+KBeWUEAHsBAHYAmAzlFcAE4CWZA5gFBRQD8UARHU1a8OUAFwFipSjTIBXFACMI9ET15zFy4Z3ExCJctSgKA9iYA2EJGVV9TFq2W1iJB6VFmUIAM2YQKtryeFD5+FM66+lJGAGKeAMbAjCY2nGreCUkpEXwmCgBWEIm8ANxsbKCQsAAMeLDwyGjoAswsWGUA9B2cUAB6XBXwsACMdXCQjRi8SLztbF09-YNVMABMYw2oGAyyEHMLnEuV0DAAzBsTW+gAFACUeDgAbiaMFPvdhwPHsAAsF4hXFqsADaAF13osuEA'>Try</a></div></pre>\n<p>But as an example of a place where conditional types are deferred - where they stick around instead of picking a branch - would be in the following:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Foo'>Foo</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Foo.propA: boolean'>propA</data-lsp></span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Foo.propB: boolean'>propB</data-lsp></span><span style=\"color: #000000\">: boolean;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f&amp;lt;T>(x: T): T extends Foo ? string : number'>f</data-lsp>&lt;<data-lsp lsp='(type parameter) T in f&amp;lt;T>(x: T): T extends Foo ? string : number'>T</data-lsp>>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T'>x</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in f&amp;lt;T>(x: T): T extends Foo ? string : number'>T</data-lsp>): <data-lsp lsp='(type parameter) T in f&amp;lt;T>(x: T): T extends Foo ? string : number'>T</data-lsp> extends <data-lsp lsp='interface Foo'>Foo</data-lsp> ? string : number;</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function foo&amp;lt;U>(x: U): void'>foo</data-lsp>&lt;<data-lsp lsp='(type parameter) U in foo&amp;lt;U>(x: U): void'>U</data-lsp>>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: U'>x</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) U in foo&amp;lt;U>(x: U): void'>U</data-lsp>) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// Has type &apos;U extends Foo ? string : number&apos;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let a: U extends Foo ? string : number'>a</data-lsp> </span><span style=\"color: #000000\">= <data-lsp lsp='function f&amp;lt;U>(x: U): U extends Foo ? string : number'>f</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: U'>x</data-lsp></span><span style=\"color: #000000\">);</span>\n\n<span style=\"color: #000000\">  </span><span style=\"color: #008000\">// This assignment is allowed though!</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let b: string | number'>b</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string </span><span style=\"color: #000000\">|</span><span style=\"color: #1A1A1A\"> number </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let a: U extends Foo ? string : number'>a</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgGIHt3IN4ChnIAOU6hAggFzIBGmANhHCANz5EmEBCVt6DTrAL65cAEwgI6cKChgBXEAjDB0IZDAA8AFQB8ACgAeVLQEpjyCAcghRAZzSZkAfmS2wUUAHNkVEHIC21NCsuPKKyqrqmBoAqvpGyDEmOGwA9KnIABJw9mAAnoQoAOQxFlYQNvYYWC5uHiDevgFBUEVsDGDIcMgAvOqGJiEE6chaABbA9jm2wJ4g-hWdk110dOgA7hCiyGBj6HKeYwCE7RCd1FR1XsgAPsh+gdC9XUJAA'>Try</a></div></pre>\n<p>In the above, the variable <code>a</code> has a conditional type that hasn’t yet chosen a branch.\nWhen another piece of code ends up calling <code>foo</code>, it will substitute in <code>U</code> with some other type, and TypeScript will re-evaluate the conditional type, deciding whether it can actually pick a branch.</p>\n<p>In the meantime, we can assign a conditional type to any other target type as long as each branch of the conditional is assignable to that target.\nSo in our example above we were able to assign <code>U extends Foo ? string : number</code> to <code>string | number</code> since no matter what the conditional evaluates to, it’s known to be either <code>string</code> or <code>number</code>.</p>\n<h2 id=\"distributive-conditional-types\" style=\"position:relative;\"><a href=\"#distributive-conditional-types\" aria-label=\"distributive conditional types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Distributive conditional types</h2>\n<p>Conditional types in which the checked type is a naked type parameter are called <em>distributive conditional types</em>.\nDistributive conditional types are automatically distributed over union types during instantiation.\nFor example, an instantiation of <code>T extends U ? X : Y</code> with the type argument <code>A | B | C</code> for <code>T</code> is resolved as <code>(A extends U ? X : Y) | (B extends U ? X : Y) | (C extends U ? X : Y)</code>.</p>\n<h4 id=\"example\" style=\"position:relative;\"><a href=\"#example\" aria-label=\"example permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example</h4>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T5 = &amp;quot;string&amp;quot; | &amp;quot;function&amp;quot;'>T5</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;string | (() </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void)&gt;;</span>\n<span class='query'>//   ^ = type T5 = \"string\" | \"function\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T6 = &amp;quot;string&amp;quot; | &amp;quot;undefined&amp;quot; | &amp;quot;object&amp;quot;'>T6</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;string | string[] | undefined>;</span>\n<span class='query'>//   ^ = type T6 = \"string\" | \"undefined\" | \"object\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T7 = &amp;quot;object&amp;quot;'>T7</data-lsp> = <data-lsp lsp='type TypeName&amp;lt;T> = T extends string ? &amp;quot;string&amp;quot; : T extends number ? &amp;quot;number&amp;quot; : T extends boolean ? &amp;quot;boolean&amp;quot; : T extends undefined ? &amp;quot;undefined&amp;quot; : T extends Function ? &amp;quot;function&amp;quot; : &amp;quot;object&amp;quot;'>TypeName</data-lsp>&lt;string[] | number[]>;</span>\n<span class='query'>//   ^ = type T7 = \"object\"</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAKuEDkCGBbCAeGA+KBeWUEAHsBAHYAmAzlFcAE4CWZA5gFBRQD8UARHU1a8OUAFwFipSjTIBXFACMI9ET15zFy4Z3ExCJctSgKA9iYA2EJGVV9TFq2W1iJB6VFmUIAM2YQKtryeFD5+FM66+lJGAGKeAMbAjCY2nGreCUkpEXwmCgBWEIm8ANxsAPTlUAC0tfGywLXVbKCQsACseLDwyGjoAswsUAA+UAAUYwCUeDgAbiaMFJNYZZWcUAB6XC3wsABsXXCQvRgDrCO0DIMA2gC6F8GhZP4rFVWcWzttMADshz2oU5XVh3C4aJT0O6vNYfLhAA'>Try</a></div></pre>\n<p>In instantiations of a distributive conditional type <code>T extends U ? X : Y</code>, references to <code>T</code> within the conditional type are resolved to individual constituents of the union type (i.e. <code>T</code> refers to the individual constituents <em>after</em> the conditional type is distributed over the union type).\nFurthermore, references to <code>T</code> within <code>X</code> have an additional type parameter constraint <code>U</code> (i.e. <code>T</code> is considered assignable to <code>U</code> within <code>X</code>).</p>\n<h4 id=\"example-1\" style=\"position:relative;\"><a href=\"#example-1\" aria-label=\"example 1 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example</h4>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type BoxedValue&amp;lt;T> = {&amp;#13;    value: T;&amp;#13;}'>BoxedValue</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type BoxedValue&amp;lt;T>'>T</data-lsp>> = { </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) value: T'>value</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in type BoxedValue&amp;lt;T>'>T</data-lsp> };</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type BoxedArray&amp;lt;T> = {&amp;#13;    array: T[];&amp;#13;}'>BoxedArray</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type BoxedArray&amp;lt;T>'>T</data-lsp>> = { </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) array: T[]'>array</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in type BoxedArray&amp;lt;T>'>T</data-lsp>[] };</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Boxed&amp;lt;T> = T extends any[] ? BoxedArray&amp;lt;T[number]> : BoxedValue&amp;lt;T>'>Boxed</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Boxed&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type Boxed&amp;lt;T>'>T</data-lsp> extends any[] ? <data-lsp lsp='type BoxedArray&amp;lt;T> = {&amp;#13;    array: T[];&amp;#13;}'>BoxedArray</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Boxed&amp;lt;T>'>T</data-lsp>[number]> : <data-lsp lsp='type BoxedValue&amp;lt;T> = {&amp;#13;    value: T;&amp;#13;}'>BoxedValue</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Boxed&amp;lt;T>'>T</data-lsp>>;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = {&amp;#13;    value: string;&amp;#13;}'>T1</data-lsp> = <data-lsp lsp='type Boxed&amp;lt;T> = T extends any[] ? BoxedArray&amp;lt;T[number]> : BoxedValue&amp;lt;T>'>Boxed</data-lsp>&lt;string>;</span>\n<span class='query'>//   ^ = type T1 = {\n    value: string;\n}</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = {&amp;#13;    array: number[];&amp;#13;}'>T2</data-lsp> = <data-lsp lsp='type Boxed&amp;lt;T> = T extends any[] ? BoxedArray&amp;lt;T[number]> : BoxedValue&amp;lt;T>'>Boxed</data-lsp>&lt;number[]>;</span>\n<span class='query'>//   ^ = type T2 = {\n    array: number[];\n}</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T3 = BoxedValue&amp;lt;string> | BoxedArray&amp;lt;number>'>T3</data-lsp> = <data-lsp lsp='type Boxed&amp;lt;T> = T extends any[] ? BoxedArray&amp;lt;T[number]> : BoxedValue&amp;lt;T>'>Boxed</data-lsp>&lt;string | number[]>;</span>\n<span class='query'>//   ^ = type T3 = BoxedValue<string> | BoxedArray<number></span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAQg9gDwgEwGoEMA2BXCAeAFQD4oBeKAbygDctcAuKAqAXwG4AoUSWRFAQQBOg9CEIlyVdMNGMCAbQC6rTt2jwkycWSZQICYBAB2yAM5R0RkEqgB+XpqEixCo9gC2AIwiDFJRhooGDj4xJxc4NAEAIw6gVqmwIIAlkYA5kScAPRZUHkAerYRPAQATHF8Wm5ePkqZHDl5UIXFUQDMFZp4iSnpUAA+UNXegnXZuQW2QA'>Try</a></div></pre>\n<p>Notice that <code>T</code> has the additional constraint <code>any[]</code> within the true branch of <code>Boxed&#x3C;T></code> and it is therefore possible to refer to the element type of the array as <code>T[number]</code>. Also, notice how the conditional type is distributed over the union type in the last example.</p>\n<p>The distributive property of conditional types can conveniently be used to <em>filter</em> union types:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #008000\">// Remove types from T that are assignable to U</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Diff&amp;lt;T, U> = T extends U ? never : T'>Diff</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Diff&amp;lt;T, U>'>T</data-lsp>, <data-lsp lsp='(type parameter) U in type Diff&amp;lt;T, U>'>U</data-lsp>> = <data-lsp lsp='(type parameter) T in type Diff&amp;lt;T, U>'>T</data-lsp> extends <data-lsp lsp='(type parameter) U in type Diff&amp;lt;T, U>'>U</data-lsp> ? never : <data-lsp lsp='(type parameter) T in type Diff&amp;lt;T, U>'>T</data-lsp>;</span>\n<span style=\"color: #008000\">// Remove types from T that are not assignable to U</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Filter&amp;lt;T, U> = T extends U ? T : never'>Filter</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Filter&amp;lt;T, U>'>T</data-lsp>, <data-lsp lsp='(type parameter) U in type Filter&amp;lt;T, U>'>U</data-lsp>> = <data-lsp lsp='(type parameter) T in type Filter&amp;lt;T, U>'>T</data-lsp> extends <data-lsp lsp='(type parameter) U in type Filter&amp;lt;T, U>'>U</data-lsp> ? <data-lsp lsp='(type parameter) T in type Filter&amp;lt;T, U>'>T</data-lsp> : never;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = &amp;quot;b&amp;quot; | &amp;quot;d&amp;quot;'>T1</data-lsp> = <data-lsp lsp='type Diff&amp;lt;T, U> = T extends U ? never : T'>Diff</data-lsp>&lt;</span><span style=\"color: #A31515\">\"a\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"b\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"c\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"d\"</span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"a\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"c\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"f\"</span><span style=\"color: #000000\">&gt;;</span>\n<span class='query'>//   ^ = type T1 = \"b\" | \"d\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = &amp;quot;a&amp;quot; | &amp;quot;c&amp;quot;'>T2</data-lsp> = <data-lsp lsp='type Filter&amp;lt;T, U> = T extends U ? T : never'>Filter</data-lsp>&lt;</span><span style=\"color: #A31515\">\"a\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"b\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"c\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"d\"</span><span style=\"color: #000000\">, </span><span style=\"color: #A31515\">\"a\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"c\"</span><span style=\"color: #000000\"> | </span><span style=\"color: #A31515\">\"f\"</span><span style=\"color: #000000\">&gt;; </span><span style=\"color: #008000\">// \"a\" | \"c\"</span>\n<span class='query'>//   ^ = type T2 = \"a\" | \"c\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T3 = string | number'>T3</data-lsp> = <data-lsp lsp='type Diff&amp;lt;T, U> = T extends U ? never : T'>Diff</data-lsp>&lt;string | number | (() </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void), <data-lsp lsp='interface Function'>Function</data-lsp>>; </span><span style=\"color: #008000\">// string | number</span>\n<span class='query'>//   ^ = type T3 = string | number</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T4 = () => void'>T4</data-lsp> = <data-lsp lsp='type Filter&amp;lt;T, U> = T extends U ? T : never'>Filter</data-lsp>&lt;string | number | (() </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void), <data-lsp lsp='interface Function'>Function</data-lsp>>; </span><span style=\"color: #008000\">// () =&gt; void</span>\n<span class='query'>//   ^ = type T4 = () => void</span>\n\n<span style=\"color: #008000\">// Remove null and undefined from T</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type NotNullable&amp;lt;T> = T extends null | undefined ? never : T'>NotNullable</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type NotNullable&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='type Diff&amp;lt;T, U> = T extends U ? never : T'>Diff</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type NotNullable&amp;lt;T>'>T</data-lsp>, null | undefined>;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T5 = string | number'>T5</data-lsp> = <data-lsp lsp='type NotNullable&amp;lt;T> = T extends null | undefined ? never : T'>NotNullable</data-lsp>&lt;string | number | undefined>;</span>\n<span class='query'>//   ^ = type T5 = string | number</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T6 = string | string[]'>T6</data-lsp> = <data-lsp lsp='type NotNullable&amp;lt;T> = T extends null | undefined ? never : T'>NotNullable</data-lsp>&lt;string | string[] | null | undefined>;</span>\n<span class='query'>//   ^ = type T6 = string | string[]</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f1&amp;lt;T>(x: T, y: NotNullable&amp;lt;T>): void'>f1</data-lsp>&lt;<data-lsp lsp='(type parameter) T in f1&amp;lt;T>(x: T, y: Diff&amp;lt;T, null | undefined>): void'>T</data-lsp>>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T'>x</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in f1&amp;lt;T>(x: T, y: Diff&amp;lt;T, null | undefined>): void'>T</data-lsp>, </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='type NotNullable&amp;lt;T> = T extends null | undefined ? never : T'>NotNullable</data-lsp>&lt;<data-lsp lsp='(type parameter) T in f1&amp;lt;T>(x: T, y: Diff&amp;lt;T, null | undefined>): void'>T</data-lsp>>) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T'>x</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></data-err></span><span style=\"color: #000000\"> = </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T'>x</data-lsp></span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'T' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'T' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.</span><span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function f2&amp;lt;T extends string | undefined>(x: T, y: NotNullable&amp;lt;T>): void'>f2</data-lsp>&lt;<data-lsp lsp='(type parameter) T in f2&amp;lt;T extends string | undefined>(x: T, y: Diff&amp;lt;T, null | undefined>): void'>T</data-lsp> </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> string | undefined&gt;(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T extends string | undefined'>x</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='(type parameter) T in f2&amp;lt;T extends string | undefined>(x: T, y: Diff&amp;lt;T, null | undefined>): void'>T</data-lsp>, </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='type NotNullable&amp;lt;T> = T extends null | undefined ? never : T'>NotNullable</data-lsp>&lt;<data-lsp lsp='(type parameter) T in f2&amp;lt;T extends string | undefined>(x: T, y: Diff&amp;lt;T, null | undefined>): void'>T</data-lsp>>) {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T extends string | undefined'>x</data-lsp></span><span style=\"color: #000000\"> = </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></data-err></span><span style=\"color: #000000\"> = </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T extends string | undefined'>x</data-lsp></span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'T' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.\n  Type 'string | undefined' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.\n    Type 'undefined' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'T' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.\n  Type 'string | undefined' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.\n    Type 'undefined' is not assignable to type 'Diff&lt;T, null | undefined&gt;'.</span><span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-err><data-lsp lsp='let s1: string'>s1</data-lsp></data-err></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: T extends string | undefined'>x</data-lsp></span><span style=\"color: #000000\">;</span>\n<span class=\"error\"><span>Type 'T' is not assignable to type 'string'.\n  Type 'string | undefined' is not assignable to type 'string'.\n    Type 'undefined' is not assignable to type 'string'.</span><span class=\"code\">2322</span></span><span class=\"error-behind\">Type 'T' is not assignable to type 'string'.\n  Type 'string | undefined' is not assignable to type 'string'.\n    Type 'undefined' is not assignable to type 'string'.</span><span style=\"color: #000000\">  </span><span style=\"color: #0000FF\">let</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\"><data-lsp lsp='let s2: string'>s2</data-lsp></span><span style=\"color: #000000\">:</span><span style=\"color: #1A1A1A\"> string </span><span style=\"color: #000000\">= </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) y: Diff&amp;lt;T, null | undefined>'>y</data-lsp></span><span style=\"color: #000000\">;</span>\n<span style=\"color: #000000\">}</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAMX0bWgFAigBKkAtnAG6SgAuAngA6SKgBm8FoAKgwAsAhvVBDodIYkQBLAOYA7IQCMANnXpxQAVUJNWoACIyOHADy8ANDoB8oALx9QkAB71ICgCbttoAPygCpC00KCovADcxGDkVLQMLGyc3E70wqLidApwGdLySmoaWrr6dABiMqru0BbW2naO-K7uXj7+TqhBIVF6iXwAjA5GJuYAREKjoAA+oKPKkzOjAMYLs56j1uOry9scozZRJKCgAHp+vQa8aEMVVTBmW9Oz8087r+ubE68rr3sHoCRHosVtFjqdzqU+BghsZTGZEPRoDIFHIngoAK4UZQwJ4AClxAEoHHZqHAZJ4CdYyuiFEt6DI4Ap-iQEUiUWjMdjoKDjmcLnReAAWG6VarwxHI1EzDFYnEzfFE+wkskUqk0ukMpkRAFgQnE0Ck8k88GEUGxGhZdGqVRiLygGmeSAcZGQTzJOA8Xj80AAORyPqtqhU6gsDWGcKsgUDTwdTpdngOpshvAArEM-fQA9bg5BxWypVHZaEZrHnUEE4cwLyIX1eAA2dP+wM5vOSp6syUAbQAuhzrTGvHHy4mjibCBx1fTGZx+qHcS5wtZGKgM1mg4VQ0SAN6EY4uIaMKLHRhDFxRAC+pontKnCk4aAszjcHm8oA77JLg7Lrps88XoGXX0m2zDdeBsbdd1AfdHEPSCT0cM9IPUUREH6VB31RBCj1AZC3zQdCJXZGCLyAA'>Try</a></div></pre>\n<p>Conditional types are particularly useful when combined with mapped types:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type FunctionPropertyNames&amp;lt;T> = { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'>FunctionPropertyNames</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type FunctionPropertyNames&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  [<data-lsp lsp='(type parameter) K'>K</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type FunctionPropertyNames&amp;lt;T>'>T</data-lsp>]: <data-lsp lsp='(type parameter) T in type FunctionPropertyNames&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) K'>K</data-lsp>] extends <data-lsp lsp='interface Function'>Function</data-lsp> ? <data-lsp lsp='(type parameter) K'>K</data-lsp> : never;</span>\n<span style=\"color: #000000\">}[</span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type FunctionPropertyNames&amp;lt;T>'>T</data-lsp>];</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type FunctionProperties&amp;lt;T> = { [P in FunctionPropertyNames&amp;lt;T>]: T[P]; }'>FunctionProperties</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type FunctionProperties&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='type Pick&amp;lt;T, K extends keyof T> = { [P in K]: T[P]; }'>Pick</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type FunctionProperties&amp;lt;T>'>T</data-lsp>, <data-lsp lsp='type FunctionPropertyNames&amp;lt;T> = { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'>FunctionPropertyNames</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type FunctionProperties&amp;lt;T>'>T</data-lsp>>>;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type NonFunctionPropertyNames&amp;lt;T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'>NonFunctionPropertyNames</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type NonFunctionPropertyNames&amp;lt;T>'>T</data-lsp>> = {</span>\n<span style=\"color: #000000\">  [<data-lsp lsp='(type parameter) K'>K</data-lsp> </span><span style=\"color: #0000FF\">in</span><span style=\"color: #000000\"> </span><span style=\"color: #1A1A1A\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type NonFunctionPropertyNames&amp;lt;T>'>T</data-lsp>]: <data-lsp lsp='(type parameter) T in type NonFunctionPropertyNames&amp;lt;T>'>T</data-lsp>[<data-lsp lsp='(type parameter) K'>K</data-lsp>] extends <data-lsp lsp='interface Function'>Function</data-lsp> ? never : <data-lsp lsp='(type parameter) K'>K</data-lsp>;</span>\n<span style=\"color: #000000\">}[</span><span style=\"color: #0000FF\">keyof</span><span style=\"color: #000000\"> <data-lsp lsp='(type parameter) T in type NonFunctionPropertyNames&amp;lt;T>'>T</data-lsp>];</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type NonFunctionProperties&amp;lt;T> = { [P in NonFunctionPropertyNames&amp;lt;T>]: T[P]; }'>NonFunctionProperties</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type NonFunctionProperties&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='type Pick&amp;lt;T, K extends keyof T> = { [P in K]: T[P]; }'>Pick</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type NonFunctionProperties&amp;lt;T>'>T</data-lsp>, <data-lsp lsp='type NonFunctionPropertyNames&amp;lt;T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'>NonFunctionPropertyNames</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type NonFunctionProperties&amp;lt;T>'>T</data-lsp>>>;</span>\n\n<span style=\"color: #0000FF\">interface</span><span style=\"color: #000000\"> <data-lsp lsp='interface Part'>Part</data-lsp> {</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Part.id: number'>id</data-lsp></span><span style=\"color: #000000\">: number;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Part.name: string'>name</data-lsp></span><span style=\"color: #000000\">: string;</span>\n<span style=\"color: #000000\">  </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) Part.subparts: Part[]'>subparts</data-lsp></span><span style=\"color: #000000\">: <data-lsp lsp='interface Part'>Part</data-lsp>[];</span>\n<span style=\"color: #000000\">  <data-lsp lsp='(method) Part.updatePart(newName: string): void'>updatePart</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) newName: string'>newName</data-lsp></span><span style=\"color: #000000\">: string): void;</span>\n<span style=\"color: #000000\">}</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = &amp;quot;updatePart&amp;quot;'>T1</data-lsp> = <data-lsp lsp='type FunctionPropertyNames&amp;lt;T> = { [K in keyof T]: T[K] extends Function ? K : never; }[keyof T]'>FunctionPropertyNames</data-lsp>&lt;<data-lsp lsp='interface Part'>Part</data-lsp>>;</span>\n<span class='query'>//   ^ = type T1 = \"updatePart\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = &amp;quot;id&amp;quot; | &amp;quot;name&amp;quot; | &amp;quot;subparts&amp;quot;'>T2</data-lsp> = <data-lsp lsp='type NonFunctionPropertyNames&amp;lt;T> = { [K in keyof T]: T[K] extends Function ? never : K; }[keyof T]'>NonFunctionPropertyNames</data-lsp>&lt;<data-lsp lsp='interface Part'>Part</data-lsp>>;</span>\n<span class='query'>//   ^ = type T2 = \"id\" | \"name\" | \"subparts\"</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T3 = {&amp;#13;    updatePart: (newName: string) => void;&amp;#13;}'>T3</data-lsp> = <data-lsp lsp='type FunctionProperties&amp;lt;T> = { [P in FunctionPropertyNames&amp;lt;T>]: T[P]; }'>FunctionProperties</data-lsp>&lt;<data-lsp lsp='interface Part'>Part</data-lsp>>;</span>\n<span class='query'>//   ^ = type T3 = {\n    updatePart: (newName: string) => void;\n}</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T4 = {&amp;#13;    id: number;&amp;#13;    name: string;&amp;#13;    subparts: Part[];&amp;#13;}'>T4</data-lsp> = <data-lsp lsp='type NonFunctionProperties&amp;lt;T> = { [P in NonFunctionPropertyNames&amp;lt;T>]: T[P]; }'>NonFunctionProperties</data-lsp>&lt;<data-lsp lsp='interface Part'>Part</data-lsp>>;</span>\n<span class='query'>//   ^ = type T4 = {\n    id: number;\n    name: string;\n    subparts: Part[];\n}</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYgrgOwMbAJYHsEAUBO7I6gByAhgLYQDOAPACoB8UAvFAN4BQUUA2gNJSoEUANYQQ6AGZRaAXQBc0vjKgQAHsAgIAJpViIUGIQH4o-BQggA3CDgDc7AL7dR4qbPuhIe5Gky58NmhUdIwsWKhIwnQANN4GfngExOTBDPT27J7QRJjwPob+SSCkFDQMzGycPPyCImKS0vKKvMpqGtq6efHGUBbWOFAKvPZOLg3umeDZufq+2ImBqKmhUOGRMVA5CF1zhYHFKWX06ezsgho4EiRI0FgkhJVcqFrmcGQARjb2XAgpCpTAHCCADm3yglDg7zA92AlAUd0I3BkYLgYC0JA0COAAAoLAB3EoQf6AkEASgUlnQzxGpyy0gAjBUdgUFoQDqVqFiTgB6blcKAAPSMky8tAATBUtsyEgE2YSaFz7Lz+UKRdBaABmJmzFmyoIKmE8vlcVV02gAFklM3yMqSSwNhCNKqMQA'>Try</a></div></pre>\n<p>Similar to union and intersection types, conditional types are not permitted to reference themselves recursively.\nFor example the following is an error.</p>\n<h4 id=\"example-2\" style=\"position:relative;\"><a href=\"#example-2\" aria-label=\"example 2 permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Example</h4>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"><data-err> <data-lsp lsp='type ElementType&amp;lt;T> = any'>ElementType</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type ElementType&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type ElementType&amp;lt;T>'>T</data-lsp> extends any[] ? <data-lsp lsp='type ElementType&amp;lt;T> = any'>ElementType</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type ElementType&amp;lt;T>'>T</data-lsp>[number]> : <data-lsp lsp='(type parameter) T in type ElementType&amp;lt;T>'>T</data-lsp>; </data-err></span><span style=\"color: #008000\">// Error</span>\n<span class=\"error\"><span>Type alias 'ElementType' circularly references itself.</br>Type 'ElementType' is not generic.</span><span class=\"code\">2456<br/>2315</span></span><span class=\"error-behind\">Type alias 'ElementType' circularly references itself.</br>Type 'ElementType' is not generic.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwBYCsA2dBmARiwCgAXATwAdJQBRAG0gFtIA7MgFWsgB5OAfKAC8oTqEgAPMuwAmiUAEM2FANoBdUAH56TVh241+qtgFdmAIxjqhqTgG5QIerARA'>Try</a></div></pre>\n<h2 id=\"type-inference-in-conditional-types\" style=\"position:relative;\"><a href=\"#type-inference-in-conditional-types\" aria-label=\"type inference in conditional types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Type inference in conditional types</h2>\n<p>Within the <code>extends</code> clause of a conditional type, it is now possible to have <code>infer</code> declarations that introduce a type variable to be inferred.\nSuch inferred type variables may be referenced in the true branch of the conditional type.\nIt is possible to have multiple <code>infer</code> locations for the same type variable.</p>\n<p>For example, the following extracts the return type of a function type:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type ReturnType&amp;lt;T> = T extends (...args: any[]) => infer R ? R : any'>ReturnType</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type ReturnType&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type ReturnType&amp;lt;T>'>T</data-lsp> extends (...</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) args: any[]'>args</data-lsp></span><span style=\"color: #000000\">: any[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> infer <data-lsp lsp='(type parameter) R'>R</data-lsp> ? <data-lsp lsp='(type parameter) R'>R</data-lsp> : any;</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEDsHsFECd7XgZwFABcCeAHApqAEp4YCu8kAKrngDyUB8oAvKJaHgB4Z6QAmKUAAoAdGICG8AOYoAXKHGQsAbQC6AShZMAlpABmeeEVAB+Y-MVYA3EA'>Try</a></div></pre>\n<p>Conditional types can be nested to form a sequence of pattern matches that are evaluated in order:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Unpacked&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type Unpacked&amp;lt;T>'>T</data-lsp> extends (infer <data-lsp lsp='(type parameter) U'>U</data-lsp>)[]</span>\n<span style=\"color: #000000\">  ? <data-lsp lsp='(type parameter) U'>U</data-lsp></span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type Unpacked&amp;lt;T>'>T</data-lsp> extends (...</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) args: any[]'>args</data-lsp></span><span style=\"color: #000000\">: any[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> infer <data-lsp lsp='(type parameter) U'>U</data-lsp></span>\n<span style=\"color: #000000\">  ? <data-lsp lsp='(type parameter) U'>U</data-lsp></span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type Unpacked&amp;lt;T>'>T</data-lsp> extends <data-lsp lsp='interface Promise&amp;lt;T>'>Promise</data-lsp>&lt;infer <data-lsp lsp='(type parameter) U'>U</data-lsp>></span>\n<span style=\"color: #000000\">  ? <data-lsp lsp='(type parameter) U'>U</data-lsp></span>\n<span style=\"color: #000000\">  : <data-lsp lsp='(type parameter) T in type Unpacked&amp;lt;T>'>T</data-lsp>;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T0 = string'>T0</data-lsp> = <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;string>;</span>\n<span class='query'>//   ^ = type T0 = string</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = string'>T1</data-lsp> = <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;string[]>;</span>\n<span class='query'>//   ^ = type T1 = string</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = string'>T2</data-lsp> = <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;() </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> string&gt;;</span>\n<span class='query'>//   ^ = type T2 = string</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T3 = string'>T3</data-lsp> = <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;<data-lsp lsp='interface Promise&amp;lt;T>'>Promise</data-lsp>&lt;string>>;</span>\n<span class='query'>//   ^ = type T3 = string</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T4 = Promise&amp;lt;string>'>T4</data-lsp> = <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;<data-lsp lsp='interface Promise&amp;lt;T>'>Promise</data-lsp>&lt;string>[]>;</span>\n<span class='query'>//   ^ = type T4 = Promise<string></span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T5 = string'>T5</data-lsp> = <data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;<data-lsp lsp='type Unpacked&amp;lt;T> = T extends (infer U)[] ? U : T extends (...args: any[]) => infer U ? U : T extends Promise&amp;lt;infer U> ? U : T'>Unpacked</data-lsp>&lt;<data-lsp lsp='interface Promise&amp;lt;T>'>Promise</data-lsp>&lt;string>[]>>;</span>\n<span class='query'>//   ^ = type T5 = string</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAqgdmAhgYwNYQCYB4AqA+KAXihyggA9gI4MBnKACgEs4AzCAJ1gEoBtAXQBQUKAH5YwqAC4SZStTqMAdCsQcA5rRmI4IAdyIEW7LjEnizImaQpUa9AAocA9gFsmtCFmOdYecxJWJADcgoKgkCQADESwCCjo2LTAHCzqeKEA9JkiUAB6ouHg0DgAjLHwSGiYWMmpcOoCGYLZuQVFkTgATBXx1dgMBoQEdWnNrSLtESUAzL1ViVhObh5eow144zmThdMkACzzCTXL7p61KWNNWdv5u8UkAKxH-ViVx9inqxf16U1bbVEQA'>Try</a></div></pre>\n<p>The following example demonstrates how multiple candidates for the same type variable in co-variant positions causes a union type to be inferred:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Foo&amp;lt;T> = T extends {&amp;#13;    a: infer U;&amp;#13;    b: infer U;&amp;#13;} ? U : never'>Foo</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Foo&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type Foo&amp;lt;T>'>T</data-lsp> extends { </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) a: U'>a</data-lsp></span><span style=\"color: #000000\">: infer <data-lsp lsp='(type parameter) U'>U</data-lsp>; </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) b: U'>b</data-lsp></span><span style=\"color: #000000\">: infer <data-lsp lsp='(type parameter) U'>U</data-lsp> } ? <data-lsp lsp='(type parameter) U'>U</data-lsp> : never;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = string'>T1</data-lsp> = <data-lsp lsp='type Foo&amp;lt;T> = T extends {&amp;#13;    a: infer U;&amp;#13;    b: infer U;&amp;#13;} ? U : never'>Foo</data-lsp>&lt;{ </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) a: string'>a</data-lsp></span><span style=\"color: #000000\">: string; </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) b: string'>b</data-lsp></span><span style=\"color: #000000\">: string }&gt;;</span>\n<span class='query'>//   ^ = type T1 = string</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = string | number'>T2</data-lsp> = <data-lsp lsp='type Foo&amp;lt;T> = T extends {&amp;#13;    a: infer U;&amp;#13;    b: infer U;&amp;#13;} ? U : never'>Foo</data-lsp>&lt;{ </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) a: string'>a</data-lsp></span><span style=\"color: #000000\">: string; </span><span style=\"color: #1A1A1A\"><data-lsp lsp='(property) b: number'>b</data-lsp></span><span style=\"color: #000000\">: number }&gt;;</span>\n<span class='query'>//   ^ = type T2 = string | number</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAYg9nAPAFQHxQLxWVCAPYCAOwBMBnKAbygEMAuKASyIDMIAnKAVQG4oAjBszacuUAL5QA-NygMiEAG4ceAKFWhI2AIyZYCRNXpQywdswDmfQSbOWJqNQHonUNwD0pG8NGQAmPXgkIwZTcyIrAXkAVwBbfg4HZ1cPKSA'>Try</a></div></pre>\n<p>Likewise, multiple candidates for the same type variable in contra-variant positions causes an intersection type to be inferred:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type Bar&amp;lt;T> = T extends {&amp;#13;    a: (x: infer U) => void;&amp;#13;    b: (x: infer U) => void;&amp;#13;} ? U : never'>Bar</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type Bar&amp;lt;T>'>T</data-lsp>> = <data-lsp lsp='(type parameter) T in type Bar&amp;lt;T>'>T</data-lsp> extends { <data-lsp lsp='(property) a: (x: infer U) => void'>a</data-lsp>: (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: U'>x</data-lsp></span><span style=\"color: #000000\">: infer <data-lsp lsp='(type parameter) U'>U</data-lsp>) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void; <data-lsp lsp='(property) b: (x: infer U) => void'>b</data-lsp>: (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: U'>x</data-lsp></span><span style=\"color: #000000\">: infer <data-lsp lsp='(type parameter) U'>U</data-lsp>) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void }</span>\n<span style=\"color: #000000\">  ? <data-lsp lsp='(type parameter) U'>U</data-lsp></span>\n<span style=\"color: #000000\">  : never;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = string'>T1</data-lsp> = <data-lsp lsp='type Bar&amp;lt;T> = T extends {&amp;#13;    a: (x: infer U) => void;&amp;#13;    b: (x: infer U) => void;&amp;#13;} ? U : never'>Bar</data-lsp>&lt;{ <data-lsp lsp='(property) a: (x: string) => void'>a</data-lsp>: (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: string'>x</data-lsp></span><span style=\"color: #000000\">: string) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void; <data-lsp lsp='(property) b: (x: string) => void'>b</data-lsp>: (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: string'>x</data-lsp></span><span style=\"color: #000000\">: string) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void }&gt;;</span>\n<span class='query'>//   ^ = type T1 = string</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T2 = never'>T2</data-lsp> = <data-lsp lsp='type Bar&amp;lt;T> = T extends {&amp;#13;    a: (x: infer U) => void;&amp;#13;    b: (x: infer U) => void;&amp;#13;} ? U : never'>Bar</data-lsp>&lt;{ <data-lsp lsp='(property) a: (x: string) => void'>a</data-lsp>: (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: string'>x</data-lsp></span><span style=\"color: #000000\">: string) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void; <data-lsp lsp='(property) b: (x: number) => void'>b</data-lsp>: (</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: number'>x</data-lsp></span><span style=\"color: #000000\">: number) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> void }&gt;;</span>\n<span class='query'>//   ^ = type T2 = never</span></code><a href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAQghgJwDwBUB8UC8UVQgD2AgDsATAZygG8o4AuKACnwYEtiAzCBKAVQEosGAG4B7VqQDcUAEYNmbTtz6DMI8aSgBfAFBQoAfj56oDYhGHdJOnaEg4AjFliIkNekxZRywBOwDmquoS0nKeDD5+xIFCUGIS2mjWAPTJ+lAAega24NAoAEzO8Mju8l6RAUFxGqFlZgCuALYy3FXxmlpJOqnpWUA'>Try</a></div></pre>\n<p>When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the <em>last</em> signature (which, presumably, is the most permissive catch-all case).\nIt is not possible to perform overload resolution based on a list of argument types.</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function foo(x: string): number (+2 overloads)'>foo</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: string'>x</data-lsp></span><span style=\"color: #000000\">: string): number;</span>\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function foo(x: number): string (+2 overloads)'>foo</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: number'>x</data-lsp></span><span style=\"color: #000000\">: number): string;</span>\n<span style=\"color: #0000FF\">declare</span><span style=\"color: #000000\"> </span><span style=\"color: #0000FF\">function</span><span style=\"color: #000000\"> <data-lsp lsp='function foo(x: string | number): string | number (+2 overloads)'>foo</data-lsp>(</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) x: string | number'>x</data-lsp></span><span style=\"color: #000000\">: string | number): string | number;</span>\n\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type T1 = string | number'>T1</data-lsp> = <data-lsp lsp='type ReturnType&amp;lt;T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any'>ReturnType</data-lsp>&lt;</span><span style=\"color: #0000FF\">typeof</span><span style=\"color: #000000\"> <data-lsp lsp='function foo(x: string): number (+2 overloads)'>foo</data-lsp>>;</span>\n<span class='query'>//   ^ = type T1 = string | number</span></code><a href='https://www.typescriptlang.org/play/#code/CYUwxgNghgTiAEAzArgOzAFwJYHtVJxwAoAPALngGcMYtUBzASgtWQFsAjEGAbgChQkWAhTpseAsXLxWnbsyo069foOhwkaTLnyJCpCtVoN4AHxnsuMBUeVmLc3nz4YAngAcEAFQCM8ALzwAEogGMgwqF4eIAA8bp44iJIAfPwA9GnwWQB6APxAA'>Try</a></div></pre>\n<p>It is not possible to use <code>infer</code> declarations in constraint clauses for regular type parameters:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type ReturnedType&amp;lt;T extends (...args: any[]) => infer R> = any'>ReturnedType</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type ReturnedType&amp;lt;T extends (...args: any[]) => infer R>'>T</data-lsp> </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> (...</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) args: any[]'>args</data-lsp></span><span style=\"color: #000000\">: any[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"><data-err> infer <data-lsp lsp='(type parameter) R'>R</data-lsp>> = <data-lsp lsp='any'>R</data-lsp>;</data-err></span>\n<span class=\"error\"><span>'infer' declarations are only permitted in the 'extends' clause of a conditional type.</br>Cannot find name 'R'.</span><span class=\"code\">1338<br/>2304</span></span><span class=\"error-behind\">'infer' declarations are only permitted in the 'extends' clause of a conditional type.</br>Cannot find name 'R'.</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygIwGYMA5QCYMAGAFgCgAXATwAdJQAlScgV2gDtIATAFRsgB5uoSAA9ykNp0SgAFADoFAQ2gBzFKEVtKAbQC6ASlABeAHygAlmwBmMBmaMMA3EA'>Try</a></div></pre>\n<p>However, much the same effect can be obtained by erasing the type variables in the constraint and instead specifying a conditional type:</p>\n<pre class=\"shiki twoslash\"><div class=\"language-id\">ts</div><div class='code-container'><code><span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type AnyFunction = (...args: any[]) => any'>AnyFunction</data-lsp> = (...</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) args: any[]'>args</data-lsp></span><span style=\"color: #000000\">: any[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> any;</span>\n<span style=\"color: #0000FF\">type</span><span style=\"color: #000000\"> <data-lsp lsp='type ReturnType&amp;lt;T extends AnyFunction> = T extends (...args: any[]) => infer R ? R : any'>ReturnType</data-lsp>&lt;<data-lsp lsp='(type parameter) T in type ReturnType&amp;lt;T extends AnyFunction>'>T</data-lsp> </span><span style=\"color: #0000FF\">extends</span><span style=\"color: #000000\"> <data-lsp lsp='type AnyFunction = (...args: any[]) => any'>AnyFunction</data-lsp>> = <data-lsp lsp='(type parameter) T in type ReturnType&amp;lt;T extends AnyFunction>'>T</data-lsp> extends (...</span><span style=\"color: #1A1A1A\"><data-lsp lsp='(parameter) args: any[]'>args</data-lsp></span><span style=\"color: #000000\">: any[]) </span><span style=\"color: #0000FF\">=&gt;</span><span style=\"color: #000000\"> infer <data-lsp lsp='(type parameter) R'>R</data-lsp></span>\n<span style=\"color: #000000\">  ? <data-lsp lsp='(type parameter) R'>R</data-lsp></span>\n<span style=\"color: #000000\">  : any;</span></code><a href='https://www.typescriptlang.org/play/#code/PTAEAEDsHsFECd7XgZwFABcCeAHApqAIKRYBiArpAMYYCW0koAvKABQB0nAhvAOYoAuUFxIBtALoBKZgD5hJANyZcBAEp4M5eJAAqKgDw7QeAB4Y8kACYoiJCtToM5LI6fNWbHbn0HysE6SY5WkgAMzx4UFU0UFAAfiiY0CERLAUgA'>Try</a></div></pre>\n<h2 id=\"predefined-conditional-types\" style=\"position:relative;\"><a href=\"#predefined-conditional-types\" aria-label=\"predefined conditional types permalink\" class=\"anchor before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>Predefined conditional types</h2>\n<p>TypeScript adds several predefined conditional types, you can find the full list and examples in <a href=\"/docs/handbook/utility-types.html\">Utility Types</a>.</p>","headings":[{"value":"Type Guards and Differentiating Types","depth":2},{"value":"User-Defined Type Guards","depth":2},{"value":"Using type predicates","depth":4},{"value":"Using the in operator","depth":3},{"value":"typeof type guards","depth":2},{"value":"instanceof type guards","depth":2},{"value":"Nullable types","depth":2},{"value":"Optional parameters and properties","depth":3},{"value":"Type guards and type assertions","depth":3},{"value":"Type Aliases","depth":2},{"value":"Interfaces vs. Type Aliases","depth":2},{"value":"Enum Member Types","depth":2},{"value":"Polymorphic this types","depth":2},{"value":"Index types","depth":2},{"value":"Index types and index signatures","depth":2},{"value":"Mapped types","depth":2},{"value":"Inference from mapped types","depth":2},{"value":"Conditional Types","depth":2},{"value":"Distributive conditional types","depth":2},{"value":"Example","depth":4},{"value":"Example","depth":4},{"value":"Example","depth":4},{"value":"Type inference in conditional types","depth":2},{"value":"Predefined conditional types","depth":2}],"frontmatter":{"permalink":"/docs/handbook/advanced-types.html","title":"Advanced Types","disable_toc":null,"oneline":"Advanced concepts around types in TypeScript"}},"prev":null,"next":null},"pageContext":{"id":"advanced-types","slug":"/docs/handbook/advanced-types.html","repoPath":"/packages/documentation/copy/en/reference/Advanced Types.md","lang":"en","modifiedTime":"2020-08-07T17:00:36.339Z"}}}