CINXE.COM
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta http-equiv="x-ua-compatible" content="ie=edge"/><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/><meta name="generator" content="Gatsby 5.13.5"/><meta name="theme-color" content="#3178C6"/><meta data-react-helmet="true" name="description" content="TypeScript 4.1 Release Notes"/><meta data-react-helmet="true" property="og:title" content="Documentation - TypeScript 4.1"/><meta data-react-helmet="true" property="og:description" content="TypeScript 4.1 Release Notes"/><meta data-react-helmet="true" property="twitter:site" content="typescriptlang"/><style data-href="/styles.831f686bbe71549836a7.css" data-identity="gatsby-global-css">#top-menu{background-color:#3178c6;clear:both;display:flex;height:3rem;justify-content:space-between;-webkit-user-select:none;user-select:none;z-index:101}#top-menu>.left{display:flex;flex-direction:row;padding-bottom:env(safe-area-inset-bottom)}#top-menu>.right{display:flex;flex-direction:row-reverse;justify-self:flex-end}#top-menu .nav{display:inline-block;text-decoration:none}#top-menu ul{margin:0;padding:0}#top-menu #home-page-logo{font-size:1.5rem;font-weight:600;padding-top:.7rem;width:200px}@media screen and (-ms-high-contrast:active){#top-menu #home-page-logo svg path{fill:blue}}#top-menu #home-page-logo svg{margin-left:1rem;margin-right:.6rem}#top-menu #home-page-logo span{margin-right:.2rem;position:relative;text-decoration:none;top:-.3rem}#top-menu .nav-item{display:inline-block;font-size:1rem;font-weight:600;text-decoration:none}#top-menu .nav-item a{display:block;padding:.95rem .5em .7em}#top-menu .nav-item a:hover{opacity:.8}#top-menu .nav-item a.active,#top-menu .nav-item a:focus{text-decoration:underline}#top-menu a{color:#fff;text-decoration:none}#beta-notification-menu,.gatsby-noscript{background-color:#c63131;color:#fff;padding:.4rem 0;text-align:center;-webkit-user-select:none;user-select:none}#beta-notification-menu a,.gatsby-noscript a{color:#fff}form.search{background-color:#235a97;border-radius:3px 0 0 3px;display:inline-block;height:3rem;padding-left:1rem}form.search svg{margin-right:.3rem;position:relative;top:.1rem}@media screen and (-ms-high-contrast:black-on-white){form.search svg path{fill:#000}}form.search:focus-within{background-color:#358ef1}@media screen and (-ms-high-contrast:black-on-white){form.search:focus-within{border:2px solid #fff}}@media screen and (-ms-high-contrast:white-on-black){form.search:focus-within{border:2px solid #000}}form.search input{-webkit-appearance:none;background-color:#235a97;border:none;border-radius:0;color:#fff;font-size:1rem;font-weight:600;height:3rem;vertical-align:initial!important;width:150px}form.search input:focus-within{background-color:#358ef1}form.search input::placeholder{color:#fff}#like-dislike-subnav,.page-popup{transition:opacity .2s linear}.page-popup{background:#222;border-radius:5px;border-radius:4px;bottom:20px;box-shadow:0 1.6px 3.6px 0 rgba(0,0,0,.432),0 .3px .9px 0 rgba(0,0,0,.408);color:#fff;position:fixed;right:20px;z-index:2}.page-popup p{font-size:14px;padding:0 10px}.page-popup div{display:flex}.page-popup div button{background-color:#235a97;border:none;border-radius:0;color:#fff;flex:1 1;flex-grow:1}.page-popup div button.focus,.page-popup div button:hover{background-color:#104261}.page-popup div button.first{border-right:1px solid #fff}.page-popup svg{fill:#fff}#top-menu nav ul .show-only-medium{display:none}#top-menu nav ul .hide-only-medium{display:inline}#top-menu nav ul .show-only-largest,#top-menu nav ul .show-only-small{display:none}@media(max-width:800px){#top-menu nav ul .show-only-small{display:block!important}#top-menu nav ul .show-small{display:inline!important}#top-menu nav ul .hide-only-medium{display:none}#top-menu nav ul .show-only-large{display:none!important}}@media(min-width:767px)and (max-width:900px){#top-menu nav ul .show-only-medium{display:inline!important}#top-menu nav ul .hide-only-medium{display:none!important}}@media(min-width:900px){#top-menu nav ul .show-only-large{display:inline-block!important}}@media(min-width:1050px){#top-menu nav ul .show-only-largest{display:inline-block!important}}@media(max-width:790px){#site-wrapper{margin-bottom:-1px}#my-lang-quick-jump,.hide-small{display:none!important}#top-menu{bottom:0;display:flex;flex-direction:column-reverse;height:auto;left:0;position:fixed;right:0}#top-menu .nav-item{display:block}#top-menu.up{transform:translate(0);transition-timing-function:ease;transition:transform .3s}#top-menu.down{transform:translateY(8.2rem);transition-timing-function:ease;transition:transform .6s}}@media(max-width:790px)and (prefers-reduced-motion:reduce){#top-menu.down,#top-menu.up{transition:none}}@media(max-width:790px){#top-menu #home-page-logo{width:auto}#top-menu .below-small nav{flex-grow:1}#top-menu .below-small nav ul{display:flex}#top-menu .below-small nav ul li{flex:1 1;text-align:center}.above-small .search-section{width:100%}.above-small form.search{display:flex;width:calc(100% - 1rem)}.above-small form.search svg{position:relative;top:1rem}.above-small form.search input{width:200%}#top-menu .ds-dropdown-menu{bottom:140%;left:0!important;margin-left:-34px;min-width:0;right:-180px!important;top:auto!important}#top-menu .ds-dropdown-menu:before{bottom:-7px;left:40px;top:auto;transform:rotate(135deg)}}.skip-to-main{clip:rect(1px,1px,1px,1px);height:1px;overflow:hidden;position:absolute;white-space:nowrap;width:1px}.skip-to-main:focus{clip:auto;background-color:#faf9f8;border:1px dashed #000;color:#000;height:auto;overflow:auto;padding:20px;position:absolute;text-align:center;width:100%;z-index:999999}#small-device-button-sidebar{display:none}nav#sidebar{background-color:var(--sidebar-background-color);color:var(--alt-text-color);min-width:16rem}nav#sidebar ul{margin:0;padding:0;position:sticky;top:0}nav#sidebar ul li{border-bottom:1px solid var(--sidebar-item-border-color);font-size:1rem;font-weight:400;list-style:none;min-height:2.5rem;padding:0}nav#sidebar ul li button{-webkit-appearance:none;background-color:transparent;border:none;color:var(--alt-text-color);cursor:pointer;display:block;font-size:1rem;font-weight:500;height:2.5rem;padding-left:1rem;position:relative;text-align:left;width:100%}nav#sidebar ul li button .closed path,nav#sidebar ul li button .open path{stroke:var(--text-color)}nav#sidebar ul li button:active,nav#sidebar ul li button:focus{background-color:var(--sidebar-active-button-background-color);color:var(--alt-text-color)}nav#sidebar ul li button span{position:absolute;right:20px}nav#sidebar ul li ul ul{margin-left:.2rem}nav#sidebar ul li.highlighted{background-color:var(--sidebar-list-active-background-color)}nav#sidebar ul li.highlighted svg path{stroke:#3178c6}nav#sidebar ul li.closed span.open,nav#sidebar ul li.closed ul,nav#sidebar ul li.open>button>span.closed{display:none}nav#sidebar ul li.open>ul{background-color:var(--sidebar-list-background-color)}nav#sidebar ul li.open.highlighted ul{background-color:var(--sidebar-list-active-background-color)}nav#sidebar ul li ul{margin:0;padding:0}nav#sidebar ul li ul a{color:var(--alt-text-color);display:block;flex-grow:1;padding-bottom:.5rem;padding-left:1rem;padding-top:.5rem;text-decoration:none}nav#sidebar ul li ul li{list-style:none}nav#sidebar ul li ul li a{font-weight:300;margin-right:-.5rem}nav#sidebar ul li ul li:hover{margin-right:-.3rem;padding-left:.3rem;transition:padding-left .1s ease-out}@media(prefers-reduced-motion:reduce){nav#sidebar ul li ul li:hover{transition:none}}nav#sidebar ul li ul li a:focus,nav#sidebar ul li ul li a:hover{border-left:2px solid var(--sidebar-link-border-color)}nav#sidebar ul li ul li.highlight a{border-left:2px solid #3178c6;color:#2866a9;font-weight:500;margin-left:.5rem;margin-right:-.5rem}@media(min-width:800px){nav#sidebar>ul{max-height:calc(100vh - 10px);overflow-x:hidden;overflow-y:auto}}@media(max-width:800px){button#small-device-button-sidebar{-webkit-appearance:none;background-color:#c4c4c4;border:none;border-radius:6px;bottom:120px;display:flex;left:20px;margin-bottom:env(safe-area-inset-bottom);padding:10px;position:fixed;transition-timing-function:ease;transition:left .3s;z-index:100}}@media(max-width:800px)and (prefers-reduced-motion:reduce){button#small-device-button-sidebar{transition:none}}@media(max-width:800px){button#small-device-button-sidebar.hidden{left:-80px}button#small-device-button-sidebar:active{background-color:#575757}nav#sidebar{-webkit-overflow-scrolling:touch;height:100%;margin-left:-800px;overflow-x:hidden;overflow-y:scroll;position:fixed;transition-timing-function:ease;transition:margin-left .3s;width:90%;z-index:99}nav#sidebar ul{padding-bottom:200px}}@media(max-width:800px)and (prefers-reduced-motion:reduce){nav#sidebar{transition:none}}@media(max-width:800px){nav#sidebar.show{margin-left:0}nav#sidebar>ul>li,nav#sidebar>ul>li>button{font-size:1.3rem}}#site-footer{background-color:#3178c6;color:#fff;padding-bottom:3rem;padding-top:1rem}@media(max-width:800px){#site-footer{padding-bottom:9rem}}#site-footer a{color:#fff}#site-footer section{margin:0 auto;max-width:1040px;padding-left:.5rem;padding-right:.5rem;padding-top:1rem}#site-footer h3{font-size:20px;font-style:normal;font-weight:600;margin-top:1px}#site-footer ul{display:flex;flex-wrap:wrap;padding:0}#site-footer ul li{font-weight:600;list-style:none;width:13rem}#site-footer ul li a{font-size:16px}#site-footer ul li p{font-size:14px;margin-top:2px;width:74%}#site-footer ul li span.link-prefix{left:-30px;position:absolute;text-align:right;width:26px}@media(max-width:800px){#site-footer ul li{margin-left:10px}#site-footer ul li p{width:100%}}#site-footer section#customize{border-bottom:1px solid hsla(0,0%,100%,.3);padding-top:2px}#site-footer section#customize article{display:flex;flex-direction:row}#site-footer section#customize article h3{width:240px}@media(max-width:800px){#site-footer section#customize article{flex-direction:column;margin-bottom:1rem}#site-footer section#customize article label{margin-left:8px}}#site-footer section#customize article label{display:flex;flex-direction:row}#site-footer section#customize article label p{margin:6px 8px 0 0;padding:0}#site-footer section#customize .switch-wrap{display:inline-block;height:20px;margin-right:1rem;padding:5px}#site-footer section#customize .switch-wrap select{background-color:#00273f;color:#fff}#site-footer section#community{border-top:1px solid hsla(0,0%,100%,.3);display:flex;padding-top:2rem}@media(max-width:800px){#site-footer section#community{flex-direction:column-reverse}#site-footer section#community article#logos{margin:3rem auto 0;text-align:center}}#site-footer section#community article>ul{display:flex;flex-wrap:wrap}#site-footer section#community article>ul>li{margin-bottom:.8rem;word-break:break-all}@media(min-width:800px){#site-footer section#community article>ul>li{width:50%}}#site-footer section#community #logos{margin-right:40px;width:200px}#site-footer section#community #logos svg{margin-bottom:-.8rem}@media screen and (-ms-high-contrast:black-on-white){#site-footer section#community #logos img{filter:invert(100%)}#site-footer section#community #logos svg path{fill:#000}}#site-footer section#community #logos svg.typescript-long{margin-left:8px;position:relative;top:2px}#site-footer section#community #logos img#microsoft-logo{margin-bottom:-.8rem;margin-top:1rem}#site-footer section#community #community-links,#site-footer section#community #using-typescript{flex:1 1}@media(max-width:800px){#playground-samples-popover{display:none}#community-links ul,#using-typescript ul{margin-left:12px}}.popover-container{position:relative}.popover-container .examples{overflow-y:auto}.popover-container .examples>div.section-content .section-list{width:300px}.popover-container.allow-hover #playground-samples-popover{bottom:-10px;opacity:0}.popover-container.allow-hover:hover #playground-samples-popover{bottom:-5px;opacity:1;visibility:visible}.popover-container.allow-hover:hover .footer-icon:after{content:"▼"}.popover-container .footer-icon:after{content:"⊙"}#playground-samples-popover{bottom:0;color:#000;left:-252px;margin:0 auto;opacity:1;position:absolute;right:-320px;transition:bottom .3s ease,opacity .2s linear,visibility 0s linear;visibility:hidden;z-index:123}#playground-samples-popover .section-content{display:flex}#playground-samples-popover .section-content .section-list li{margin-top:4px}#playground-samples-popover .section-content .example-indicator{margin-top:0}#playground-samples-popover .arrow-down{border-left:10px solid transparent;border-right:10px solid transparent;border-top:14px solid var(--footer-arrow-color);height:0;margin:0 auto 20px;position:relative;right:179px;width:0}#playground-samples-popover .navbar-sub{border-bottom:1px solid #235a97;border-radius:0}#playground-samples-popover .navbar-sub div.info{color:#000;padding:20px;width:320px}#playground-samples-popover a{color:#3178c6;text-decoration:none}@font-face{font-display:swap;font-family:Cascadia Mono-SemiLight;font-style:normal;font-weight:400;src:url(/fonts/CascadiaMono-SemiLight.woff2) format("woff2")}@font-face{font-display:swap;font-family:Cascadia Code-SemiLight;font-style:normal;font-weight:400;src:url(/fonts/CascadiaCode-SemiLight.woff2) format("woff2")}@font-face{font-display:swap;font-family:JetBrains Mono-Regular;font-style:normal;font-weight:400;src:url(/fonts/JetBrainsMono-Regular.woff2) format("woff2")}@font-face{font-display:swap;font-family:FiraCode-Regular;font-style:normal;font-weight:400;src:url(/fonts/FiraCode-Regular.woff2) format("woff2")}@font-face{font-display:swap;font-family:Dank Mono Regular;font-style:normal;font-weight:400;src:url(/fonts/DankMono-Regular.woff2) format("woff2")}@font-face{font-display:swap;font-family:SourceCode Pro Regular;font-style:normal;font-weight:400;src:url(/fonts/SourceCodePro-Regular.woff2) format("woff2")}@font-face{font-display:swap;font-family:OpenDyslexicMono Regular;font-style:normal;font-weight:400;src:url(/fonts/OpenDyslexicMono-Regular.woff) format("woff")}@font-face{font-display:swap;font-family:OpenDyslexic Regular;font-style:normal;font-weight:400;src:url(/fonts/OpenDyslexic-Regular.woff) format("woff")}@font-face{font-display:swap;font-family:Leelawadee UI Web;font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:Leelawadee UI Web;font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:Leelawadee UI Web;font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:Leelawadee UI Web;font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:Leelawadee UI Web;font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/leelawadeeui-thai/leelawadeeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Arabic)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Arabic)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Arabic)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Arabic)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Arabic)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-arabic/segoeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Cyrillic)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Cyrillic)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Cyrillic)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Cyrillic)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Cyrillic)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-cyrillic/segoeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (East European)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (East European)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (East European)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (East European)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (East European)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-easteuropean/segoeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Greek)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Greek)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Greek)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Greek)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Greek)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-greek/segoeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Hebrew)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Hebrew)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Hebrew)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Hebrew)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Hebrew)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-hebrew/segoeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Vietnamese)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Vietnamese)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Vietnamese)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Vietnamese)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (Vietnamese)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-vietnamese/segoeui-bold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (West European)";font-style:normal;font-weight:100;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-light.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-light.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (West European)";font-style:normal;font-weight:300;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-semilight.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-semilight.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (West European)";font-style:normal;font-weight:400;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-regular.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-regular.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (West European)";font-style:normal;font-weight:600;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-semibold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-semibold.woff) format("woff")}@font-face{font-display:swap;font-family:"Segoe UI Web (West European)";font-style:normal;font-weight:700;src:url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-bold.woff2) format("woff2"),url(https://res-1.cdn.office.net/files/fabric-cdn-prod_20230815.002/assets/fonts/segoeui-westeuropean/segoeui-bold.woff) format("woff")}body{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}body button,body input,body textarea{font-family:inherit}[lang^=ar] body,body [lang^=ar],body[lang^=ar]{font-family:"Segoe UI Web (Arabic)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=bg] body,body [lang^=bg],body[lang^=bg]{font-family:"Segoe UI Web (Cyrillic)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=cs] body,body [lang^=cs],body[lang^=cs]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=el] body,body [lang^=el],body[lang^=el]{font-family:"Segoe UI Web (Greek)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=et] body,body [lang^=et],body[lang^=et]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=he] body,body [lang^=he],body[lang^=he]{font-family:"Segoe UI Web (Hebrew)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=hi] body,body [lang^=hi],body[lang^=hi]{font-family:Nirmala UI,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=hr] body,[lang^=hu] body,body [lang^=hr],body [lang^=hu],body[lang^=hr],body[lang^=hu]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=ja] body,body [lang^=ja],body[lang^=ja]{font-family:Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,Meiryo,Hiragino Sans,Source Han Sans,Noto Sans CJK JP,sans-serif}[lang^=kk] body,body [lang^=kk],body[lang^=kk]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=ko] body,body [lang^=ko],body[lang^=ko]{font-family:Malgun Gothic,Gulim,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=lo] body,body [lang^=lo],body[lang^=lo]{font-family:Leelawadee UI Web,Lao UI,DokChampa,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=lt] body,[lang^=lv] body,[lang^=pl] body,body [lang^=lt],body [lang^=lv],body [lang^=pl],body[lang^=lt],body[lang^=lv],body[lang^=pl]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=ru] body,body [lang^=ru],body[lang^=ru]{font-family:"Segoe UI Web (Cyrillic)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=sk] body,[lang^=sr-latn] body,body [lang^=sk],body [lang^=sr-latn],body[lang^=sk],body[lang^=sr-latn]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=th] body,body [lang^=th],body[lang^=th]{font-family:Leelawadee UI Web,Kmer UI,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=tr] body,body [lang^=tr],body[lang^=tr]{font-family:"Segoe UI Web (East European)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=uk] body,body [lang^=uk],body[lang^=uk]{font-family:"Segoe UI Web (Cyrillic)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=vi] body,body [lang^=vi],body[lang^=vi]{font-family:"Segoe UI Web (Vietnamese)",Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=zh-hans] body,body [lang^=zh-hans],body[lang^=zh-hans]{font-family:Microsoft Yahei UI,Verdana,Simsun,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}[lang^=zh-hant] body,body [lang^=zh-hant],body[lang^=zh-hant]{font-family:Microsoft Jhenghei UI,Pmingliu,Segoe UI,-apple-system,BlinkMacSystemFont,Roboto,Helvetica Neue,sans-serif}.dark-theme{--background-color:#262626;--text-color:#fff;--border-color:#444;--background-minor-highlight-color:#343434;--inline-code-background-color:rgba(58,58,92,.7);--link-color:#719af4;--pure-background:#000;--raised-background-color:#313131;--alt-text-color:#fff;--raised-box-shadow:0 1.6px 3.6px 0 hsla(0,0%,100%,.132),0 0.3px 0.9px 0 hsla(0,0%,100%,.108);--sidebar-background-color:#2a2a2b;--sidebar-list-active-background-color:#28323a;--sidebar-list-background-color:#353434;--sidebar-link-border-color:#fff;--sidebar-item-border-color:#3e3e3e;--sidebar-active-button-background-color:#4e4e4f;--playground-divider:#f2f2f2;--playground-dropdown-bg:#313131;--playground-dropdown-shadow:0 6px 12px hsla(0,0%,58%,.175);--playground-dropdown-border:#000;--playground-toolbar-hover-bg:#262626;--playground-dragbar-bg:#28323a;--playground-dragbar-border:#fff;--playground-pre-color:#fff;--table-border-color:#545454;--playground-pre-bg:#1e1e1e;--blue-tinged-bg:#2c3841;--blue-tinged-strong:#273f52;--footer-arrow-color:$ts-light-bg-grey-highlight-color;--fade-gradient:linear-gradient(0deg,#313131,rgba(49,49,49,.2))}html,html.light-theme{--background-color:#faf9f8;--pure-background:#fff;--text-color:#333;--border-color:#eee;--background-minor-highlight-color:#fcfcfc;--inline-code-background-color:#f1f1fe;--link-color:#235a97;--raised-background-color:#fff;--alt-text-color:#000;--raised-box-shadow:0 1.6px 3.6px 0 rgba(0,0,0,.132),0 0.3px 0.9px 0 rgba(0,0,0,.108);--sidebar-background-color:#eee;--sidebar-list-active-background-color:#e3e8ec;--sidebar-list-background-color:#e4e4e4;--sidebar-link-border-color:#000;--sidebar-item-border-color:#dfdfdf;--sidebar-active-button-background-color:#dfdfdf;--playground-divider:#4e4e4f;--playground-dropdown-bg:#fff;--playground-dropdown-shadow:0 6px 12px rgba(0,0,0,.175);--playground-dropdown-border:#f2f2f2;--playground-toolbar-hover-bg:#f2f2f2;--playground-dragbar-bg:#fff;--playground-dragbar-border:#c4c4c4;--playground-pre-color:#000;--playground-pre-bg:#f7f7f7;--footer-arrow-color:$ts-dark-bg-for-foreground-color;--table-border-color:#f1f1f1;--blue-tinged-bg:#e6f2fb;--blue-tinged-strong:#cce4f6;--fade-gradient:linear-gradient(0deg,#fff,hsla(0,0%,100%,.2));-webkit-font-smoothing:antialiased;background-color:var(--background-color);color:var(--text-color);font-family:var(--body-font);font-size:16px;line-height:1.4}html{--code-font:"Cascadia Mono-SemiLight",Menlo,Monaco,Consolas,monospace;--body-font:"Segoe UI Web (West European)","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif}html.font-cascadia-ligatures{--code-font:"Cascadia Code-SemiLight",Menlo,Monaco,Consolas,monospace}html.font-consolas{--code-font:Consolas,monospace}html.font-dank-mono{--code-font:"Dank Mono Regular",Menlo,Monaco,Consolas,monospace}html.font-jetbrains-mono{--code-font:"JetBrains Mono-Regular",Menlo,Monaco,Consolas,monospace}html.font-fira-code{--code-font:"FiraCode-Regular",Menlo,Monaco,Consolas,monospace}html.font-sf-mono{--code-font:"SF Mono",Menlo,Monaco,Consolas,monospace}html.font-source-code-pro{--code-font:"SourceCode Pro Regular",Menlo,Monaco,Consolas,monospace}html.font-open-dyslexic{--code-font:"OpenDyslexicMono Regular",Menlo,Monaco,Consolas,monospace;--body-font:"OpenDyslexic Regular","Segoe UI Web (West European)","Segoe UI",-apple-system,BlinkMacSystemFont,Roboto,"Helvetica Neue",sans-serif}.raised{background-color:var(--raised-background-color);box-shadow:var(--raised-box-shadow);color:var(--alt-text-color)}.raised a{color:var(--link-color)}.raised h1,.raised h2,.raised h3{line-height:normal;margin-bottom:1.5rem;margin-top:2rem}.raised li,.raised p{line-height:1.4rem}.raised ul{padding-left:10px}.raised ul li{margin-bottom:10px;margin-left:10px}.raised h1>code,.raised h2>code,.raised h3>code{background-color:var(--inline-code-background-color);font-size:.95em;margin-left:.2em;margin-right:.2em;padding:2px 4px}.raised li>code,.raised p>code{background-color:var(--inline-code-background-color);font-family:var(--code-font);font-size:.9rem;padding:2px 4px}.raised td{padding:4px}.dark-theme .raised .markdown .anchor.before svg path{fill:#fff}h2,h3{font-weight:400}.main-content-block{margin:1rem auto;max-width:960px;padding:.4rem 2rem 2rem}.main-content-block.headline{max-width:calc(960px + 4rem)}body{margin:0}#___gatsby,body,html{height:100%}#site-wrapper{display:flex;flex-direction:column}.dark-theme{color-scheme:dark} /*! mscc v0.4.2 - Copyright 2020 Microsoft Corporation */.cc-banner{font-size:12px;position:relative}.cc-banner .hide{display:none}.cc-banner a,.cc-banner div,.cc-banner span,.cc-banner svg{margin:0;padding:0;text-decoration:none}.cc-banner .cc-v-center{display:inline;line-height:2em;vertical-align:middle}.cc-banner[dir=rtl] .cc-float-left,.cc-float-right{float:right}.cc-banner[dir=rtl] .cc-float-right,.cc-float-left{float:left}.cc-banner{background:#f2f2f2;color:#231f20;display:none;font-family:Segoe UI,Helvetica Neue,Helvetica,Arial,sans-serif;margin:0;padding:0 1em;text-align:center}@media(min-width:768px){.cc-banner{font-size:13px;padding:0 1.65em}}.cc-banner>.cc-container{display:inline-block;padding:.75em 0;text-align:left;width:100%}[dir=rtl].cc-banner>.cc-container{text-align:right}@media(min-width:1084px){.cc-banner{padding:0}.cc-banner>.cc-container{max-width:1600px;width:90%}}.cc-banner.active{display:block}.cc-banner .cc-icon{height:1.846em;width:1.846em}.cc-banner .cc-text{margin-left:.5em;margin-right:1.5em}[dir=rtl].cc-banner .cc-text{margin-left:1.5em;margin-right:.5em}.cc-banner .cc-link{color:#0067b8;text-decoration:none}.cc-banner .cc-link:focus,.cc-banner .cc-link:hover{text-decoration:underline}.cc-banner .cc-link:focus{background:content-box rgba(0,120,215,.1);outline:0}@media screen and (-ms-high-contrast:active){.cc-banner{border-bottom:1px solid}}#branding>h1,#branding>h2{font-weight:400;text-align:center}#branding>h1{font-size:3rem;margin-bottom:0;margin-top:5rem}#branding>h2{font-size:1.5rem;margin-bottom:2rem;margin-top:6rem}#branding>h2.subnav{margin-top:0}#branding .headline{padding:2rem}#branding .headline,#branding .subheadline{align-items:center;display:flex;justify-content:center}#branding .subheadline{flex-direction:column;max-width:400px;padding-bottom:5rem;position:relative}#branding .subheadline p.attached-bottom{border-top:1px solid #d3d3d3;bottom:0;height:2.8rem;left:0;padding:1rem;position:absolute;right:0;text-align:left}#branding .recommendations p{margin-top:0;padding:0 1rem 1rem}.navbar-sub{clear:both;display:flex;height:3rem;justify-content:space-between;position:relative}.navbar-sub>ul{display:flex;margin:0;padding:0}.navbar-sub li.name{font-size:1.2rem;font-weight:600;width:200px}.navbar-sub li.name span{padding-left:1rem;padding-top:.7rem}.navbar-sub li{display:flex;font-size:1rem;font-weight:600;list-style:none}.navbar-sub li.divider{background-color:var(--playground-divider);height:1px;margin:9px 0;overflow:hidden}.navbar-sub li .example-indicator{top:1.25em!important}.navbar-sub li a{color:var(--text-color);display:block;padding:.95rem .75rem .5rem .7rem;text-decoration:none}.navbar-sub li.dropdown.open .dropdown-dialog,.navbar-sub li.dropdown.open ul{display:block}.navbar-sub li.dropdown .dropdown-dialog,.navbar-sub li.dropdown ul{display:none;float:left;left:0;position:absolute;top:100%;z-index:5}.navbar-sub li.dropdown ul.dropdown-menu{-webkit-background-clip:padding-box;background-clip:padding-box;background-color:var(--playground-dropdown-bg);border:1px solid var(--playground-dropdown-border);border-radius:4px;box-shadow:0 6px 12px rgba(0,0,0,.175);font-size:14px;list-style:none;margin:2px 0 0;max-height:calc(100vh - 150px);min-width:300px;overflow-y:auto;padding:5px 0;text-align:left;z-index:99}.navbar-sub li.dropdown ul.dropdown-menu.versions{min-width:5rem}.navbar-sub li.dropdown ul.dropdown-menu.versions li{margin-bottom:0;margin-left:0}.navbar-sub li.dropdown ul.dropdown-menu.versions li.beta{border-bottom:1px solid #f2f2f2;color:#3178c6}.navbar-sub li.dropdown ul.dropdown-menu.versions li.nightly{border-top:1px solid #f2f2f2}.navbar-sub li.dropdown ul.dropdown-menu.versions a{margin:0;padding:10px;text-align:center}.navbar-sub li.dropdown ul.dropdown-menu a{display:block;width:100%}.navbar-sub li.dropdown ul.dropdown-menu li:hover{background-color:#f5f5f5;color:#262626;text-decoration:none}.navbar-sub li.dropdown .dropdown-dialog{overflow-y:scroll;padding:2rem;width:800px}.navbar-sub li.dropdown .dropdown-dialog h3{font-size:2em;font-weight:600;height:2em;margin:0}.navbar-sub li.dropdown .dropdown-dialog a{color:var(--link-color);padding-bottom:.2rem;padding-left:0}.navbar-sub li.dropdown .dropdown-dialog #config-container p{margin:0 0 8px 4px}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container{display:flex;flex-wrap:wrap}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div{max-width:400px;min-width:200px}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div ol{margin:0;padding:0}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div li{margin-bottom:.5rem}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div input{margin-top:.4rem}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div label{font-weight:400}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div label:hover a.compiler_info_link{display:block}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div label a.compiler_info_link{display:none;padding:0;position:absolute;right:10px;text-align:center;top:0}.navbar-sub li.dropdown .dropdown-dialog #config-container #boolean-options-container>div label>span{font-family:var(--code-font);margin-left:4px}.navbar-sub li.dropdown .dropdown-dialog #compiler-dropdowns{display:flex;margin:1.5rem 0}.navbar-sub li.dropdown .dropdown-dialog #compiler-dropdowns label{font-family:var(--code-font);margin-right:.5rem;width:33%}.navbar-sub li.dropdown .dropdown-dialog #compiler-dropdowns label select{margin-left:1rem}.navbar-sub li.dropdown .dropdown-dialog #compiler-dropdowns label span.compiler-flag-blurb{display:block;font-family:var(--body-font);font-weight:400}main>nav{position:relative}main>nav .dropdown-dialog{background-color:var(--playground-dropdown-bg);padding-left:0}main>nav>ul li.disabled{opacity:.5}main>nav>ul li.active.open,main>nav>ul li.active:hover{background-color:var(--playground-dropdown-bg)}main>nav>ul li.active.open .caret{transform:scaleY(-1)}main>nav>ul li.active.name:hover{background-color:transparent}main>nav .examples{box-shadow:none;height:auto}button.examples-close{position:absolute;right:20px;top:20px}main #editor-toolbar>ul>li{margin-bottom:0;margin-left:0;position:relative}main #editor-toolbar>ul>li>a{padding-top:.8rem}@media(prefers-color-scheme:dark){main #editor-toolbar>ul>li>a:hover{border-bottom:1px solid #fff}}main #editor-toolbar>ul>li .dropdown-menu{left:4px}main #editor-toolbar li:hover{background-color:var(--playground-toolbar-hover-bg)}.caret{border-left:4px solid transparent;border-right:4px solid transparent;border-top:4px solid;display:inline-block;height:0;margin-left:2px;vertical-align:middle;width:0}#editor-toolbar>ul>li>a:first-child{padding-left:1rem}#playground-container{display:flex;height:800px}#playground-container ol{padding:0}#playground-container #navigation-container{background-color:var(--blue-tinged-bg);overflow-y:auto}#playground-container #navigation-container h4{margin-left:12px;margin-top:12px}#playground-container #navigation-container ul{padding:0}#playground-container #navigation-container ul li{border-radius:0 3px 3px 0;cursor:pointer;font-size:14px;font-weight:600;height:22px;line-height:22px;list-style:none;margin:0;overflow:hidden;padding-left:12px;text-overflow:ellipsis;white-space:nowrap}#playground-container #navigation-container ul li a{display:block;text-decoration:none}#playground-container #navigation-container ul li a svg{margin-right:8px}#playground-container #navigation-container ul li.selectable:hover{background-color:hsla(0,0%,100%,.314)}#playground-container #navigation-container ul li.selectable.selected{background-color:var(--blue-tinged-strong)}#playground-container #navigation-container ul li.selectable.selected a{color:var(--text-color)}#playground-container #navigation-container ul li.selectable.selected path{stroke:var(--text-color)}#playground-container #navigation-container ul li hr{margin-left:0;margin-top:10px;width:60px}#playground-container #story-container{font-size:.9rem;overflow-y:auto;padding:0 20px 20px}#playground-container #story-container .highlight pre{background-color:#f7f7f7;border-radius:3px;font-size:85%;line-height:1.45;overflow:auto;padding:16px}#playground-container #story-container details[open]{border-left:2px solid var(--blue-tinged-strong);padding-left:1rem}#playground-container #story-container details[open] summary{margin-left:-.5rem}#playground-container #story-container summary:hover{background-color:var(--background-minor-highlight-color);cursor:pointer}#playground-container #story-container kbd{background-color:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 2px #fff;color:#333;display:inline-block;font-family:Arial,Helvetica,sans-serif;font-size:11px;line-height:1.4;margin:0 .1em;padding:.1em .6em;text-shadow:0 1px 0 #fff}#playground-container #story-container .highlight{font-size:14px;margin-bottom:16px}#playground-container #story-container .pl-c{color:#969896}#playground-container #story-container .pl-c1,#playground-container #story-container .pl-s .pl-v{color:#0086b3}#playground-container #story-container .pl-e,#playground-container #story-container .pl-en{color:#795da3}#playground-container #story-container .pl-s .pl-s1,#playground-container #story-container .pl-smi{color:#333}#playground-container #story-container .pl-ent{color:#63a35c}#playground-container #story-container .pl-k{color:#a71d5d}#playground-container #story-container .pl-pds,#playground-container #story-container .pl-s,#playground-container #story-container .pl-s .pl-pse .pl-s1,#playground-container #story-container .pl-sr,#playground-container #story-container .pl-sr .pl-cce,#playground-container #story-container .pl-sr .pl-sra,#playground-container #story-container .pl-sr .pl-sre{color:#183691}#playground-container #story-container .pl-v{color:#ed6a43}#playground-container #story-container .pl-id{color:#b52a1d}#playground-container #story-container .pl-ii{background-color:#b52a1d;color:#f8f8f8}#playground-container #story-container .pl-sr .pl-cce{color:#63a35c;font-weight:700}#playground-container #story-container .pl-ml{color:#693a17}#playground-container #story-container .pl-mh,#playground-container #story-container .pl-mh .pl-en,#playground-container #story-container .pl-ms{color:#1d3e81;font-weight:700}#playground-container #story-container .pl-mq{color:teal}#playground-container #story-container .pl-mi{color:#333;font-style:italic}#playground-container #story-container .pl-mb{color:#333;font-weight:700}#playground-container #story-container .pl-md{background-color:#ffecec;color:#bd2c00}#playground-container #story-container .pl-mi1{background-color:#eaffea;color:#55a532}#playground-container #story-container .pl-mdr{color:#795da3;font-weight:700}#playground-container #story-container .pl-mo{color:#1d3e81}#playground-container #editor-container{-webkit-font-smoothing:subpixel-antialiased;background-color:var(--playground-dropdown-bg);display:flex;flex-direction:column;flex-grow:1;position:relative;width:calc(100% - 360px)}#playground-container #editor-container .editor-section{display:flex;flex-direction:column}#playground-container #editor-container #monaco-editor-embed{height:100%}#playground-container #editor-container #editor-toolbar{border-bottom:1px solid #c4c4c4;height:3rem;margin-bottom:10px;margin-right:-2px;position:relative}#playground-container #editor-container #editor-toolbar ul.right{background-color:var(--playground-dropdown-bg);position:relative;right:0}#playground-container .playground-dragbar{background-color:var(--playground-dragbar-bg);border-left:1px solid var(--playground-dragbar-border);cursor:col-resize;margin-left:2px;padding:3px}#playground-container .playground-dragbar.left{background-color:var(--blue-tinged-bg);border-left:none;border-right:1px solid var(--playground-dragbar-border);margin-left:0}#playground-container .playground-dragbar:hover{background-color:var(--blue-tinged-tinged-strong)}#playground-container .playground-dragbar.selected{background-color:var(--blue-tinged-strong)}#playground-container .playground-sidebar{background-color:var(--playground-dropdown-bg);display:flex;flex-basis:320px;flex-direction:column;max-width:320px;overflow-x:hidden;overflow-y:hidden;padding:0 1em 0 .5rem;width:320px;z-index:1}@media(max-width:800px){#playground-container .playground-sidebar{flex-basis:300px;max-width:300px;width:300px}}#playground-container .playground-sidebar .playground-plugin-container{flex:1 1;flex-grow:1;flex-shrink:1;height:100%;max-width:100%;overflow-x:hidden;overflow-y:auto;position:relative;width:100%}#playground-container .playground-sidebar .playground-plugin-container #restart-required{border:1px solid #3178c6;display:none;padding:5px 10px;position:absolute;right:0;text-align:center;top:-2px}#playground-container .playground-sidebar .playground-plugin-container pre{background-color:var(--pure-background);border:none;color:var(--text-color);overflow-x:auto;padding:0 10px;width:100%}#playground-container .playground-sidebar .playground-plugin-container pre code{font-family:var(--code-font);font-size:14px;line-height:19px}#playground-container .playground-sidebar .playground-plugin-tabview{align-items:center;display:flex;flex-wrap:wrap;justify-content:center;margin-bottom:10px;overflow-x:auto;overflow-y:hidden;padding-bottom:6px}@media(max-width:800px){#playground-container .playground-sidebar .playground-plugin-tabview{justify-content:flex-start}}#playground-container .playground-sidebar .playground-plugin-tabview button{background:none;border:none;color:inherit;cursor:pointer;font-family:var(--body-font);font-size:14px;font-weight:600;margin:14px 2px 5px;padding-top:0;position:relative}#playground-container .playground-sidebar .playground-plugin-tabview button .plugin-tab-notification{background-color:#c63131;border-radius:20px;color:#fff;height:20px;padding:0 4px;position:absolute;right:-10px;text-align:right;top:-8px}#playground-container .playground-sidebar .playground-plugin-tabview button:disabled{opacity:.4}#playground-container .playground-sidebar .playground-plugin-tabview button.active{border-bottom:1px solid var(--link-color)}#playground-container .playground-sidebar .playground-plugin-tabview button:focus{color:var(--link-color)}#playground-container .playground-sidebar .playground-settings-container,#playground-container .playground-sidebar pre{margin:0}.playground-plugin-container #log-tools{align-items:center;border-bottom:1px solid var(--playground-dragbar-border);border-top:1px solid var(--playground-dragbar-border);display:flex;margin-top:1px;padding:3px}.playground-plugin-container #log-tools svg{stroke:var(--text-color);cursor:pointer;padding-right:5px}.playground-plugin-container #log-container{font-family:var(--code-font);height:95%;line-height:1.5rem;overflow:auto;white-space:pre-wrap}.playground-plugin-container #log-container #log{margin-top:1rem}.playground-plugin-container #log-container .log-warn{color:orange}.playground-plugin-container #log-container .log-error{color:red}.playground-plugin-container #log-container .log-info{color:skyblue}.playground-plugin-container #log-container .log-log{color:silver}.playground-plugin-container #log-container .log-error,.playground-plugin-container #log-container .log-warn{font-weight:700}.playground-plugin-container #log-container hr{background:#fff;border:0;border-bottom:1px dashed #ccc}.playground-plugin-container #log-container .comma{color:#777}.playground-plugin-container div.ast{font-family:var(--code-font);font-size:.8rem;line-height:.3rem}.playground-plugin-container div.ast li{list-style-type:none;margin-bottom:4px;margin-left:0;position:relative}.playground-plugin-container div.ast li span.ast-node-number{color:blue}.dark-theme .playground-plugin-container div.ast li span.ast-node-number{color:#87cefa}.playground-plugin-container div.ast li span.ast-node-string{color:green}.dark-theme .playground-plugin-container div.ast li span.ast-node-string{color:#adff2f}.playground-plugin-container div.ast li span.ast-node-boolean{color:red}.dark-theme .playground-plugin-container div.ast li span.ast-node-boolean{color:coral}.playground-plugin-container div.ast li span.ast-node-undefined{color:brown}.dark-theme .playground-plugin-container div.ast li span.ast-node-undefined{color:#f4a460}.playground-plugin-container div.ast .ast-children>div.ast-tree-start{display:block;margin-left:12px;min-height:1rem}.playground-plugin-container div.ast div.ast-tree-start{display:inline-block}.playground-plugin-container div.ast div.ast-tree-start ul.ast-tree{border-left:1px solid #d3d3d3;display:none;margin-left:12px;margin-top:4px;padding-top:0}.playground-plugin-container div.ast div.ast-tree-start.open>a.node-name{top:4px}.playground-plugin-container div.ast div.ast-tree-start a.node-name{color:purple;font-weight:700;margin-left:10px;position:relative;text-decoration:none;top:0}.dark-theme .playground-plugin-container div.ast div.ast-tree-start a.node-name{color:orchid}.playground-plugin-container div.ast div.ast-tree-start a.node-name:hover{cursor:pointer;text-decoration:underline}.playground-plugin-container div.ast div.ast-tree-start a.node-name:before{display:block;height:1em;left:-.8em;padding:0 .1em;position:absolute}.playground-plugin-container div.ast div.ast-tree-start.open,.playground-plugin-container div.ast div.ast-tree-start.open>ul{display:block}.playground-plugin-container div.ast div.ast-tree-start>a:not(:last-child):before{content:"+"}.playground-plugin-container div.ast div.ast-tree-start.open>a:not(:last-child):before{content:"-"}.playground-plugin-container ul.compiler-diagnostics{font-family:var(--code-font);margin:0;padding:0}.playground-plugin-container ul.compiler-diagnostics li.diagnostic{cursor:pointer;font-size:.85rem;list-style:none;margin:0 0 1rem;padding-left:1rem;white-space:pre-wrap}.playground-plugin-container ul.compiler-diagnostics .error{border-left:2px solid red}.playground-plugin-container #empty-message-container{align-items:center;display:flex;flex-direction:column;height:80%;justify-content:center}.playground-plugin-container .playground-options input[type=checkbox]{margin-right:6px}.playground-plugin-container .playground-options.tight li{margin-bottom:.2rem}.playground-plugin-container .playground-options.tight span{margin-right:1rem}.playground-plugin-container .playground-options li{list-style:none;margin-bottom:1rem}.playground-plugin-container .playground-options li span{font-weight:600}.playground-plugin-container .briefly-highlight{animation:highlight 1s ease 1}@keyframes highlight{0%{background-color:#ff0}to{background-color:inherit}}span.right{float:right}.warning{font-size:.8}input[type=text],input[type=url]{font-size:1.1rem;padding:.2rem;width:80%}input.good{border-color:#086f56}#playground-container .playground-plugins{margin:1rem 0}#playground-container .playground-plugins.featured{border:1px solid #d3d3d3}#playground-container .playground-plugins.featured li{border-bottom:1px solid #d3d3d3}#playground-container .playground-plugins li{padding:10px 0}#playground-container .playground-plugins li div{display:flex;flex-direction:row;position:relative}#playground-container .playground-plugins input{display:block;height:100%;margin:0 8px;position:absolute}#playground-container .playground-plugins label{padding-left:30px;padding-right:10px}#playground-container .playground-plugins label span{font-weight:600}.custom-modules li a{border:1px solid #000;display:inline-block;height:1rem;line-height:1rem;text-align:center;text-decoration:none;width:1rem}.custom-modules li a:hover{background-color:#fcb7b7;color:red}.highlight-error{background-color:#fcb7b7}.highlight-info{background-color:#d3d3d3}.underscore-neutral{border-bottom:1px solid green}#popover-background{background-color:rgba(0,0,0,.75);height:100%;left:0;position:fixed;top:0;width:100%;z-index:100}#popover-modal{background-color:#fff;color:#000;display:flex;flex-direction:column;height:70%;left:50%;padding:20px;position:fixed;top:50%;transform:translate(-50%,-50%);width:80%;z-index:101}#popover-modal.smaller{height:40%;min-width:320px;padding:0;width:40%}#popover-modal textarea{font-family:var(--code-font);padding:8px}#popover-modal .close{position:absolute;right:20px;top:20px}#popover-modal pre{max-height:90%;overflow:auto}#popover-modal .window-title{background-color:#eee;font-size:32px;text-align:center}#popover-modal .window-title.warning{background:repeating-linear-gradient(45deg,#d63131,#d63131 10px,#c63131 0,#c63131 20px);color:#fff}#loader{align-items:center;display:flex;flex-direction:column;justify-content:center;padding-bottom:200px;padding-top:200px}#loader p{text-align:center}#loader .lds-grid{display:inline-block;height:80px;position:relative;width:80px}#loader .lds-grid div{animation:lds-grid 1.2s linear infinite;background:#3178c6;border-radius:50%;height:16px;position:absolute;width:16px}#loader .lds-grid div:first-child{animation-delay:0s;left:8px;top:8px}#loader .lds-grid div:nth-child(2){animation-delay:-.4s;left:32px;top:8px}#loader .lds-grid div:nth-child(3){animation-delay:-.8s;left:56px;top:8px}#loader .lds-grid div:nth-child(4){animation-delay:-.4s;left:8px;top:32px}#loader .lds-grid div:nth-child(5){animation-delay:-.8s;left:32px;top:32px}#loader .lds-grid div:nth-child(6){animation-delay:-1.2s;left:56px;top:32px}#loader .lds-grid div:nth-child(7){animation-delay:-.8s;left:8px;top:56px}#loader .lds-grid div:nth-child(8){animation-delay:-1.2s;left:32px;top:56px}#loader .lds-grid div:nth-child(9){animation-delay:-1.6s;left:56px;top:56px}@keyframes lds-grid{0%,to{opacity:1}50%{opacity:.5}}#flash-bg{align-items:center;bottom:0;display:flex;justify-content:center;left:0;pointer-events:none;position:fixed;right:0;top:0;z-index:42}#flash-bg p{background-color:rgba(0,0,0,.8);border-radius:1em;color:#fff;font-size:1.5rem;padding:.5em 1.5em;transform:translateZ(0);transition:opacity .1s ease-in-out}.monaco-list{background-color:var(--background-color)}#dev .navbar-sub .active{text-decoration:underline}#dev .content{display:flex}@media(max-width:800px){#dev .content{flex-direction:column}}#dev pre{background-color:#f9f9f9;margin-right:0;overflow-x:scroll}#dev pre,#dev pre .mtk5{color:#000}#dev .split-fifty{display:flex;flex-direction:row;width:100%}@media(max-width:800px){#dev .split-fifty{flex-direction:column}}#dev .split-fifty>div,#dev .split-fifty>p{flex:1 1}#dev .split-fivehundred{width:calc(100% - 500px)}@media(max-width:900px){#dev .split-fivehundred{width:100%}}#dev .fivehundred{margin-left:20px;width:500px}@media(max-width:900px){#dev .fivehundred{margin-left:0;padding-left:20px;text-align:center;width:100%}}#dev .split-code{display:flex}#dev .split-code>p{flex:1 1;padding-right:1rem;width:30%}#dev .split-code>pre{flex:3 1;overflow-x:scroll}#dev #example-buttons div.button{background-color:#faf9f8;color:#000;cursor:pointer;display:inline-block;margin:10px;padding:8px 12px;text-decoration:none}#dev #example-buttons div.button:active,#dev #example-buttons div.button:hover{background-color:#dfdfdf}#dev #twoslash-failure{-webkit-backdrop-filter:blur(5px);backdrop-filter:blur(5px);background-color:hsla(0,0%,100%,.5);bottom:0;left:0;padding:10px;position:absolute;right:0;top:0}#dev #twoslash-failure .err-content{border:2px solid #c63131;padding:20px}#dev #twoslash-failure .err-content p{font-family:Menlo,Monaco,Consolas,Courier New,monospace;white-space:pre-wrap}.cheatsheets .row{justify-content:center;margin-bottom:2rem}.cheatsheets .row p{flex:1 1;margin:10px;max-width:320px}.cheatsheets .sheet-container{align-items:center;display:flex;flex-wrap:wrap;justify-content:center}.cheatsheets .sheet{position:relative}.cheatsheets .sheet img{border:1px solid #000;box-shadow:0 4px 20px -6px rgba(0,0,0,.25);max-width:360px;transition:all .15s ease}.cheatsheets .sheet:active,.cheatsheets .sheet:hover{z-index:100}.cheatsheets .sheet:active img,.cheatsheets .sheet:hover img{border-color:#3178c6;box-shadow:0 4px 20px -2px rgba(0,0,0,.25);margin:-2px;z-index:100}.cheatsheets .sheet:active .description,.cheatsheets .sheet:hover .description{display:block}.cheatsheets .sheet.cs-1{transform:rotate(-1.1deg)}.cheatsheets .sheet.cs-2{transform:rotate(1.2deg)}.cheatsheets .sheet.cs-3{margin-top:-40px;transform:rotate(3deg)}.cheatsheets .sheet.cs-4{margin-top:-40px;transform:rotate(-2deg)}.cheatsheets .sheet .description{background-color:rgba(0,0,0,.5);box-sizing:border-box;color:#fff;display:none;font-size:2.5rem;height:100%;padding-top:30%;position:absolute;text-align:center;top:0;width:100%}.cheatsheets .fluid-button{border:1px solid #000;color:#000;margin:3rem auto 0;max-width:260px}@media(max-width:800px){.cheatsheets .cs-2{margin-top:-40px}}@media(min-width:768px){.cheatsheets .sheet-container{margin:0;min-height:550px}.cheatsheets .cs-1 .description{padding-top:20%}}@media(min-width:1200px){.cheatsheets .sheet-container{margin:0 -80px;min-height:780px}.cheatsheets .sheet img{max-width:550px}.cheatsheets .cs-1 .description{padding-top:30%}}.community{padding:0}.community.centered{text-align:center}.community.centered h2{margin-top:120px}.community .sidebar{background-color:rgba(204,207,233,.1)}.community .next-steps-container{background-color:#fff}.community .banner-text{margin-top:20px}.community .callouts{display:flex;flex-wrap:wrap;margin:20px 0}.community .callouts .callout{display:flex;line-height:1.4rem;margin-bottom:10px;margin-top:20px;width:48%}@media(max-width:800px){.community .callouts .callout{width:90%}}.community .callouts h3{font-size:1rem;margin:0 0 10px;padding:0}.community .callouts .icon{background-position:50%;background-repeat:no-repeat;background-size:auto 3.2rem;display:block;height:5rem;margin:0 20px 20px;min-width:5rem;transition:background-color .2s ease-out;width:5rem}@media screen and (-ms-high-contrast:active){.community .callouts .icon{-ms-high-contrast-adjust:none}}.community .callouts .icon.high-contrast-only{font-size:1.8rem}.community .callouts .icon.img-circle{border-radius:50%}.community .callouts .icon.discord{background-color:#7289da;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGlkPSJwcmVmaXhfX0xheWVyXzEiIHZpZXdCb3g9IjAgMCAyNDUgMjQwIj48cGF0aCBkPSJNMTA0LjQgMTAzLjljLTUuNyAwLTEwLjIgNS0xMC4yIDExLjFzNC42IDExLjEgMTAuMiAxMS4xYzUuNyAwIDEwLjItNSAxMC4yLTExLjEuMS02LjEtNC41LTExLjEtMTAuMi0xMS4xem0zNi41IDBjLTUuNyAwLTEwLjIgNS0xMC4yIDExLjFzNC42IDExLjEgMTAuMiAxMS4xYzUuNyAwIDEwLjItNSAxMC4yLTExLjFzLTQuNS0xMS4xLTEwLjItMTEuMXoiIGNsYXNzPSJwcmVmaXhfX3N0MCIvPjxwYXRoIGQ9Ik0xODkuNSAyMGgtMTM0QzQ0LjIgMjAgMzUgMjkuMiAzNSA0MC42djEzNS4yYzAgMTEuNCA5LjIgMjAuNiAyMC41IDIwLjZoMTEzLjRsLTUuMy0xOC41IDEyLjggMTEuOSAxMi4xIDExLjIgMjEuNSAxOVY0MC42YzAtMTEuNC05LjItMjAuNi0yMC41LTIwLjZ6bS0zOC42IDEzMC42cy0zLjYtNC4zLTYuNi04LjFjMTMuMS0zLjcgMTguMS0xMS45IDE4LjEtMTEuOS00LjEgMi43LTggNC42LTExLjUgNS45LTUgMi4xLTkuOCAzLjUtMTQuNSA0LjMtOS42IDEuOC0xOC40IDEuMy0yNS45LS4xLTUuNy0xLjEtMTAuNi0yLjctMTQuNy00LjMtMi4zLS45LTQuOC0yLTcuMy0zLjQtLjMtLjItLjYtLjMtLjktLjUtLjItLjEtLjMtLjItLjQtLjMtMS44LTEtMi44LTEuNy0yLjgtMS43czQuOCA4IDE3LjUgMTEuOGMtMyAzLjgtNi43IDguMy02LjcgOC4zLTIyLjEtLjctMzAuNS0xNS4yLTMwLjUtMTUuMiAwLTMyLjIgMTQuNC01OC4zIDE0LjQtNTguMyAxNC40LTEwLjggMjguMS0xMC41IDI4LjEtMTAuNWwxIDEuMmMtMTggNS4yLTI2LjMgMTMuMS0yNi4zIDEzLjFzMi4yLTEuMiA1LjktMi45YzEwLjctNC43IDE5LjItNiAyMi43LTYuMy42LS4xIDEuMS0uMiAxLjctLjIgNi4xLS44IDEzLTEgMjAuMi0uMiA5LjUgMS4xIDE5LjcgMy45IDMwLjEgOS42IDAgMC03LjktNy41LTI0LjktMTIuN2wxLjQtMS42czEzLjctLjMgMjguMSAxMC41YzAgMCAxNC40IDI2LjEgMTQuNCA1OC4zIDAgMC04LjUgMTQuNS0zMC42IDE1LjJ6IiBjbGFzcz0icHJlZml4X19zdDAiLz48L3N2Zz4=)}.community .callouts .icon.stackoverflow{background-color:#5016d9;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTE0IDU1VjM1LjhoMy41bC0uMSAxNS40aDIzVjM1LjlINDRWNTVIMTR6bTUuNi0xMC4xaDE4djMuOGgtMTh2LTMuOHptLjEtM0wyMCAzOGwxOC4xIDEuNy0uNCAzLjktMTgtMS43em0uOS03LjkgMS4xLTMuOCAxNy41IDQuOS0xLjEgMy44TDIwLjYgMzR6bTMuMy05LjMgMi0zLjQgMTUuNSA5LjQtMi4xIDMuNC0xNS40LTkuNHptNy43LTkuNCAzLjItMi4zIDEwLjYgMTQuOC0zLjIgMi4zLTEwLjYtMTQuOHptMTEuNi01LjdMNDcgOWwzIDE3LjktMy45LjYtMi45LTE3Ljl6Ii8+PC9zdmc+)}.community .callouts .icon.blog{background-color:#d9a216;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTI2LjMgMTcuNmMxMS4xIDAgMjAuMSA5IDIwLjEgMjAuMWgtNC4zYzAtNC4yLTEuNi04LjItNC42LTExLjJzLTctNC42LTExLjItNC42di00LjN6bTAtOC42QzQyLjEgOSA1NSAyMS45IDU1IDM3LjhoLTQuM2MwLTMuMy0uNi02LjUtMS45LTkuNS0xLjItMi45LTMtNS41LTUuMi03LjgtMi4yLTIuMi00LjktNC03LjgtNS4yLTMtMS4zLTYuMi0xLjktOS41LTEuOVY5em04LjUgMjAuMmMyIDIgMi45IDQuNSAyLjkgNy4xLTIuOSA0LjMtMi45IDEwLjEtMi45IDEwLjEtMTEuNSAwLTIwLjEgOC42LTIwLjEgOC42bC0uNi0uNi0xLTEgMTIuNy0xMi43aC40YzEuNiAwIDIuOS0xLjMgMi45LTIuOXMtMS4zLTIuOS0yLjktMi45LTIuOSAxLjMtMi45IDIuOXYuNEwxMC43IDUwLjkgOSA0OS4zczguNi04LjYgOC42LTIwLjFjMCAwIDUuNyAwIDEwLjEtMi45IDIuNiAwIDUuMS45IDcuMSAyLjl6Ii8+PC9zdmc+)}.community .callouts .icon.uservoice{background-color:#1a2833;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTM0LjkgOUM0NiA5IDU1IDE0LjYgNTUgMjEuNWMwIDQuNC0zLjYgOC4yLTkuMSAxMC40IDEuMiAyLjMgMy4yIDQuNyA1LjMgNy45LTQuMy0xLjUtMTAuNy0yLjktMTQuNC01LjlMMzUgMzRjLTExLjEgMC0yMC4xLTUuNi0yMC4xLTEyLjUtLjItNi45IDguOS0xMi41IDIwLTEyLjV6bTQuOCAyOS43YzAgNS44LTYuOSAxMC41LTE1LjMgMTAuNWgtMS4yYy0zLjEgMi45LTcuNCA1LjgtMTIuMyA1LjggMS4xLTIuMiAzLjUtNC41IDUtNy41LTQuMi0xLjktNi45LTUuMS02LjktOC44IDAtMy43IDIuNy02LjkgNi45LTguOCAzLjYgMy41IDkuOSA1LjggMTcuMSA1LjhsMS44LS4xYzEuNCAxLjEgMyAxLjkgNC45IDIuN3YuNHoiLz48L3N2Zz4=)}.community .callouts .icon.twitter{background-color:#00a0d1;background-image:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+PHBhdGggZmlsbD0iI2ZmZiIgZD0iTTU2IDE3LjRjLTEuOC44LTMuNyAxLjMtNS43IDEuNSAyLTEuMiAzLjYtMy4xIDQuMy01LjMtMS45IDEuMS00IDEuOS02LjMgMi4zLTEuOC0xLjktNC40LTMuMS03LjItMy4xLTUuNCAwLTkuOCA0LjMtOS44IDkuNyAwIC44LjEgMS41LjMgMi4yLTguMi0uNC0xNS40LTQuMy0yMC4zLTEwLjEtLjggMS40LTEuMyAzLjEtMS4zIDQuOSAwIDMuNCAxLjcgNi4zIDQuNCA4LTEuNi0uMS0zLjEtLjUtNC41LTEuMnYuMWMwIDQuNyAzLjQgOC42IDcuOSA5LjUtLjguMi0xLjcuMy0yLjYuMy0uNiAwLTEuMy0uMS0xLjktLjIgMS4zIDMuOCA0LjkgNi42IDkuMiA2LjctMy40IDIuNi03LjYgNC4xLTEyLjIgNC4xLS44IDAtMS42IDAtMi4zLS4xIDQuNCAyLjcgOS41IDQuMyAxNS4xIDQuMyAxOC4xIDAgMjgtMTQuNyAyOC0yNy41di0xLjNjMS45LTEuMiAzLjYtMi45IDQuOS00Ljh6Ii8+PC9zdmc+)}.community .callouts .icon.definitelytyped{background-color:#0077d2;background-image:url(data:image/png;base64,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)}.community .callouts .icon.bug{background-color:#4d4d4d;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NDkxMSwgMjAxMy8xMC8yOS0xMTo0NzoxNiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzlFQkFERkU4NkJCMTFFM0FBNTJFRTMzNTJEMUJDNDYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzlFQkFERkQ4NkJCMTFFM0FBNTJFRTMzNTJEMUJDNDYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkU1MTc4QTJFOTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkU1MTc4QTJGOTlBMDExRTI5QTE1QkMxMDQ2QTg5MDREIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Kk5lQwAABYxJREFUeNrkm29oVXUYx3+7bM3V1FnbqlltrtXWtYRa1nqxooY5E7EhKWGuaTDBagol9SIMDCKICASj+cISw/DPi16ZBakrUBnoC7nNoTMWy6I1c+LmVq6t78N9jpyu555znt855+536IHPi939/jzP95zznN+/kzc1NaUitirwJJgPasF94DZQDG7hMqNgBFwEZ5kU+AH0R+lcXgQCJMBT4EXwLKgM2N7P4FvwJegCk6YKUA5eB23grogu2C/gc7AN/GGKABTsZtAOZqjc2DjYAT5kUfSNBNCkAGwGo1PTZ6PsQ4FuHLp3QD3YDR5QZtgZsAac1ElYokcGbATHDApesS/kUwf7GEkOKAK7wAvKbNsPXgZjYQowG3wNnlDxsONgCbgchgAU/GHwiIqXUT5o8hLBKwfcDA7FMHgrUR/iGLQEoGTyBWhQ8bUGjiFPR4A3QIuKv7VwLKIcQMnue5Dv0fjT/IwtAM3g+RyMBmkU+BXf3qc5Rx3xqDPBE7LjfkaCheCcj1HYKYe6JeBt8GcEo75L3HaJQ7+nfNQ/x7H9p67TFX4L1Pi4EocdfhsGH4BPwVbwqu0xGwI/8vT2N/77Gv+vAJSCO3n6PJ//Vjz72w62cPtORnfAwx7+1nBsW93ugGow7vOKtPkYa9eDl0Clxji9kuvW+yjb5tPncY7xet3MhjoFt2RzgIlU2DQL/O6017W/Be4BawXJqMCgTH+ToOxajvWG1+AmYVBlBglQKrxwmzIFoB9XCzt91CABpL6sti62JcBiXtKS2GMGCSD1pZxjvi7AKmED9PraYJAAG2yvVL+2yi7AImHl90C3QQJ03/B+97ZF1lCYVlN6BBV/BffykNQkoyF4H5grqJOkO6BR2NF2A4O35gifCOs0JjTW9vYaPPPbJ11LJAFqBRVoDf68wQLQI3BBUL424XPiY1lvDOb/ZwRla0iAOYIKv8dAgEFB2VtJgJmCChMxEEAyHigmAQoFFWbFQIDZgrKF0p2hmTEQQOQjCTAmKD8vBgJUCcqOkQBXBBXosEORwcEXKdmBjCskwICgQr5h0+BMW6i8V7LtNkAC9As7WWqwAM8Jy/cnhBMhspVKvq2eC0uwbxLrSWhMa+dpdJQLW6mRpLtpOlyuMcL7CTwErhoSPG2ApjQEuD3BQ0fp0ZJqlT6pZYpt0wieYh60nuWDGp2+At4xIPgt7IvU0jHzBkFdgD27HWDGNGyGFHHfulaXuTN0IkBjZ8EykJeDwKmPFtAXwN8TTltjrVkKfwcawXJW3G3v8DTYCKoiCLwGvAl6QthpbnU6J5jP2f1uh1Wgxbbxwv0qvT/vtZRGA6wuzs50+Pkb8JdgQtPMq1VJld7bnxtSzhjgJD5hzwEW611OZK6xlSvzeYbAsl3Cx4PK7ozodOl6t93hfJByqbzOVnYh+MdHhxfBLI1bnuoMhRx8imPMKgDR5LG/nrSVfddHpx8HeO4/ClmApsw+snXsdk7gYMat+r5Hp0sDCLAkxOA7nfrI1nGxx2tmQUb5x8FuzgvD4Dw4wNm2MIAA1SEF38cx+RaAeBCMZGlwb44GOyUhBD/CsTj24TatpddXq3L+RIVmXnE4QzjJMaSylvBxFdqzKHsVrDD8Dmj36sOvIx0unewHDRENg4MI0BH2FyP0RcZOlzW3Ib7VLvPqDK0z1PEq7bDmLVwCLgnr0AhvnUp/0eJp0k9m6HO4fUp2nGZODgUY5PzUJVlHkxg1TEfnjxqY8I6yb12SSjqLm7T9/Ax4TaW/+JxuIx862KcL4toBk1QFT1omXZLRHQHaL3Npl/r8jH3QjiGsbJ3kGd/fDo6WBWi31KG9a9xXMgzfw35tVfCR9l52dk8Ibe7htnq57YowfY7i4+lYWUL9z+1fAQYACqstE4NCc18AAAAASUVORK5CYII=)}.community .community-callout-headline{margin-top:0}.community h3.centered-highlight{background-color:rgba(204,207,233,.1);padding:20px;text-align:center}.community .upcoming-event{min-width:330px}.community .upcoming-event img{width:50px}.community .upcoming-event .event-info{position:relative}.community .upcoming-event .meetup-text{max-height:300px;overflow-y:auto;padding-bottom:20px}.community .upcoming-event .meetup-gradient{background:var(--raised-background-color);background:var(--fade-gradient);height:30px;position:absolute;top:290px;width:100%}.community .events>h4{padding-left:20px}.row,.split-row{display:flex;flex-direction:row;flex-wrap:wrap}.split-row{align-items:center;justify-content:center}.split-row .first{margin-left:0}.col1{flex:1 1;min-width:250px;padding:1rem}.col2{flex:2 1}.col1.first{margin-left:20px}.col1.last{margin-right:0}@media(max-width:800px){.container>.row{flex-direction:column}}.version-bar{background-color:#262626;color:#fff;margin:0;padding:.7rem 2rem;text-align:center}.version-bar p{margin:0}.version-bar p a{color:#719af4}.grey-box{background-color:#d8d8d8;box-sizing:border-box;margin-right:20px;padding:18px}.grey-box a{color:#000}.clicky-grey-button.first,.grey-box.first{margin-left:20px}.clicky-grey-button.last,.grey-box.last{margin-right:0}.split-row>.clicky-grey-button{flex:1 1}@media(max-width:800px){main #index-2 h2{font-size:1.8rem;padding-left:20px;padding-right:20px}main #index-2 div.headline-diagram{height:400px;max-width:100%;overflow-x:hidden}main #index-2 .split-row>a{margin-left:20px!important;min-width:80%}main #index-2 .grey-box{margin-right:0}main #index-2 .illustration{display:none}main #index-2 ul.dropdown{margin-top:12px}main #index-2 .headline-diagram div.editor.front{margin:20px auto;position:static}main #index-2 .headline-diagram .text{overflow-x:scroll}main #index-2 #m-stories{flex-direction:column}main #index-2 #m-stories div.illustration{display:flex;justify-content:center;order:1}main #index-2 #m-stories div.illustration div.bg{visibility:hidden}main #index-2 #m-stories div.illustration div.fg{position:static;text-align:center}main #index-2 #m-stories div.copy{margin:20px auto 0;order:2;position:static;text-align:center}main #index-2 #m-stories div.copy a.migration-button{margin:0 auto}main #index-2 .small_full_width{width:100%}main #index-2 .github-bar{display:none}main #index-2 .get-started-section{flex-direction:column}main #index-2 .get-started-section a.get-started{background-image:none!important;height:auto!important;margin:0 auto}main #index-2 img{max-width:100%}main #index-2 h3{text-align:center}}@media(max-width:900px){.tag-container .twoslash-annotation.left{bottom:0;left:0;position:static;top:auto!important}.tag-container .twoslash-annotation.left svg{transform:rotate(44deg) scaleX(-1) translateX(-20px)!important}.tag-container .twoslash-annotation.right{display:none}}.show-only-small{display:none}@media(max-width:480px){.show-only-small{display:block!important}#index div.headline-diagram div.editor.front{max-width:300px}}#index-2 h1{font-size:2.5rem;font-weight:200;line-height:2.8rem;margin-top:0;padding-right:40px}#index-2 h1 strong{font-weight:600}#index-2 h2{font-size:2.5rem;font-weight:500;line-height:2.5rem;margin-top:0;text-align:center}#index-2 h3{font-size:1.6rem;font-weight:400;line-height:1.6rem;margin-bottom:2.5rem;margin-top:0}#index-2 p{font-size:1.2rem}#index-2 .col1{min-width:230px}@media(max-width:360px){#index-2 .col1{max-width:calc(100% - 2rem)}}#index-2 .darkblue{background-color:#00273f;color:#fff}#index-2 .blue{background-color:#3178c6;color:#fff}#index-2 .purple{background-color:#4e086f;color:#fff}#index-2 .dark-green{background-color:#086e12;color:#fff}#index-2 .white{background-color:#fff;color:#000}#index-2 .white .col1 h3{text-align:center}#index-2 .white .col1>p,#index-2 .white .col2>p{font-size:1.2rem}#index-2 .light-grey{background-color:#faf9f8;color:#000}#index-2 .grey{background-color:#d8d8d8;padding-bottom:0}#index-2 .grey div.container{padding:1rem}#index-2 .headline{min-height:420px}#index-2 .headline .col1{padding-bottom:3rem}#index-2 .headline p{padding-right:20px}#index-2 .headline .container{font-size:1rem;padding-bottom:0}#index-2 .container{max-width:1080px;padding-bottom:40px;padding-top:64px}#index-2 .container,#index-2 .container .half{display:flex;flex-direction:column;margin:0 auto;position:relative}#index-2 .container .half{max-width:780px}@media(max-width:360px){#index-2 .container .half{max-width:100%}}#index-2 .headline-diagram{display:relative}@media screen and (-ms-high-contrast:active){#index-2 .headline-diagram{border:2px solid #fff}}#index-2 .headline-diagram pre .code-container{overflow:hidden}#index-2 .headline-diagram pre .code-container a{display:none}#index-2 .headline-diagram .editor{border:2px solid #7fa2c9;border-radius:4px;width:540px}#index-2 .headline-diagram .editor ul.editor-tabs{display:flex;flex-direction:row;font-size:14px;margin:0;padding:0}#index-2 .headline-diagram .editor ul.editor-tabs li{list-style:none;padding:10px}#index-2 .headline-diagram .editor ul.editor-tabs li a{color:#fff;text-decoration:none}#index-2 .headline-diagram .editor ul.editor-tabs li.selected{text-decoration:underline}#index-2 .headline-diagram .editor .min-dark{display:none}#index-2 .headline-diagram .editor.front{border-radius:8px;width:96%}@media screen and (-ms-high-contrast:active){#index-2 .headline-diagram .editor.front{border:none}}#index-2 .headline-diagram .editor .error{border-left:0!important}#index-2 .headline-diagram .editor .editor-inner{position:relative}#index-2 .headline-diagram .editor .titlebar{border-bottom:2px solid #172e38;display:flex;flex-direction:row;height:2rem}#index-2 .headline-diagram .editor .titlebar .lang{display:none;margin-left:6px;margin-top:3px}#index-2 .headline-diagram .editor .titlebar .window-name{display:none;margin-left:10px;padding-top:5px}#index-2 .headline-diagram .editor .line-error{background-color:#c63131;height:20px;left:0;position:absolute;width:22px}#index-2 .headline-diagram .editor .underline-error{background:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='6' height='3' viewBox='0 0 6 3'%3E%3Cg fill='%23c94824'%3E%3Cpolygon points='5.5 0 2.5 3 1.1 3 4.1 0'/%3E%3Cpolygon points='4 0 6 2 6 .6 5.4 0'/%3E%3Cpolygon points='0 2 1 3 2.4 3 0 .6'/%3E%3C/g%3E%3C/svg%3E") repeat-x 0 100%;padding-bottom:3px}#index-2 .headline-diagram .editor .error-message{color:#444d80;font-family:var(--code-font);font-size:.8rem}#index-2 .headline-diagram .editor .error-behind{opacity:0}#index-2 .headline-diagram .editor .inline-completions{position:relative}#index-2 .headline-diagram .editor .inline-completions ul.dropdown{background-color:#fff;border-left:4px solid #4b9edd;color:gray;display:inline-block;font-family:var(--code-font);font-size:.8rem;margin:0;padding:0;position:absolute;width:240px}#index-2 .headline-diagram .editor .inline-completions ul.dropdown:before{background-color:#fff;content:" ";left:-3px;position:absolute;top:-16px;width:2px}#index-2 .headline-diagram .editor .inline-completions ul.dropdown li{border-bottom:1px solid #000;height:1rem;overflow-x:hidden;padding-left:4px}#index-2 .headline-diagram .editor .inline-completions ul.dropdown li span.result-found{color:#4b9edd}#index-2 .headline-diagram .editor .inline-completions ul.dropdown li span.result{color:#000;display:inline-block;width:100px}#index-2 .headline-diagram .editor .did-you-mean,#index-2 .headline-diagram .editor .did-you-mean-icon{position:absolute}#index-2 .headline-diagram .editor .content{display:flex;flex-direction:row}#index-2 .headline-diagram .editor .content svg{margin:12px auto}#index-2 .headline-diagram .editor .content svg path{fill:#fff}#index-2 .headline-diagram .editor .content .text{background-color:#235a97;border-radius:0 0 6px 6px;border-top:1px solid #7fa2c9;flex-grow:1;flex-shrink:1;font-family:var(--code-font);font-size:.8rem;height:260px;line-height:.95rem;overflow-x:auto;position:relative}#index-2 .headline-diagram .editor .content .text pre{background-color:#235a97;border:none;margin:0}#index-2 .headline-diagram .editor .content .text pre code{font-size:14px;line-height:16px}#index-2 .headline-diagram .editor .content .text pre .error{background-color:rgba(255,0,0,.149);color:#ffc5c5}#index-2 .headline-diagram .editor .content .text .language-id{display:none}#index-2 .headline-diagram .editor .highlight{color:#9ed5ff}#index-2 .headline-diagram .back .content .text>div{padding-right:200px}#index-2 .next-headline-button{align-items:center;background-color:#fff;bottom:20px;color:#000;cursor:pointer;display:flex;flex-direction:row;height:30px;justify-content:center;margin-bottom:20px;padding:3px;position:absolute;right:15px;text-decoration:none;width:30px}@media screen and (-ms-high-contrast:active){#index-2 .next-headline-button{border:2px solid gray}}#index-2 .next-headline-button.focus,#index-2 .next-headline-button:hover{background-color:#eee}#index-2 .next-headline-button:active{background-color:#ddd}#index-2 .next-headline-button .fluid-button-title{font-weight:600}#index-2 .next-headline-button svg path{fill:#000}@media screen and (-ms-high-contrast:active){#index-2 .next-headline-button svg path{fill:#ff0}}#index-2 a.get-started{align-items:flex-end;background-color:#fff;box-shadow:0 4px 20px -6px rgba(0,0,0,.25);box-sizing:border-box;color:#000;cursor:pointer;display:flex;margin:0 auto;max-width:244px;padding:1rem;text-decoration:none;width:100%}@media screen and (-ms-high-contrast:active){#index-2 a.get-started{border:2px solid gray}}#index-2 a.get-started.focus,#index-2 a.get-started:hover{background-color:#eee}#index-2 a.get-started:active{background-color:#ddd}#index-2 a.get-started .fluid-button-title{font-weight:600}#index-2 a.get-started.short{background:#3178c6;background-position-y:bottom -180px;color:#fff;height:260px;outline:1px solid #fff}#index-2 a.get-started.short.handbook{background-image:url(/images/index/get-started-handbook-blue.svg)}#index-2 a.get-started.short.playground{background-image:url(/images/index/get-started-playground-blue.svg)}#index-2 a.get-started.short.download{background-image:url(/images/index/get-started-download-blue.svg);background-position:100% 100%;background-repeat:no-repeat}#index-2 a.get-started.short svg path{stroke:#fff}#index-2 a.get-started.short:active{background-color:#156fb4}#index-2 a.get-started.short:focus-visible,#index-2 a.get-started.short:hover{box-shadow:0 4px 20px -2px rgba(0,0,0,.25);outline-width:2px}#index-2 a.get-started.tall{background:#fff;color:#000;height:342px;margin-bottom:2px;outline:1px solid #000}#index-2 a.get-started.tall:focus-visible,#index-2 a.get-started.tall:hover{box-shadow:0 4px 20px -2px rgba(0,0,0,.25);color:#3178c6;margin-bottom:0;outline-color:#3178c6;outline-width:2px}#index-2 a.get-started.tall:focus-visible svg path,#index-2 a.get-started.tall:hover svg path{stroke:#3178c6}#index-2 a.get-started.tall:active{background-color:#eee}#index-2 a.get-started .fluid-button-title{font-size:1.4rem}#index-2 a.get-started svg{margin-bottom:10px;margin-left:20px}#index-2 a.get-started:active{box-shadow:0 4px 10px 0 rgba(0,0,0,.25)}#index-2 a.get-started.handbook{background-image:url(/images/index/get-started-handbook.svg);background-position:0 100%;background-repeat:no-repeat}#index-2 a.get-started.playground{background-image:url(/images/index/get-started-playground.svg);background-position:bottom;background-repeat:no-repeat}#index-2 a.get-started.download{background-image:url(/images/index/get-started-download.svg);background-position:100% 100%;background-repeat:no-repeat}#index-2 .call-to-action{display:flex;justify-content:center;position:relative}#index-2 .call-to-action a.flat-button{background-color:#fff;color:#000;cursor:pointer;display:block;font-size:1.2rem;height:1.4rem;line-height:1.4rem;padding:1rem;text-align:center;text-decoration:none}@media screen and (-ms-high-contrast:active){#index-2 .call-to-action a.flat-button{border:2px solid gray}}#index-2 .call-to-action a.flat-button.focus,#index-2 .call-to-action a.flat-button:hover{background-color:#eee}#index-2 .call-to-action a.flat-button:active{background-color:#ddd}#index-2 .call-to-action a.flat-button .fluid-button-title{font-weight:600}#index-2 .call-to-action a.flat-button:first-child{margin-right:2rem}#index-2 .call-to-action .handbook-preview{background-color:#1a1a1a;padding:4rem}#index-2 .call-to-action .inline-buttons{background-color:#1a1a1a;display:flex;justify-content:center}#index-2 .call-to-action .inline-buttons a{background-color:#1a1a1a;border-left:4px solid #00273f;color:#fff;flex:1 1;margin:0!important}#index-2 .call-to-action .inline-buttons a:first-child{border-left:none}#index-2 .call-to-action .inline-buttons a:active,#index-2 .call-to-action .inline-buttons a:hover{color:#000}#index-2 .cta-redirects{overflow-y:hidden}#index-2 .cta-redirects>div{margin-bottom:-18%;position:relative}#index-2 .cta-redirects>div a{bottom:55%;position:absolute}#index-2 .release-info{display:flex;flex-direction:row;position:relative;width:100%}#index-2 .release-info .needle,#index-2 .release-info .needle-head{background-color:#000;height:68px;margin-top:-8px;position:absolute;width:2px}#index-2 .release-info .needle-head{background-color:transparent;border-left:4px solid transparent;border-right:4px solid transparent;border-top:6px solid #000;height:0;margin-left:-4px;margin-top:-14px}#index-2 .release-info>div>div{display:flex;flex-direction:row}#index-2 .bar{height:50px;margin-left:-1px;width:100%}#index-2 .separator{background-color:#000;height:12px;margin-top:50px;width:1px}@media screen and (-ms-high-contrast:active){#index-2 .needle-head{opacity:0}#index-2 .release-info .needle{border:1px solid #000;height:80px}#index-2 .beta>div,#index-2 .rc>div,#index-2 .release>div,#index-2 form.search:focus{border:1px solid #000}}#index-2 .release{width:55%}#index-2 .release .bar{background-color:#c4c4c4}#index-2 .beta{width:28%}#index-2 .beta .bar{background-color:#3178c6}#index-2 .rc{width:17%}#index-2 .rc .bar{background-color:#235a97}#index-2 .migrations{overflow:hidden}#index-2 .migrations.github #migration_title{color:#fff}#index-2 .migrations strong{color:#187abf}#index-2 .migrations .container{padding-bottom:0}#index-2 #m-stories{min-height:370px;position:relative}#index-2 #m-stories .controls a{align-items:center;background-color:#c4c4c4;color:#000;display:flex;height:2rem;justify-content:center;line-height:2.5rem;position:absolute;text-align:center;top:70%;width:2rem;z-index:2}#index-2 #m-stories .controls a:hover{background-color:#eee}#index-2 #m-stories .controls a:active{background-color:#ddd;top:calc(70% + 1px)}#index-2 #m-stories .controls a.left{left:0}#index-2 #m-stories .controls a.right{right:0}#index-2 #m-stories .copy{background:#faf9f8;background:linear-gradient(90deg,#faf9f8 48%,hsla(30,17%,98%,.125))}#index-2 #m-stories .copy p{font-size:1rem}#index-2 #m-stories .airbnb .fg,#index-2 #m-stories .goog .illustration .fg{padding-top:40px}#index-2 #m-stories .copy{padding-left:20px;padding-right:30px;position:absolute;transition:opacity .2s ease-out;width:260px}#index-2 #m-stories .copy p{padding:1rem 0}#index-2 #m-stories .copy a.migration-button{border:1px solid #000;color:#000;display:block;padding:8px 0;text-align:center;text-decoration:none;width:60%}#index-2 #m-stories .copy a.migration-button:focus,#index-2 #m-stories .copy a.migration-button:hover{background-color:#fff;color:#000}#index-2 #m-stories .illustration .bg{position:absolute;right:20px}#index-2 #m-stories .illustration .fg{font-size:1.4rem;line-height:1.6rem;position:absolute;right:70px;width:370px}#index-2 .oss{width:100%}#index-2 .oss .icons{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-around;margin:0 auto;max-width:800px}@media screen and (-ms-high-contrast:black-on-white){#index-2 .oss .icons svg path{fill:#000}}@media screen and (-ms-high-contrast:white-on-black){#index-2 .oss .icons svg path{fill:#fff}}#index-2 .oss .icons svg{margin:0 auto}#index-2 .oss .icons a{color:#fff;display:flex;flex:1 1;flex-direction:column;height:145px;justify-content:space-between;margin:20px;max-width:140px;text-align:center;width:140px}#index-2 .oss .icons a p{padding-bottom:0}#index-2 .github-bar{opacity:0;position:absolute;transition:opacity .3s ease-out}#index-2 .github-bar.left{left:-200px}#index-2 .github-bar.right{right:-200px}#index-2 ul#videos{margin:0;padding:0}#index-2 ul#videos li{border-left:2px solid transparent;list-style:none;margin:0;padding:0}#index-2 ul#videos li.active{border-color:#000}#index-2 ul#videos li a{color:#000;display:block;font-size:1rem;margin-left:6px;text-decoration:none}#index-2 ul#videos li span{font-size:.8rem;font-style:italic}#index-2 .installation-panel .flat-button{background-color:#fff;color:#000;cursor:pointer;display:block;margin-top:20px;padding:1rem;text-decoration:none}@media screen and (-ms-high-contrast:active){#index-2 .installation-panel .flat-button{border:2px solid gray}}#index-2 .installation-panel .flat-button.focus,#index-2 .installation-panel .flat-button:hover{background-color:#eee}#index-2 .installation-panel .flat-button:active{background-color:#ddd}#index-2 .installation-panel .flat-button .fluid-button-title{font-weight:600}#index-2 .installation-panel .flat-button button{background-color:transparent;border:none;float:right}#index-2 .installation-panel .flat-button svg{float:right;height:.9em;margin-top:3px;opacity:.5;transition:opacity .2s linear;width:.9em}#index-2 .installation-panel .flat-button:hover svg{opacity:1}#index-2 .installation-panel .tooltip{background-color:#3f3f3f;border-radius:2px;color:#fff;display:none;font-family:var(--code-font);font-size:14px;padding:5px 8px;pointer-events:none;text-align:center;white-space:pre-wrap;z-index:100}#index-2 #adopt-gradually-content.fancy-scroll{height:1400px}#index-2 #adopt-gradually-content.fancy-scroll #adopt-step-slider{height:580px;position:sticky;top:80px}#index-2 #adopt-gradually-content.fancy-scroll #adopt-step-blurb,#index-2 #adopt-gradually-content.fancy-scroll #global-stepper{bottom:64px;left:0;margin:0 auto;max-width:480px;position:absolute;right:0}#index-2 #adopt-gradually-content.fancy-scroll #global-stepper{bottom:32px;display:flex}#index-2 #adopt-gradually-content.fancy-scroll #global-stepper>div{opacity:.2;transition:opacity .2s}#index-2 #adopt-gradually-content.fancy-scroll #global-stepper>div.active{opacity:1}#index-2 #adopt-gradually-content.fancy-scroll .adopt-step{left:0;margin-left:auto;margin-right:auto;padding-top:200px;position:absolute;right:0;top:0;transition:opacity .2s}#index-2 #adopt-gradually-content.fancy-scroll .adopt-step .adopt-step-stepper,#index-2 #adopt-gradually-content.fancy-scroll .adopt-step>div>p,#index-2 #global-stepper{display:none}#index-2 .adopt-step{margin:20px auto;max-width:480px;padding-top:120px}#index-2 .adopt-step pre{margin-bottom:10px}#index-2 .adopt-step>p{font-size:1rem;font-weight:700;margin:10px 0}#index-2 .adopt-step .tag-container p{font-size:1rem}#index-2 .adopt-step-stepper{display:flex;margin-bottom:80px}#index-2 .adopt-step-stepper div{border:1px solid #000;display:inline-block;flex:1 1;height:13px;margin-left:10px;position:relative}#index-2 .adopt-step-stepper div.yellow,#index-2 .adopt-step-stepper div.yellow-hint-blue,#index-2 .adopt-step-stepper div.yellow-lot-blue{background-color:#ffe200}#index-2 .adopt-step-stepper div.yellow-hint-blue:after,#index-2 .adopt-step-stepper div.yellow-lot-blue:after{background-color:#3178c6;content:"";height:13px;left:0;position:absolute;width:20%}#index-2 .adopt-step-stepper div.yellow-lot-blue:after{width:60%}#index-2 .adopt-step-stepper div.first{margin-left:0}#index-2 .via-delete .highlight{background-color:#fee}#index-2 .via-delete .dim{opacity:1}.yellow{background-color:#f1dd3f;color:#000;margin-bottom:-110px}.yellow .col1{align-self:stretch;width:50%}.yellow .col1 pre{height:220px;overflow:hidden}.yellow .col1 pre code{font-size:14px;line-height:16px}.yellow a{color:#000}.darkblue.dt{position:relative}.darkblue.dt .dark-blue-trans-bg{background-color:rgba(0,39,62,.77)}.darkblue.dt .dark-blue-trans-bg a{color:#fff}.darkblue.dt .dt-background{bottom:20px;font-family:var(--code-font);font-size:1.2rem;left:20px;opacity:.2;overflow:hidden;position:absolute;top:20px;width:80%}.flex-column{flex-direction:column}.fluid-button{background-color:#fff;color:#000;display:flex;padding:.5rem 1rem;text-decoration:none}.fluid-button .fluid-button-title{font-weight:600}.fluid-button div.fluid-button-icon{align-items:center;border-left:2px solid #000;display:flex;justify-content:center;margin-left:1rem;margin-right:-1rem;min-width:4rem;text-align:center}.fluid-button.focus,.fluid-button:hover{background-color:#eee}.fluid-button:active{background-color:#ddd}.cta .cta-back a{left:20px;position:relative;top:20px;width:60px}.transparent-button{border:1px solid #fff;color:#fff;cursor:pointer;left:20px;padding:10px;position:absolute;text-decoration:none;top:40px;width:80px}.transparent-button svg{margin-right:8px}.transparent-button.focus,.transparent-button:hover{background-color:hsla(0,0%,100%,.063)}.transparent-button:active{background-color:hsla(0,0%,100%,.125);border:1px solid hsla(0,0%,100%,.376)}.flow-links{display:flex;flex-wrap:wrap}.clicky-grey-button{background-color:#d8d8d8;color:#000;display:flex;flex-direction:column-reverse;height:10rem;margin-bottom:20px;margin-right:20px;padding:18px;position:relative;text-decoration:none;width:16rem}.clicky-grey-button.white-theme{background-color:#fff;border:1px solid #000}.clicky-grey-button.white-theme:hover{background-color:#eee}.clicky-grey-button.white-theme:active{background-color:#f2f2f2;margin-bottom:19px}@media screen and (-ms-high-contrast:active){.clicky-grey-button{border:1px solid gray}.clicky-grey-button svg path{fill:#fff}}.clicky-grey-button.headline{height:200px;width:300px}.clicky-grey-button.links{height:26rem}.clicky-grey-button.focus,.clicky-grey-button:hover{background-color:#ccc}.clicky-grey-button:active{background-color:#ddd}.clicky-grey-button p{color:#000}.clicky-grey-button div{color:#000;font-size:1.6rem;font-weight:400;line-height:1.6rem;margin-bottom:.2rem;text-decoration:none}.clicky-grey-button div:hover{text-decoration:none}.clicky-grey-button p{margin-bottom:0;margin-top:0}.clicky-grey-button a{text-decoration:none}.clicky-grey-button .badge{background-color:#666;position:absolute;right:10px;top:10px}.columns{display:flex;flex-direction:row;flex-wrap:wrap;margin:0 -2.6rem}.columns.wide{justify-content:space-between}.columns.wide .item{min-width:240px}.columns .item{flex:1 1;margin:.6rem;padding:1rem}.columns .item h4{margin-top:0}.columns .item ul{padding:0}.columns .item ul ul{margin-left:.5rem}.columns .item li{list-style:none;margin-left:0}@media(max-width:800px){.columns{flex-direction:column;margin:0}}div#like-dislike-subnav div{font-size:14px;padding-left:4px;padding-top:16px}div#like-dislike-subnav div button{align-items:center;background:none;border:none;color:var(--text-color);display:inline-flex;flex-direction:row}div#like-dislike-subnav div button svg{fill:var(--text-color);color:var(--text-color);margin-right:4px}#beta{background:repeating-linear-gradient(45deg,#9b9a4e,#9b9a4e 10px,#6e6a33 0,#6e6a33 20px);background-color:"#c63131";color:#fff;padding:4px 4px 6px;text-align:center;text-shadow:0 2px 4px #000}#doc-layout{display:flex;flex-direction:row}#handbook-content{margin:auto;max-width:1200px;min-width:0;padding:0 2rem}@media(max-width:480px){#handbook-content{padding:0}}#handbook-content>h1{font-size:3.5rem;font-weight:400;letter-spacing:0;line-height:3.5rem}@media(max-width:800px){#handbook-content>h1{font-size:2.5rem;margin-left:1rem;margin-right:1rem}}#handbook-content article{display:flex;flex-direction:row;width:100%}@media(max-width:999px){#handbook-content article{flex-direction:column}}#handbook-content .whitespace,#handbook-content .whitespace-tight{margin:0 auto 1rem;overflow:hidden;padding:2rem}@media(max-width:999px){#handbook-content .whitespace,#handbook-content .whitespace-tight{order:2}}#handbook-content .whitespace-tight{padding:1.2rem 2rem}#handbook-content aside{flex-shrink:0;margin-left:20px;width:13rem}@media(min-width:1000px){#handbook-content aside{display:block}}@media(max-width:999px){#handbook-content aside{margin-left:0;order:1;position:relative;top:0;width:100%;z-index:98}}#handbook-content aside nav{margin-bottom:1rem;position:sticky;top:30px}#handbook-content aside nav.deprecated{top:7rem}#handbook-content aside h5{font-size:16px;font-weight:600;margin:0}#handbook-content aside ul{padding:0}#handbook-content aside ul li{list-style:none}#handbook-content aside ul a{border-left:2px solid transparent;color:var(--alt-text-color);display:block;font-size:14px;font-weight:400;overflow:hidden;padding-left:8px;text-decoration:none;text-overflow:ellipsis;white-space:nowrap}#handbook-content aside ul a:active,#handbook-content aside ul a:hover{border-left:2px solid rgba(0,120,212,.3)}#handbook-content aside ul a.current{border-left:2px solid #0078d4}#handbook-content aside .like-dislike-subnav #dislike-button,#handbook-content aside .like-dislike-subnav #like-button{cursor:pointer}#handbook-content .preamble a{color:var(--text-color)}#handbook-content .justify-between{justify-content:space-between}#handbook-content a.navigation-link{flex:1 1;text-decoration:none}#handbook-content .prev-next{flex:1 1}#handbook-content .prev-next .arrow{align-items:center;display:flex;flex-direction:row;justify-content:center;margin-right:20px}#handbook-content .prev-next h3,#handbook-content .prev-next header,#handbook-content .prev-next p{margin:0;padding:0}#handbook-content .prev-next header{font-size:.8rem;margin-bottom:.5rem}#handbook-content .prev-next p{margin-bottom:.4rem}#handbook-content .prev-next header,#handbook-content .prev-next p{color:var(--text-color)}#handbook-content .prev-next:hover h3,#handbook-content .prev-next:hover svg path{fill:var(--text-color);color:var(--text-color)}#handbook-content .prev-next .nav-content{flex:1 1;padding-right:1rem}#handbook-content .prev-next.next{flex-direction:row-reverse;padding-left:1rem;padding-right:0;text-align:right}#handbook-content .prev-next.next .arrow{margin-left:20px;margin-right:0}#handbook-content .prev-next.next svg{transform:scaleX(-1)}#handbook-content .vertical-line{background-color:#e3e3e3;flex-basis:2px;flex-grow:0;flex-shrink:0;height:80px;min-width:2px}#handbook-content .docs-footer{border-top:1px solid var(--border-color);display:flex;flex-direction:row-reverse;height:2rem;margin:0 -2rem;padding:0}#handbook-content .docs-footer h5{font-weight:400;margin:0;padding:.5rem 1rem 0 0}#handbook-content .docs-footer button{align-items:center;background:none;border:none;border-left:1px solid var(--border-color);color:var(--text-color);cursor:pointer;display:inline-flex;flex-direction:row;padding:0 1rem}#handbook-content .docs-footer button:hover{background-color:var(--border-color)}#handbook-content .docs-footer button svg{fill:var(--text-color);color:var(--text-color);margin-right:4px}#handbook-content #deprecated-header{align-items:center;background-color:#fff4cf;color:#000;display:flex;justify-content:space-between;margin:0 -2rem;padding:1rem 2rem 1rem 0;position:sticky;top:0;z-index:1}#handbook-content #deprecated-header [id]:before{height:110px;margin-top:-110px}@media(max-width:800px){#handbook-content #deprecated-header{flex-direction:column;margin:0;padding:1rem}#handbook-content #deprecated-header h3{font-size:.8rem}#handbook-content #deprecated-header #deprecated-icon{margin-right:1rem}#handbook-content #deprecated-header #deprecated-action{margin-top:1rem}}#handbook-content #deprecated-header #deprecated-content{align-items:center;display:flex}#handbook-content #deprecated-header #deprecated-content #deprecated-icon{text-align:center;width:2rem}#handbook-content #deprecated-header h3{font-size:1.5rem;font-weight:400;margin-bottom:.5rem;margin-top:0}#handbook-content #deprecated-header p{margin-bottom:.2rem;margin-top:0}#handbook-content #deprecated-header #deprecated-action{flex-shrink:0}#handbook-content #deprecated-header #deprecated-action a{background-color:#fff;border:1px solid #000;color:#000;padding:.2rem .5rem;text-decoration:none}#handbook-content #deprecated-header #deprecated-action a:hover{background-color:#eee}#handbook-content .markdown table.cli-option{display:table}#handbook-content .markdown table.cli-option tr{width:100%}#handbook-content .markdown table.cli-option tr p{margin:0;padding:0}#handbook-content .markdown table.cli-option tr code{word-wrap:normal}#handbook-content .markdown table.cli-option tr.odd{background-color:var(--background-color)!important}#handbook-content .markdown table.cli-option tr.even{background-color:var(--background-minor-highlight-color)!important}#handbook-content .markdown table.cli-option ul{margin:0;padding:0}#handbook-content .markdown table.cli-option ul li{list-style:none;margin:0 0 8px}#handbook-content .markdown table.cli-option tr.option-description td{border-top:none;margin-top:0}.circle-bg{background-color:#719af4;color:#000;display:inline-block;line-height:31px;margin-right:3px;margin-top:12px;overflow:hidden;position:relative;text-align:center}.circle-bg,.circle-bg img{border-radius:16px;height:32px;width:32px}.circle-bg img{left:0;position:absolute;top:0}.bottom-section-content{flex:1 1;padding:1rem 2rem}@media(max-width:480px){.small-columns{flex-direction:column!important}}.inline-popup{background:var(--background-color);border-radius:2px;box-shadow:0 30px 90px -20px rgba(0,0,0,.3),0 0 1px 1px rgba(0,0,0,.05);font-size:14px;line-height:20px;max-width:400px;min-width:300px;padding:0;position:absolute;transition:opacity .5s;z-index:110}.inline-popup .inline-popup-container{display:flex}.inline-popup .inline-popup-container a.inline-popup-extract{color:var(--text-color);display:block;margin:16px;max-height:140px;overflow:hidden;position:relative;text-decoration:none}.inline-popup .inline-popup-container a.inline-popup-extract h5{margin-top:0}.inline-popup .inline-popup-container a.inline-popup-extract:after{background-color:transparent;bottom:0;content:" ";height:20px;pointer-events:none;position:absolute;width:25%}.inline-popup .inline-popup-container a.inline-popup-extract div{margin:0}.inline-popup .inline-popup-container a.inline-popup-extract div code{background-color:var(--inline-code-background-color);border-radius:2px;padding:2px 4px}.inline-popup.popup-fade-in{animation:.1s ease forwards}.handbook-on-this-page-section-list{max-height:80vh;overflow:auto}.handbook-on-this-page-section-list ul{padding-left:.5em!important}pre{background-color:#fff;border-bottom:1px solid #999;border-left:1px solid #999;color:#000;margin-bottom:3rem;overflow-x:auto;padding:12px;position:relative}pre.shiki{overflow-x:visible}pre.shiki:hover .dim{opacity:1}pre.shiki div.dim{opacity:.9}pre.shiki div.dim,pre.shiki div.highlight{margin:0;padding:0}pre.shiki div.highlight{background-color:#f1f8ff;opacity:1}pre.shiki div.line{min-height:1rem}pre.shiki .language-id{display:none}pre.twoslash{border-color:#719af4}pre.twoslash:hover data-lsp{border-color:#747474}pre.twoslash data-lsp:hover:before{background-color:#3f3f3f;border-radius:2px;color:#fff;content:attr(lsp);font-family:JetBrains Mono,Menlo,Monaco,Consolas,Courier New,monospace;font-size:14px;padding:5px 8px;position:absolute;text-align:left;transform:translateY(1rem);white-space:pre-wrap;z-index:100}pre .code-container{overflow:auto}pre .code-container>a{border:1px solid var(--link-color);border-radius:4px;bottom:8px;color:var(--link-color);opacity:0;padding:0 8px;position:absolute;right:8px;text-decoration:none;transition-timing-function:ease;transition:opacity .3s}@media(prefers-reduced-motion:reduce){pre .code-container>a{transition:none}}pre .code-container>a:focus,pre .code-container>a:hover{background-color:var(--link-color);color:#fff;opacity:1}pre .code-container:focus a,pre .code-container:hover a{opacity:1}pre code{-webkit-overflow-scrolling:touch;font-family:JetBrains Mono,Menlo,Monaco,Consolas,Courier New,monospace;font-size:15px;white-space:pre}pre code a{text-decoration:none}pre .query{color:#137998;display:inline-block;margin-bottom:10px}pre .error,pre .error-behind{display:block;margin-bottom:4px;margin-left:-14px;margin-top:8px;padding:6px 6px 6px 14px;white-space:pre-wrap;width:calc(100% - 20px)}pre .error{align-items:center;background-color:#fee;border-left:2px solid #bf1818;color:#000;display:flex;margin-right:-2px;position:absolute}pre .error .code{display:none}pre .error-behind{color:#fee;-webkit-user-select:none;user-select:none;visibility:transparent}pre .arrow{background-color:#eee;border-left:1px solid #eee;border-top:1px solid #eee;height:8px;margin-left:.1rem;position:relative;top:-7px;transform:translateY(25%) rotate(45deg);width:8px}pre .popover{background-color:#eee;border-radius:3px;display:inline-block;margin-bottom:10px;margin-top:10px;padding:0 .5rem .6rem}pre .inline-completions ul.dropdown{background-color:#e7e7e7;border-left:4px solid #4b9edd;color:#333;display:inline-block;font-family:var(--code-font);font-size:.8rem;margin:0;padding:0;position:absolute;width:240px}pre .inline-completions ul.dropdown:before{background-color:#4b9edd;content:" ";left:-3px;position:absolute;top:-1.2rem;width:2px}pre .inline-completions ul.dropdown li{margin-bottom:4px;overflow-x:hidden;padding-left:4px}pre .inline-completions ul.dropdown li.deprecated{text-decoration:line-through}pre .inline-completions ul.dropdown li span.result-found{color:#2265a5}pre .inline-completions ul.dropdown li span.result{color:#000;display:inline-block;width:100px}.dark-theme .markdown pre{background-color:#d8d8d8;border-color:#ddd;filter:invert(98%) hue-rotate(180deg)}data-lsp{border-bottom:1px dotted transparent;transition-timing-function:ease;transition:border-color .3s}@media(prefers-reduced-motion:reduce){data-lsp{transition:none}}.tag-container{position:relative}.tag-container .twoslash-annotation{color:#187abf;font-family:JetBrains Mono,Menlo,Monaco,Consolas,Courier New,monospace;position:absolute;right:-210px;width:200px}.tag-container .twoslash-annotation svg{float:left;margin-left:-44px}.tag-container .twoslash-annotation.left{left:-200px;right:auto}.tag-container .twoslash-annotation.left svg{float:right;margin-right:-5px}.markdown{scroll-behavior:smooth}.markdown h1,.markdown h2,.markdown h3{white-space-collapse:preserve;display:flex;flex-wrap:wrap;font-weight:400;line-height:1.3}.markdown h1 a,.markdown h2 a,.markdown h3 a{padding-right:10px!important}.markdown h1[id]:before,.markdown h2[id]:before,.markdown h3[id]:before{content:"";display:block;height:30px;margin-top:-30px;visibility:hidden}.markdown h1{word-wrap:break-word;font-size:2rem;margin-bottom:12px;margin-top:0;word-break:break-word}.markdown h2{font-size:1.75rem;margin-bottom:12px;margin-top:32px}.markdown h3{font-size:1.1875rem;margin-bottom:18px;margin-top:30px}.markdown pre{clear:both;top:10px}.markdown blockquote{background-color:var(--inline-code-background-color);border-left:2px solid var(--border-color);font-size:.8rem;margin:auto;padding:.1rem 2rem}.markdown blockquote.bg-reading{border-left:none;float:right;margin-left:.5rem}.markdown .language-id{display:none}.markdown table{border-collapse:separate;border-spacing:0;display:block;font-size:.875rem;max-width:100%;overflow-x:auto;table-layout:auto;width:100%}.markdown table.data{display:table}.markdown table.data td,.markdown table.data th,.markdown table.data tr{text-align:center}.markdown table td,.markdown table th{word-wrap:break-word;border:0;border-top:1px solid var(--border-color);display:table-cell;line-height:1.5;padding:.75rem 1rem;text-align:left;vertical-align:top}.markdown table tr:nth-child(2n){background-color:var(--background-minor-highlight-color)}.markdown table th{border-top:none}.markdown img{max-width:100%}.markdown div.table-container{overflow-x:auto}.markdown table.full-width-table{display:table;width:100%}.markdown .blue-tick{color:#3178c6;font-size:1.2rem;font-weight:700}.markdown .black-tick{color:#086f56;font-size:1.2rem}.markdown .red-cross{color:#c63131;font-size:1.2rem}#glossary ul.filterable-quicklinks{align-items:center;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:center}#glossary ul.filterable-quicklinks li{background-color:#e0e0e0;cursor:pointer;list-style:none;margin:.1rem;padding:.3rem;text-decoration:none}@media screen and (-ms-high-contrast:active){#glossary ul.filterable-quicklinks li{border:2px solid gray}}#glossary ul.filterable-quicklinks li.focus,#glossary ul.filterable-quicklinks li:hover{background-color:#cecece}#glossary ul.filterable-quicklinks li:active{background-color:#adadad}#glossary ul.filterable-quicklinks li a{color:#000;text-decoration:none}#glossary ul.filterable-quicklinks li a:visited{color:#505050}.cropper{background-color:#f9f6f6;display:block;height:500px;overflow:hidden;position:relative}.cropper img{margin-left:-50px}.cropper p{background:#fff;background:linear-gradient(0deg,#fff,hsla(0,0%,100%,.5));bottom:0;font-size:3rem;left:0;line-height:3rem;margin:0;padding-bottom:.8rem;padding-left:.8rem;position:absolute;width:100%}.dev-tools h3{margin:.6rem 0 0 1rem}@media(max-width:800px){.navbar-sub.dev-tools{height:auto}.navbar-sub.dev-tools .nav{flex-direction:column}}.examples{background-color:var(--playground-dropdown-bg);box-shadow:0 6px 12px rgba(0,0,0,.175);color:var(--text-color);height:450px;padding:20px}.examples a{color:var(--link-color)}.examples button.section-name{background-color:transparent;border:none;color:var(--text-color);font-size:2rem;font-weight:600;height:2.8rem;margin-right:1rem;margin-top:0;padding-bottom:.05rem;padding-top:0;text-decoration:none}.examples button.section-name.selected{border-bottom:2px solid #3178c6}.examples>ol{padding-left:0}.examples>ol li{display:inline-block;margin-bottom:20px;padding:0;width:auto}.examples>ol li:hover{background-color:transparent}.examples ol{list-style:none;padding-left:0;padding-right:20px}.examples>div.section-content{display:flex;flex-wrap:wrap}.examples>div.section-content>p>a{color:#3178c6;display:inline-block;padding:0}.examples>div.section-content .section-list{display:flex;flex-direction:column;margin-top:1.5em;width:280px}.examples>div.section-content .section-list h4{font-size:16px;font-weight:600;margin:0 0 8px}.examples>div.section-content .section-list ol li{margin:0;padding:0;position:relative;width:auto!important}.examples>div.section-content .section-list ol li .section-list a{border-bottom:none;display:block;font-size:14px;margin-left:-8px;padding:4px 4px 4px 10px;text-decoration:none}.examples>div.section-content .section-list ol li .section-list a:hover{color:#000}.examples>div.section-content .section-list ol li .section-list a.highlight{border-left:2px solid #235a97;padding-left:8px}.examples>div.section-content .section-list ol li .example-indicator{border-radius:.5rem;height:.5rem;margin-top:.3rem;position:absolute;right:.8rem;top:.75rem;width:.5rem}.examples>div.section-content .section-list ol li .example-indicator.done{background-color:#235a97}.examples>div.section-content .section-list ol li .example-indicator.changed{border:1px solid #235a97}.tsconfig{margin-bottom:6rem}@media(max-width:480px){.tsconfig.raised{margin:0;padding:2rem}.tsconfig.raised #full-option-list{padding:10px}.tsconfig.raised .indent{padding:1rem}}.tsconfig.button{margin-bottom:2rem}.tsconfig.button>a{display:block}.tsconfig.button svg{margin-right:.3rem;margin-top:.8rem}.tsconfig.button svg path{stroke:var(--text-color)}.tsconfig.button.closed svg{transform:rotate(270deg)}.tsconfig.button.open a{color:var(--text-color);text-decoration:none}.tsconfig .tsconfig-quick-nav{margin-left:-1rem;padding-left:1rem}.tsconfig .tsconfig-quick-nav.grouped{border-left:1px solid var(--text-color);margin-bottom:3rem}.tsconfig .tsconfig-quick-nav h4{font-weight:400;margin-bottom:.1rem}.tsconfig .tsconfig-quick-nav h4 a{color:var(--text-color)}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category{align-items:flex-start;display:flex}@media(max-width:900px){.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category{flex-direction:column}}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category h5{flex:0 0 auto;width:160px}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category ol{flex:1 1 auto;max-width:100%}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category li{display:inline-block;list-style:none;margin-left:8px}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category li a{color:var(--text-color);text-decoration:none}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category li a:hover{text-decoration:underline}.tsconfig .tsconfig-quick-nav .tsconfig-quick-nav-category li span{opacity:.8}.tsconfig article{width:100%}.tsconfig a[id]:before{content:"";display:block;height:80px;margin-top:-80px;scroll-margin-top:121px;visibility:hidden}.tsconfig .indent{padding:2rem}.tsconfig div#full-option-list{display:flex;flex-flow:row wrap}.tsconfig div#full-option-list div.tsconfig-nav-top{flex:auto;margin:0 8px 8px 0;width:30%}@media(max-width:480px){.tsconfig div#full-option-list div.tsconfig-nav-top{width:46%}.tsconfig div#full-option-list div.tsconfig-nav-top h5{overflow-x:hidden}}.tsconfig div#full-option-list div.tsconfig-nav-top h5 a{color:var(--text-color);font-size:2rem;font-weight:400;text-decoration:none}.tsconfig div#full-option-list div.tsconfig-nav-top ul{margin:0;padding:0}.tsconfig div#full-option-list div.tsconfig-nav-top li{font-family:var(--code-font);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.tsconfig div#full-option-list div.tsconfig-nav-top li a{color:var(--text-color)}.tsconfig nav{background-color:var(--raised-background-color);border-bottom:1px solid #d3d3d3;flex-direction:row;padding-bottom:10px;padding-top:4px;position:sticky;top:0;z-index:99999}.tsconfig nav,.tsconfig nav ul{display:flex;justify-content:center}.tsconfig nav ul{flex-wrap:wrap;margin:0}@media(max-width:800px){.tsconfig nav{position:static}.tsconfig nav ul{flex-wrap:wrap}.tsconfig nav li{min-width:120px}}.tsconfig nav a{text-decoration:none}.tsconfig nav a.current{border-bottom:1px solid #3178c6}.tsconfig nav li{display:block;margin:6px}.tsconfig .category{margin-bottom:40px;margin-top:80px}.tsconfig .category>h2>a:focus{background-color:#000;color:#fff;outline:none}.tsconfig .compiler-option{margin-bottom:80px}.tsconfig .compiler-option>h3{margin-bottom:0;offset-anchor:-30px;overflow-x:hidden}@media(max-width:800px){.tsconfig .compiler-option>h3{display:block;overflow-y:hidden}}.tsconfig .compiler-option>h3>a{scroll-margin-top:65px}.tsconfig .compiler-option>h3>a:focus{background-color:#000;color:#fff;outline:none}.tsconfig .compiler-option .compiler-content{display:flex}.tsconfig .compiler-option .compiler-content .markdown{word-wrap:break-word;border-right:1px solid gray;flex-shrink:1;padding-right:20px;width:calc(100% - 250px)}@media(max-width:480px){.tsconfig .compiler-option .compiler-content .markdown{border-right:none;padding-right:0}}.tsconfig .compiler-option .compiler-content ul.compiler-option-md{float:right;margin-left:20px;max-width:220px;min-width:200px;overflow-x:hidden;padding:0;width:220px}.tsconfig .compiler-option .compiler-content ul.compiler-option-md span{display:block;font-weight:600;width:100px}.tsconfig .compiler-option .compiler-content ul.compiler-option-md li{list-style:none;margin-bottom:12px}.tsconfig .compiler-option .compiler-content ul.compiler-option-md li ul{margin-bottom:18px;padding:0}.tsconfig .compiler-option .compiler-content ul.compiler-option-md li li{margin:0 0 12px}.tsconfig .compiler-option .compiler-content ul.compiler-option-md tr{padding:10px 0}.tsconfig .compiler-option .compiler-content ul.compiler-option-md li>p{display:inline-block;margin:0}@media(max-width:800px){.tsconfig .compiler-option .compiler-content{flex-direction:column}.tsconfig .compiler-option .compiler-content .markdown{width:100%}.tsconfig .compiler-option .compiler-content ul.compiler-option-md{margin-left:0;width:100%}}</style><link rel="icon" href="/favicon-32x32.png?v=8944a05a8b601855de116c8a56d3b3ae" type="image/png"/><link rel="manifest" href="/manifest.webmanifest" crossorigin="anonymous"/><link rel="apple-touch-icon" sizes="48x48" href="/icons/icon-48x48.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="72x72" href="/icons/icon-72x72.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="96x96" href="/icons/icon-96x96.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="144x144" href="/icons/icon-144x144.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="192x192" href="/icons/icon-192x192.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="256x256" href="/icons/icon-256x256.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="384x384" href="/icons/icon-384x384.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="apple-touch-icon" sizes="512x512" href="/icons/icon-512x512.png?v=8944a05a8b601855de116c8a56d3b3ae"/><link rel="sitemap" type="application/xml" href="/sitemap-index.xml"/><title data-react-helmet="true">TypeScript: Documentation - TypeScript 4.1</title><link data-react-helmet="true" rel="preload" href="/css/docsearch.css" as="style"/><link data-react-helmet="true" rel="preconnect" href="https://consentdeliveryfd.azurefd.net/"/><style data-react-helmet="true"> pre data-err { background:url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x 0 100%; padding-bottom: 3px; }</style><style type="text/css"> .anchor.before { position: absolute; top: 0; left: 0; transform: translateX(-100%); padding-right: 4px; } .anchor.after { display: inline-block; padding-left: 4px; } h1 .anchor svg, h2 .anchor svg, h3 .anchor svg, h4 .anchor svg, h5 .anchor svg, h6 .anchor svg { visibility: hidden; } h1:hover .anchor svg, h2:hover .anchor svg, h3:hover .anchor svg, h4:hover .anchor svg, h5:hover .anchor svg, h6:hover .anchor svg, h1 .anchor:focus svg, h2 .anchor:focus svg, h3 .anchor:focus svg, h4 .anchor:focus svg, h5 .anchor:focus svg, h6 .anchor:focus svg { visibility: visible; } </style><script> document.addEventListener("DOMContentLoaded", function(event) { var hash = window.decodeURI(location.hash.replace('#', '')) if (hash !== '') { var element = document.getElementById(hash) if (element) { var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop var clientTop = document.documentElement.clientTop || document.body.clientTop || 0 var offset = element.getBoundingClientRect().top + scrollTop - clientTop // Wait for the browser to finish rendering before scrolling. setTimeout((function() { window.scrollTo(0, offset - 0) }), 0) } } }) </script></head><body><script> (function() { let hasLocalStorage = false try { hasLocalStorage = typeof localStorage !== "undefined" } catch (error) {} const systemIsDark = typeof window !== 'undefined' && window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches const hasSetColorTheme = hasLocalStorage && localStorage.getItem("force-color-theme") const customThemeOverride = hasLocalStorage && localStorage.getItem("force-color-theme") if (!hasSetColorTheme && systemIsDark) { document.documentElement.classList.add("dark-theme") } else if (customThemeOverride) { document.documentElement.classList.add(customThemeOverride.replace("force-", "") + "-theme") } const customFontOverride = hasLocalStorage && localStorage.getItem("force-font") || "cascadia" document.documentElement.classList.add('font-' + customFontOverride) })() </script><div id="___gatsby"><div style="outline:none" tabindex="-1" id="gatsby-focus-wrapper"><div class="ms-Fabric"><div id="cookie-banner" class="openx"></div><header dir="ltr"><a class="skip-to-main" href="#handbook-content" tabindex="0">Skip to main content</a><div id="top-menu" class="up"><div class="left below-small"><a id="home-page-logo" aria-label="TypeScript Home Page" href="/"><svg fill="none" height="26" viewBox="0 0 27 26" width="27" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m.98608 0h24.32332c.5446 0 .9861.436522.9861.975v24.05c0 .5385-.4415.975-.9861.975h-24.32332c-.544597 0-.98608-.4365-.98608-.975v-24.05c0-.538478.441483-.975.98608-.975zm13.63142 13.8324v-2.1324h-9.35841v2.1324h3.34111v9.4946h2.6598v-9.4946zm1.0604 9.2439c.4289.2162.9362.3784 1.5218.4865.5857.1081 1.2029.1622 1.8518.1622.6324 0 1.2331-.0595 1.8023-.1784.5691-.1189 1.0681-.3149 1.497-.5879s.7685-.6297 1.0187-1.0703.3753-.9852.3753-1.6339c0-.4703-.0715-.8824-.2145-1.2365-.1429-.3541-.3491-.669-.6186-.9447-.2694-.2757-.5925-.523-.9692-.7419s-.8014-.4257-1.2743-.6203c-.3465-.1406-.6572-.2771-.9321-.4095-.275-.1324-.5087-.2676-.7011-.4054-.1925-.1379-.3409-.2838-.4454-.4379-.1045-.154-.1567-.3284-.1567-.523 0-.1784.0467-.3392.1402-.4824.0935-.1433.2254-.2663.3959-.369s.3794-.1824.6269-.2392c.2474-.0567.5224-.0851.8248-.0851.22 0 .4523.0162.697.0486.2447.0325.4908.0825.7382.15.2475.0676.4881.1527.7218.2555.2337.1027.4495.2216.6475.3567v-2.4244c-.4015-.1514-.84-.2636-1.3157-.3365-.4756-.073-1.0214-.1095-1.6373-.1095-.6268 0-1.2207.0662-1.7816.1987-.5609.1324-1.0544.3392-1.4806.6203s-.763.6392-1.0104 1.0743c-.2475.4352-.3712.9555-.3712 1.5609 0 .7731.2268 1.4326.6805 1.9785.4537.546 1.1424 1.0082 2.0662 1.3866.363.146.7011.2892 1.0146.4298.3134.1405.5842.2865.8124.4378.2282.1514.4083.3162.5403.4946s.198.3811.198.6082c0 .1676-.0413.323-.1238.4662-.0825.1433-.2076.2676-.3753.373s-.3766.1879-.6268.2473c-.2502.0595-.5431.0892-.8785.0892-.5719 0-1.1383-.0986-1.6992-.2959-.5608-.1973-1.0805-.4933-1.5589-.8879z" fill="#fff" fill-rule="evenodd"></path></svg><span class="hide-small">TypeScript</span></a><nav aria-label="top menu"><ul role="tablist" aria-owns="tab1 tab2 tab3 tab4 tab5 tab6" aria-busy="true"><li class="nav-item hide-small" role="none presentation"><a id="tab1" role="tab" href="/download/">Download</a></li><li class="nav-item" role="none presentation"><a id="tab2" role="tab" href="/docs/"><span>Docs</span></a></li><li class="nav-item show-only-large" role="none presentation"><a id="tab3" role="tab" href="/docs/handbook/intro.html">Handbook</a></li><li class="nav-item" role="none presentation"><a id="tab4" role="tab" href="/community/">Community</a></li><li class="nav-item show-only-largest" role="none presentation"><a id="tab5" role="tab" to="/play/" href="/play/">Playground</a></li><li class="nav-item" role="none presentation"><a id="tab6" role="tab" href="/tools/">Tools</a></li></ul></nav></div><div class="right above-small"><div class="search-section"><div id="my-lang-quick-jump" style="display:none" class="nav-item"><a href="">in En</a></div><div class="nav-item"><form id="search-form" class="search top-nav" role="search" aria-live="assertive"><svg fill="none" height="16" viewBox="0 0 16 16" width="16" xmlns="http://www.w3.org/2000/svg"><path d="m10.5 0c.5052 0 .9922.0651042 1.4609.195312.4688.130209.9063.315105 1.3125.554688.4063.239583.7761.52865 1.1094.86719.3386.33333.6276.70312.8672 1.10937s.4245.84375.5547 1.3125.1953.95573.1953 1.46094-.0651.99219-.1953 1.46094-.3151.90625-.5547 1.3125-.5286.77864-.8672 1.11718c-.3333.33334-.7031.61978-1.1094.85938-.4062.2396-.8437.4245-1.3125.5547-.4687.1302-.9557.1953-1.4609.1953-.65104 0-1.27604-.1094-1.875-.3281-.59375-.2188-1.14062-.5339-1.64062-.94534l-6.132818 6.12504c-.098958.0989-.216145.1484-.351562.1484s-.252604-.0495-.351562-.1484c-.0989588-.099-.148438-.2162-.148438-.3516s.0494792-.2526.148438-.3516l6.125002-6.13278c-.41146-.5-.72656-1.04687-.94532-1.64062-.21874-.59896-.32812-1.22396-.32812-1.875 0-.50521.0651-.99219.19531-1.46094s.31511-.90625.55469-1.3125.52604-.77604.85938-1.10937c.33854-.33854.71093-.627607 1.11718-.86719s.84375-.424479 1.3125-.554688c.46875-.1302078.95573-.195312 1.46094-.195312zm0 10c.6198 0 1.2031-.11719 1.75-.35156.5469-.23959 1.0234-.5625 1.4297-.96875.4062-.40625.7265-.88281.9609-1.42969.2396-.54688.3594-1.13021.3594-1.75s-.1198-1.20312-.3594-1.75c-.2344-.54688-.5547-1.02344-.9609-1.42969-.4063-.40625-.8828-.72656-1.4297-.96093-.5469-.23959-1.1302-.35938-1.75-.35938-.61979 0-1.20312.11979-1.75.35938-.54688.23437-1.02344.55468-1.42969.96093s-.72916.88281-.96875 1.42969c-.23437.54688-.35156 1.13021-.35156 1.75s.11719 1.20312.35156 1.75c.23959.54688.5625 1.02344.96875 1.42969s.88281.72916 1.42969.96875c.54688.23437 1.13021.35156 1.75.35156z" fill="#fff"></path></svg><span><input id="search-box-top" type="search" placeholder="Search Docs" aria-label="Search the TypeScript site"/></span><input type="submit" style="display:none"/></form></div></div></div></div><div id="site-content"></div></header><main role="main"><section id="doc-layout"><button id="small-device-button-sidebar"><svg fill="none" height="26" viewBox="0 0 26 26" width="26" xmlns="http://www.w3.org/2000/svg"><g fill="#fff"><path d="m0 1c0-.552285.447715-1 1-1h24c.5523 0 1 .447715 1 1v3h-26z"></path><path d="m0 11h13 13v4h-26z"></path><path d="m0 22h26v3c0 .5523-.4477 1-1 1h-24c-.552284 0-1-.4477-1-1z"></path></g></svg></button><div class="page-popup" id="page-helpful-popup" style="opacity:0;display:none"><p>Was this page helpful?</p><div><button class="first" id="like-button-popup" title="Like this page"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.052 2.29429C10.3913 1.31699 11.6841 0.866721 12.4829 1.70385C12.6455 1.87427 12.8081 2.05843 12.9176 2.22265C13.2379 2.70316 13.3725 3.33595 13.4218 3.95232C13.4721 4.58045 13.438 5.25457 13.3738 5.86484C13.3093 6.47746 13.2129 7.03959 13.1328 7.44777C13.1294 7.46547 13.1259 7.48288 13.1225 7.5H14.006C15.8777 7.5 17.2924 9.19514 16.9576 11.0367L16.2737 14.7984C15.8017 17.3943 13.2078 19.0291 10.6622 18.3348L5.06251 16.8076C4.14894 16.5585 3.45455 15.8145 3.26885 14.886L2.91581 13.1208C2.63809 11.7322 3.69991 10.5624 4.82905 10.1161C5.15163 9.98861 5.44337 9.82679 5.66974 9.62597C7.37583 8.11245 7.99442 6.90287 9.05406 4.77695C9.4084 4.06605 9.77205 3.10054 10.052 2.29429ZM12.0165 7.87862L12.0169 7.87707L12.0187 7.86973L12.0262 7.83863C12.0328 7.81079 12.0426 7.76903 12.0549 7.71494C12.0793 7.60669 12.1135 7.4493 12.1515 7.25536C12.2277 6.86666 12.3188 6.33504 12.3793 5.76016C12.4401 5.18293 12.4685 4.5758 12.425 4.03206C12.3806 3.47655 12.2652 3.04684 12.0855 2.77735C12.0264 2.6887 11.9138 2.55604 11.7594 2.39421C11.5605 2.18576 11.1314 2.23428 10.9967 2.62228C10.7141 3.43609 10.3334 4.45194 9.94904 5.22305C8.88216 7.36349 8.19326 8.72408 6.33336 10.374C5.99304 10.6759 5.58878 10.8911 5.19665 11.0461C4.31631 11.3941 3.75035 12.1945 3.89639 12.9247L4.24943 14.6899C4.36085 15.247 4.77748 15.6934 5.32562 15.8428L10.9254 17.3701C12.9052 17.91 14.9227 16.6385 15.2898 14.6195L15.9738 10.8578C16.197 9.63009 15.2538 8.5 14.006 8.5H12.5015C12.3476 8.5 12.2022 8.42906 12.1074 8.30771C12.0127 8.18638 11.9792 8.02796 12.0165 7.87862C12.0165 7.87858 12.0165 7.87866 12.0165 7.87862Z"></path></svg></button><button id="dislike-button-popup" title="Dislike this page"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.052 17.7057C10.3913 18.683 11.6841 19.1333 12.4829 18.2962C12.6455 18.1257 12.8081 17.9416 12.9176 17.7773C13.2379 17.2968 13.3725 16.664 13.4218 16.0477C13.4721 15.4195 13.438 14.7454 13.3738 14.1352C13.3093 13.5225 13.2129 12.9604 13.1328 12.5522C13.1294 12.5345 13.1259 12.5171 13.1225 12.5H14.006C15.8777 12.5 17.2924 10.8049 16.9576 8.96334L16.2737 5.20164C15.8017 2.60569 13.2078 0.970948 10.6622 1.66518L5.06251 3.19238C4.14894 3.44154 3.45455 4.18546 3.26885 5.11401L2.91581 6.87918C2.63809 8.26779 3.69991 9.43756 4.82905 9.88388C5.15163 10.0114 5.44337 10.1732 5.66974 10.374C7.37583 11.8875 7.99442 13.0971 9.05406 15.223C9.4084 15.9339 9.77205 16.8995 10.052 17.7057ZM12.0165 12.1214L12.0169 12.1229L12.0187 12.1303L12.0262 12.1614C12.0328 12.1892 12.0426 12.231 12.0549 12.2851C12.0793 12.3933 12.1135 12.5507 12.1515 12.7446C12.2277 13.1333 12.3188 13.665 12.3793 14.2398C12.4401 14.8171 12.4685 15.4242 12.425 15.9679C12.3806 16.5234 12.2652 16.9532 12.0855 17.2226C12.0264 17.3113 11.9138 17.444 11.7594 17.6058C11.5605 17.8142 11.1314 17.7657 10.9967 17.3777C10.7141 16.5639 10.3334 15.5481 9.94904 14.777C8.88216 12.6365 8.19326 11.2759 6.33336 9.62597C5.99304 9.32406 5.58878 9.1089 5.19665 8.9539C4.31631 8.60592 3.75035 7.80549 3.89639 7.0753L4.24943 5.31012C4.36085 4.753 4.77748 4.30664 5.32562 4.15715L10.9254 2.62995C12.9052 2.08999 14.9227 3.36145 15.2898 5.38052L15.9738 9.14222C16.197 10.3699 15.2538 11.5 14.006 11.5H12.5015C12.3476 11.5 12.2022 11.5709 12.1074 11.6923C12.0127 11.8136 11.9792 11.972 12.0165 12.1214C12.0165 12.1214 12.0165 12.1213 12.0165 12.1214Z"></path></svg></button></div></div><noscript><style> nav#sidebar > ul > li.closed ul { display: block !important; } </style></noscript><nav aria-label="sidebar" id="sidebar"><ul><li class="closed"><button aria-expanded="false">Get Started<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/typescript-from-scratch.html">TS for the New Programmer</a></li><li><a href="/docs/handbook/typescript-in-5-minutes.html">TypeScript for JS Programmers</a></li><li><a href="/docs/handbook/typescript-in-5-minutes-oop.html">TS for Java/C# Programmers</a></li><li><a href="/docs/handbook/typescript-in-5-minutes-func.html">TS for Functional Programmers</a></li><li><a href="/docs/handbook/typescript-tooling-in-5-minutes.html">TypeScript Tooling in 5 minutes</a></li></ul></li><li class="closed"><button aria-expanded="false">Handbook<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/intro.html">The TypeScript Handbook</a></li><li><a href="/docs/handbook/2/basic-types.html">The Basics</a></li><li><a href="/docs/handbook/2/everyday-types.html">Everyday Types</a></li><li><a href="/docs/handbook/2/narrowing.html">Narrowing</a></li><li><a href="/docs/handbook/2/functions.html">More on Functions</a></li><li><a href="/docs/handbook/2/objects.html">Object Types</a></li><li class="closed"><button aria-expanded="false">Type Manipulation<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/2/types-from-types.html">Creating Types from Types</a></li><li><a href="/docs/handbook/2/generics.html">Generics</a></li><li><a href="/docs/handbook/2/keyof-types.html">Keyof Type Operator</a></li><li><a href="/docs/handbook/2/typeof-types.html">Typeof Type Operator</a></li><li><a href="/docs/handbook/2/indexed-access-types.html">Indexed Access Types</a></li><li><a href="/docs/handbook/2/conditional-types.html">Conditional Types</a></li><li><a href="/docs/handbook/2/mapped-types.html">Mapped Types</a></li><li><a href="/docs/handbook/2/template-literal-types.html">Template Literal Types</a></li></ul></li><li><a href="/docs/handbook/2/classes.html">Classes</a></li><li><a href="/docs/handbook/2/modules.html">Modules</a></li></ul></li><li class="closed"><button aria-expanded="false">Reference<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/utility-types.html">Utility Types</a></li><li><a href="/cheatsheets/">Cheat Sheets</a></li><li><a href="/docs/handbook/decorators.html">Decorators</a></li><li><a href="/docs/handbook/declaration-merging.html">Declaration Merging</a></li><li><a href="/docs/handbook/enums.html">Enums</a></li><li><a href="/docs/handbook/iterators-and-generators.html">Iterators and Generators</a></li><li><a href="/docs/handbook/jsx.html">JSX</a></li><li><a href="/docs/handbook/mixins.html">Mixins</a></li><li><a href="/docs/handbook/namespaces.html">Namespaces</a></li><li><a href="/docs/handbook/namespaces-and-modules.html">Namespaces and Modules</a></li><li><a href="/docs/handbook/symbols.html">Symbols</a></li><li><a href="/docs/handbook/triple-slash-directives.html">Triple-Slash Directives</a></li><li><a href="/docs/handbook/type-compatibility.html">Type Compatibility</a></li><li><a href="/docs/handbook/type-inference.html">Type Inference</a></li><li><a href="/docs/handbook/variable-declarations.html">Variable Declaration</a></li></ul></li><li class="closed"><button aria-expanded="false">Modules Reference<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/modules/introduction.html">Introduction</a></li><li><a href="/docs/handbook/modules/theory.html">Theory</a></li><li class="closed"><button aria-expanded="false">Guides<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/modules/guides/choosing-compiler-options.html">Choosing Compiler Options</a></li></ul></li><li><a href="/docs/handbook/modules/reference.html">Reference</a></li><li class="closed"><button aria-expanded="false">Appendices<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/modules/appendices/esm-cjs-interop.html">ESM/CJS Interoperability</a></li></ul></li></ul></li><li class="closed"><button aria-expanded="false">Tutorials<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/asp-net-core.html">ASP.NET Core</a></li><li><a href="/docs/handbook/gulp.html">Gulp</a></li><li><a href="/docs/handbook/dom-manipulation.html">DOM Manipulation</a></li><li><a href="/docs/handbook/migrating-from-javascript.html">Migrating from JavaScript</a></li><li><a href="/docs/handbook/babel-with-typescript.html">Using Babel with TypeScript</a></li></ul></li><li class="open highlighted"><button aria-expanded="true">What's New<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/release-notes/typescript-5-7.html">TypeScript 5.7</a></li><li><a href="/docs/handbook/release-notes/typescript-5-6.html">TypeScript 5.6</a></li><li><a href="/docs/handbook/release-notes/typescript-5-5.html">TypeScript 5.5</a></li><li><a href="/docs/handbook/release-notes/typescript-5-4.html">TypeScript 5.4</a></li><li><a href="/docs/handbook/release-notes/typescript-5-3.html">TypeScript 5.3</a></li><li><a href="/docs/handbook/release-notes/typescript-5-2.html">TypeScript 5.2</a></li><li><a href="/docs/handbook/release-notes/typescript-5-1.html">TypeScript 5.1</a></li><li><a href="/docs/handbook/release-notes/typescript-5-0.html">TypeScript 5.0</a></li><li><a href="/docs/handbook/release-notes/typescript-4-9.html">TypeScript 4.9</a></li><li><a href="/docs/handbook/release-notes/typescript-4-8.html">TypeScript 4.8</a></li><li><a href="/docs/handbook/release-notes/typescript-4-7.html">TypeScript 4.7</a></li><li><a href="/docs/handbook/release-notes/typescript-4-6.html">TypeScript 4.6</a></li><li><a href="/docs/handbook/release-notes/typescript-4-5.html">TypeScript 4.5</a></li><li><a href="/docs/handbook/release-notes/typescript-4-4.html">TypeScript 4.4</a></li><li><a href="/docs/handbook/release-notes/typescript-4-3.html">TypeScript 4.3</a></li><li><a href="/docs/handbook/release-notes/typescript-4-2.html">TypeScript 4.2</a></li><li aria-current="page" class="highlight"><a aria-current="page" class="" href="/docs/handbook/release-notes/typescript-4-1.html">TypeScript 4.1</a></li><li><a href="/docs/handbook/release-notes/typescript-4-0.html">TypeScript 4.0</a></li><li><a href="/docs/handbook/release-notes/typescript-3-9.html">TypeScript 3.9</a></li><li><a href="/docs/handbook/release-notes/typescript-3-8.html">TypeScript 3.8</a></li><li><a href="/docs/handbook/release-notes/typescript-3-7.html">TypeScript 3.7</a></li><li><a href="/docs/handbook/release-notes/typescript-3-6.html">TypeScript 3.6</a></li><li><a href="/docs/handbook/release-notes/typescript-3-5.html">TypeScript 3.5</a></li><li><a href="/docs/handbook/release-notes/typescript-3-4.html">TypeScript 3.4</a></li><li><a href="/docs/handbook/release-notes/typescript-3-3.html">TypeScript 3.3</a></li><li><a href="/docs/handbook/release-notes/typescript-3-2.html">TypeScript 3.2</a></li><li><a href="/docs/handbook/release-notes/typescript-3-1.html">TypeScript 3.1</a></li><li><a href="/docs/handbook/release-notes/typescript-3-0.html">TypeScript 3.0</a></li><li><a href="/docs/handbook/release-notes/typescript-2-9.html">TypeScript 2.9</a></li><li><a href="/docs/handbook/release-notes/typescript-2-8.html">TypeScript 2.8</a></li><li><a href="/docs/handbook/release-notes/typescript-2-7.html">TypeScript 2.7</a></li><li><a href="/docs/handbook/release-notes/typescript-2-6.html">TypeScript 2.6</a></li><li><a href="/docs/handbook/release-notes/typescript-2-5.html">TypeScript 2.5</a></li><li><a href="/docs/handbook/release-notes/typescript-2-4.html">TypeScript 2.4</a></li><li><a href="/docs/handbook/release-notes/typescript-2-3.html">TypeScript 2.3</a></li><li><a href="/docs/handbook/release-notes/typescript-2-2.html">TypeScript 2.2</a></li><li><a href="/docs/handbook/release-notes/typescript-2-1.html">TypeScript 2.1</a></li><li><a href="/docs/handbook/release-notes/typescript-2-0.html">TypeScript 2.0</a></li><li><a href="/docs/handbook/release-notes/typescript-1-8.html">TypeScript 1.8</a></li><li><a href="/docs/handbook/release-notes/typescript-1-7.html">TypeScript 1.7</a></li><li><a href="/docs/handbook/release-notes/typescript-1-6.html">TypeScript 1.6</a></li><li><a href="/docs/handbook/release-notes/typescript-1-5.html">TypeScript 1.5</a></li><li><a href="/docs/handbook/release-notes/typescript-1-4.html">TypeScript 1.4</a></li><li><a href="/docs/handbook/release-notes/typescript-1-3.html">TypeScript 1.3</a></li><li><a href="/docs/handbook/release-notes/typescript-1-1.html">TypeScript 1.1</a></li></ul></li><li class="closed"><button aria-expanded="false">Declaration Files<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/declaration-files/introduction.html">Introduction</a></li><li><a href="/docs/handbook/declaration-files/by-example.html">Declaration Reference</a></li><li><a href="/docs/handbook/declaration-files/library-structures.html">Library Structures</a></li><li class="closed"><button aria-expanded="false">.d.ts Templates<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/declaration-files/templates/module-d-ts.html">Modules .d.ts</a></li><li><a href="/docs/handbook/declaration-files/templates/module-plugin-d-ts.html">Module: Plugin</a></li><li><a href="/docs/handbook/declaration-files/templates/module-class-d-ts.html">Module: Class</a></li><li><a href="/docs/handbook/declaration-files/templates/module-function-d-ts.html">Module: Function</a></li><li><a href="/docs/handbook/declaration-files/templates/global-d-ts.html">Global .d.ts</a></li><li><a href="/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html">Global: Modifying Module</a></li></ul></li><li><a href="/docs/handbook/declaration-files/do-s-and-don-ts.html">Do's and Don'ts</a></li><li><a href="/docs/handbook/declaration-files/deep-dive.html">Deep Dive</a></li><li><a href="/docs/handbook/declaration-files/publishing.html">Publishing</a></li><li><a href="/docs/handbook/declaration-files/consumption.html">Consumption</a></li></ul></li><li class="closed"><button aria-expanded="false">JavaScript<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/intro-to-js-ts.html">JS Projects Utilizing TypeScript</a></li><li><a href="/docs/handbook/type-checking-javascript-files.html">Type Checking JavaScript Files</a></li><li><a href="/docs/handbook/jsdoc-supported-types.html">JSDoc Reference</a></li><li><a href="/docs/handbook/declaration-files/dts-from-js.html">Creating .d.ts Files from .js files</a></li></ul></li><li class="closed"><button aria-expanded="false">Project Configuration<span class="open"><svg fill="none" height="9" viewBox="0 0 14 9" width="14" xmlns="http://www.w3.org/2000/svg"><path d="m1 1 6 6 6-6" stroke="#000" stroke-width="2"></path></svg></span><span class="closed"><svg fill="none" height="14" viewBox="0 0 9 14" width="9" xmlns="http://www.w3.org/2000/svg"><path d="m1 13 6-6-6-6" stroke="#000" stroke-width="2"></path></svg></span></button><ul><li><a href="/docs/handbook/tsconfig-json.html">What is a tsconfig.json</a></li><li><a href="/docs/handbook/compiler-options-in-msbuild.html">Compiler Options in MSBuild</a></li><li><a href="/tsconfig/">TSConfig Reference</a></li><li><a href="/docs/handbook/compiler-options.html">tsc CLI Options</a></li><li><a href="/docs/handbook/project-references.html">Project References</a></li><li><a href="/docs/handbook/integrating-with-build-tools.html">Integrating with Build Tools</a></li><li><a href="/docs/handbook/configuring-watch.html">Configuring Watch</a></li><li><a href="/docs/handbook/nightly-builds.html">Nightly Builds</a></li></ul></li></ul></nav><div id="handbook-content" role="article"><h1>TypeScript 4.1</h1><article><div class="whitespace raised"><div class="markdown"><h2 id="template-literal-types" style="position:relative;"><a href="#template-literal-types" aria-label="template literal 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>Template Literal Types</h2> <p>String literal types in TypeScript allow us to model functions and APIs that expect a set of specific strings.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26"><data-lsp lsp='function setVerticalAlignment(location: "top" | "middle" | "bottom"): void' >setVerticalAlignment</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) location: "top" | "middle" | "bottom"' >location</data-lsp></span><span style="color: #000000">: </span><span style="color: #A31515">"top"</span><span style="color: #000000"> | </span><span style="color: #A31515">"middle"</span><span style="color: #000000"> | </span><span style="color: #A31515">"bottom"</span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// ...</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'> </div><div class='line'><span style="color: #795E26"><data-lsp lsp='function setVerticalAlignment(location: "top" | "middle" | "bottom"): void' >setVerticalAlignment</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515"><data-err>"middel"</data-err></span><span style="color: #000000">);</span></div><span class="error"><span>Argument of type '"middel"' is not assignable to parameter of type '"top" | "middle" | "bottom"'.</span><span class="code">2345</span></span><span class="error-behind">Argument of type '"middel"' is not assignable to parameter of type '"top" | "middle" | "bottom"'.</span></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAGYCuAdgMYAuAlnCaIpBQGozVkCGANgIKdUDmJALaQSFABSc4HarVQAiCnAAO80AB9Q8oVQAmuzpDWb5AIzgUlQ+QEpQAbzyhQIUADoPeAL548DZqxUHDx8giJi4tp6upCctgDcQA'>Try</a></div></pre> <p>This is pretty nice because string literal types can basically spell-check our string values.</p> <p>We also like that string literals can be used as property names in mapped types. In this sense, they’re also usable as building blocks:</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">Options</span><span style="color: #000000"> = {</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #1C6277">K</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #A31515">"noImplicitAny"</span><span style="color: #000000"> | </span><span style="color: #A31515">"strictNullChecks"</span><span style="color: #000000"> | </span><span style="color: #A31515">"strictFunctionTypes"</span><span style="color: #000000">]?: </span><span style="color: #1C6277">boolean</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">};</span></div><div class='line'><span style="color: #008000">// same as</span></div><div class='line'><span style="color: #008000">// type Options = {</span></div><div class='line'><span style="color: #008000">// noImplicitAny?: boolean,</span></div><div class='line'><span style="color: #008000">// strictNullChecks?: boolean,</span></div><div class='line'><span style="color: #008000">// strictFunctionTypes?: boolean</span></div><div class='line'><span style="color: #008000">// };</span></div></code></div></pre> <p>But there’s another place that string literal types could be used as building blocks: building other string literal types.</p> <p>That’s why TypeScript 4.1 brings the template literal string type. It has the same syntax as <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals">template literal strings in JavaScript</a>, but is used in type positions. When you use it with concrete literal types, it produces a new string literal type by concatenating the contents.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type World = "world"' >World</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">"world"</span><span style="color: #000000">;</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type Greeting = "hello world"' style='border-bottom: solid 2px lightgrey;'>Greeting</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">`hello </span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='type World = "world"' >World</data-lsp></span><span style="color: #0000FF">}</span><span style="color: #A31515">`</span><span style="color: #000000">;</span></div><div class='meta-line'><span class='popover-prefix'> </span><span class='popover'><div class='arrow'></div>type Greeting = "hello world"</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/C4TwDgpgBA6g9gJwDYBMoF4oCIDujVYDcAUMaJFAOIIQTACWAdgOYZQAGAFhEknFABIA3vGQoAvuxIB6aVHkA9APxA'>Try</a></div></pre> <p>What happens when you have unions in substitution positions? It produces the set of every possible string literal that could be represented by each union member.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type Color = "red" | "blue"' >Color</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">"red"</span><span style="color: #000000"> | </span><span style="color: #A31515">"blue"</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type Quantity = "one" | "two"' >Quantity</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">"one"</span><span style="color: #000000"> | </span><span style="color: #A31515">"two"</span><span style="color: #000000">;</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type SeussFish = "red fish" | "blue fish" | "one fish" | "two fish"' >SeussFish</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">`</span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='type Quantity = "one" | "two"' >Quantity</data-lsp></span><span style="color: #000000FF"> </span><span style="color: #000000">|</span><span style="color: #000000FF"> </span><span style="color: #1C6277"><data-lsp lsp='type Color = "red" | "blue"' >Color</data-lsp></span><span style="color: #0000FF">}</span><span style="color: #A31515"> fish`</span><span style="color: #000000">;</span></div><div class='meta-line'><span class='popover-prefix'></span><span class='popover'><div class='arrow'></div>type SeussFish = "one fish" | "two fish" | "red fish" | "blue fish"</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAwg9gGzgJygXigImRAJpqAHywCMEBXCTAbgChRIoBFcgQwDtgBLUdLOdlSJZgAdzg1a9cNADKEcgGdFAMS6KAFnwAGAEgDeLDt17F4SZAF8oAM3UbtdAPROobgHoB+IA'>Try</a></div></pre> <p>This can be used beyond cute examples in release notes. For example, several libraries for UI components have a way to specify both vertical and horizontal alignment in their APIs, often with both at once using a single string like <code>"bottom-right"</code>. Between vertically aligning with <code>"top"</code>, <code>"middle"</code>, and <code>"bottom"</code>, and horizontally aligning with <code>"left"</code>, <code>"center"</code>, and <code>"right"</code>, there are 9 possible strings where each of the former strings is connected with each of the latter strings using a dash.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type VerticalAlignment = "top" | "middle" | "bottom"' >VerticalAlignment</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">"top"</span><span style="color: #000000"> | </span><span style="color: #A31515">"middle"</span><span style="color: #000000"> | </span><span style="color: #A31515">"bottom"</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type HorizontalAlignment = "left" | "center" | "right"' >HorizontalAlignment</data-lsp></span><span style="color: #000000"> = </span><span style="color: #A31515">"left"</span><span style="color: #000000"> | </span><span style="color: #A31515">"center"</span><span style="color: #000000"> | </span><span style="color: #A31515">"right"</span><span style="color: #000000">;</span></div><div class='line'> </div><div class='line'><span style="color: #008000">// Takes</span></div><div class='line'><span style="color: #008000">// | "top-left" | "top-center" | "top-right"</span></div><div class='line'><span style="color: #008000">// | "middle-left" | "middle-center" | "middle-right"</span></div><div class='line'><span style="color: #008000">// | "bottom-left" | "bottom-center" | "bottom-right"</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">declare</span><span style="color: #000000"> </span><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26"><data-lsp lsp='function setAlignment(value: `${VerticalAlignment}-${HorizontalAlignment}`): void' >setAlignment</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) value: "top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right"' >value</data-lsp></span><span style="color: #000000">: </span><span style="color: #A31515">`</span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='type VerticalAlignment = "top" | "middle" | "bottom"' >VerticalAlignment</data-lsp></span><span style="color: #0000FF">}</span><span style="color: #A31515">-</span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='type HorizontalAlignment = "left" | "center" | "right"' >HorizontalAlignment</data-lsp></span><span style="color: #0000FF">}</span><span style="color: #A31515">`</span><span style="color: #000000">): </span><span style="color: #1C6277">void</span><span style="color: #000000">;</span></div><div class='line'> </div><div class='line'><span style="color: #795E26"><data-lsp lsp='function setAlignment(value: `${VerticalAlignment}-${HorizontalAlignment}`): void' >setAlignment</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515">"top-left"</span><span style="color: #000000">); </span><span style="color: #008000">// works!</span></div><div class='line'><span style="color: #795E26"><data-lsp lsp='function setAlignment(value: `${VerticalAlignment}-${HorizontalAlignment}`): void' >setAlignment</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515"><data-err>"top-middel"</data-err></span><span style="color: #000000">); </span><span style="color: #008000">// error!</span></div><span class="error"><span>Argument of type '"top-middel"' is not assignable to parameter of type '"top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right"'.</span><span class="code">2345</span></span><span class="error-behind">Argument of type '"top-middel"' is not assignable to parameter of type '"top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right"'.</span><div class='line'><span style="color: #795E26"><data-lsp lsp='function setAlignment(value: `${VerticalAlignment}-${HorizontalAlignment}`): void' >setAlignment</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515"><data-err>"top-pot"</data-err></span><span style="color: #000000">); </span><span style="color: #008000">// error! but good doughnuts if you're ever in Seattle</span></div><span class="error"><span>Argument of type '"top-pot"' is not assignable to parameter of type '"top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right"'.</span><span class="code">2345</span></span><span class="error-behind">Argument of type '"top-pot"' is not assignable to parameter of type '"top-left" | "top-center" | "top-right" | "middle-left" | "middle-center" | "middle-right" | "bottom-left" | "bottom-center" | "bottom-right"'.</span></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAC4CeADpKAGowECWAxgIYA2AgkzQOYB2AtpFwVABeUACICcEqNAAfMTxoATRU0jS5ogEZwCEnqIDchUuQASCGgC84A5m069+gkaNUAzAurF0nML6OhOAAtPIzwQUAAVBgBrSERwsFBZMQkSAFp3T2TkjTT0nwE-HJTxSXTAjhDRRJyNBWVVTMgPfwaVSALfaDalDorgz1rcsW1dOB5m1tKxvS6inpmdOcrqvDxFSDomBmhyNwBXLjpaG1BESAJ7bj4BAAoAN2YDyFQAAwASAG8qaFpGVjsG5OAC+6W+5kC1lsgIctwIILeAEpUA84EowhcrkDHPcyhksqIkQYchEAO4IGKIACEeCx11xBDu+PS7UgTCJJIiMHg0Fp9Jx8OZ+RIOk5JW5sAQ1NAmgOgg4cDgilAijgByqXHliFANDcoCI6oA5HtQJAHjBdVxQABlSAMXSqIA'>Try</a></div></pre> <p>While there are <strong>lots</strong> of examples of this sort of API in the wild, this is still a bit of a toy example since we could write these out manually. In fact, for 9 strings, this is likely fine; but when you need a ton of strings, you should consider automatically generating them ahead of time to save work on every type-check (or just use <code>string</code>, which will be much simpler to comprehend).</p> <p>Some of the real value comes from dynamically creating new string literals. For example, imagine a <code>makeWatchedObject</code> API that takes an object and produces a mostly identical object, but with a new <code>on</code> method to detect for changes to the properties.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #001080">person</span><span style="color: #000000"> = </span><span style="color: #795E26">makeWatchedObject</span><span style="color: #000000">({</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">firstName:</span><span style="color: #000000"> </span><span style="color: #A31515">"Homer"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">age:</span><span style="color: #000000"> </span><span style="color: #098658">42</span><span style="color: #000000">, </span><span style="color: #008000">// give-or-take</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">location:</span><span style="color: #000000"> </span><span style="color: #A31515">"Springfield"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000">});</span></div><div class='line'></div><div class='line'><span style="color: #001080">person</span><span style="color: #000000">.</span><span style="color: #795E26">on</span><span style="color: #000000">(</span><span style="color: #A31515">"firstNameChanged"</span><span style="color: #000000">, () </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">console</span><span style="color: #000000">.</span><span style="color: #795E26">log</span><span style="color: #000000">(</span><span style="color: #A31515">`firstName was changed!`</span><span style="color: #000000">);</span></div><div class='line'><span style="color: #000000">});</span></div></code></div></pre> <p>Notice that <code>on</code> listens on the event <code>"firstNameChanged"</code>, not just <code>"firstName"</code>. How would we type this?</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000" twslash="true"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">PropEventSource</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">> = {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">on</span><span style="color: #000000">(</span><span style="color: #001080">eventName</span><span style="color: #000000">: </span><span style="color: #A31515">`</span><span style="color: #0000FF">${</span><span style="color: #1C6277">string</span><span style="color: #000000FF"> </span><span style="color: #000000">&</span><span style="color: #000000FF"> </span><span style="color: #0000FF">keyof</span><span style="color: #000000FF"> </span><span style="color: #1C6277">T</span><span style="color: #0000FF">}</span><span style="color: #A31515">Changed`</span><span style="color: #000000">, </span><span style="color: #795E26">callback</span><span style="color: #000000">: () </span><span style="color: #0000FF">=></span><span style="color: #000000"> </span><span style="color: #1C6277">void</span><span style="color: #000000">): </span><span style="color: #1C6277">void</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">};</span></div><div class='line'></div><div class='line'><span style="color: #008000">/// Create a "watched object" with an 'on' method</span></div><div class='line'><span style="color: #008000">/// so that you can watch for changes to properties.</span></div><div class='line'><span style="color: #0000FF">declare</span><span style="color: #000000"> </span><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">makeWatchedObject</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">>(</span><span style="color: #001080">obj</span><span style="color: #000000">: </span><span style="color: #1C6277">T</span><span style="color: #000000">): </span><span style="color: #1C6277">T</span><span style="color: #000000"> & </span><span style="color: #1C6277">PropEventSource</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">>;</span></div></code></div></pre> <p>With this, we can build something that errors when we give the wrong property!</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #008000">// error!</span></div><div class='line'><span style="color: #001080"><data-lsp lsp='let person: { firstName: string; age: number; location: string; } & PropEventSource<{ firstName: string; age: number; location: string; }>' >person</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) on(eventName: "firstNameChanged" | "ageChanged" | "locationChanged", callback: () => void): void' >on</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515"><data-err>"firstName"</data-err></span><span style="color: #000000">, () </span><span style="color: #0000FF">=></span><span style="color: #000000"> {});</span></div><span class="error"><span>Argument of type '"firstName"' is not assignable to parameter of type '"firstNameChanged" | "ageChanged" | "locationChanged"'.</span><span class="code">2345</span></span><span class="error-behind">Argument of type '"firstName"' is not assignable to parameter of type '"firstNameChanged" | "ageChanged" | "locationChanged"'.</span><div class='line'> </div><div class='line'><span style="color: #008000">// error!</span></div><div class='line'><span style="color: #001080"><data-lsp lsp='let person: { firstName: string; age: number; location: string; } & PropEventSource<{ firstName: string; age: number; location: string; }>' >person</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) on(eventName: "firstNameChanged" | "ageChanged" | "locationChanged", callback: () => void): void' >on</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515"><data-err>"frstNameChanged"</data-err></span><span style="color: #000000">, () </span><span style="color: #0000FF">=></span><span style="color: #000000"> {});</span></div><span class="error"><span>Argument of type '"frstNameChanged"' is not assignable to parameter of type '"firstNameChanged" | "ageChanged" | "locationChanged"'.</span><span class="code">2345</span></span><span class="error-behind">Argument of type '"frstNameChanged"' is not assignable to parameter of type '"firstNameChanged" | "ageChanged" | "locationChanged"'.</span></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwGYAsBWAUAC4CeADpKAArwkCiAbpAHYEDKcArtAMaQA8AKgD5QAXlABvPKGmg4jABSQGzAHIBDALaRUAAwAk4xAWgBLRgHNQAMlABrSETgAzUPwC+AYQAWai5AAmOgA0oFxqADbhAEZqXLao8gCUosJ0cCb+iahpGQDceG75-pBc4WrQ5E7sjFwEJnKgGmr2AOpqBFxeAQDyUQBWJQQCgvJw-aj8Wa7WlNT0TKwc3HxC+eGQBKBkSA1iTa3tnT39g-KS0k4mSATqWqgARAAScFrQ90FSoGrm2qBYaCEQKBzCYGABaBBggjNSCfcJwMJ1OQPFgkUwWS6QcL+d4FRL5PBAsHErjsAjEsGEsAweDQACEeG2iDkADo5PJ7pdrrdIO9QEkUhI3Pi8FTQDSEAymaz2ZzuZpIN5fD8cSEBSJhOJhbkgA'>Try</a></div></pre> <p>We can also do something special in template literal types: we can <em>infer</em> from substitution positions. We can make our last example generic to infer from parts of the <code>eventName</code> string to figure out the associated property.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type PropEventSource<T> = { on<K extends string & keyof T>(eventName: `${K}Changed`, callback: (newValue: T[K]) => void): void; }' >PropEventSource</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type PropEventSource<T>' >T</data-lsp></span><span style="color: #000000">> = {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='(method) on<K extends string & keyof T>(eventName: `${K}Changed`, callback: (newValue: T[K]) => void): void' >on</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K in on<K extends string & keyof T>(eventName: `${K}Changed`, callback: (newValue: T[K]) => void): void' >K</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">extends</span><span style="color: #000000"> </span><span style="color: #1C6277">string</span><span style="color: #000000"> & </span><span style="color: #0000FF">keyof</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type PropEventSource<T>' >T</data-lsp></span><span style="color: #000000">></span></div><div class='line'><span style="color: #000000"> (</span><span style="color: #001080"><data-lsp lsp='(parameter) eventName: `${K}Changed`' >eventName</data-lsp></span><span style="color: #000000">: </span><span style="color: #A31515">`</span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K in on<K extends string & keyof T>(eventName: `${K}Changed`, callback: (newValue: T[K]) => void): void' >K</data-lsp></span><span style="color: #0000FF">}</span><span style="color: #A31515">Changed`</span><span style="color: #000000">, </span><span style="color: #795E26"><data-lsp lsp='(parameter) callback: (newValue: T[K]) => void' >callback</data-lsp></span><span style="color: #000000">: (</span><span style="color: #001080"><data-lsp lsp='(parameter) newValue: T[K]' >newValue</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type PropEventSource<T>' >T</data-lsp></span><span style="color: #000000">[</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K in on<K extends string & keyof T>(eventName: `${K}Changed`, callback: (newValue: T[K]) => void): void' >K</data-lsp></span><span style="color: #000000">]) </span><span style="color: #0000FF">=></span><span style="color: #000000"> </span><span style="color: #1C6277">void</span><span style="color: #000000"> ): </span><span style="color: #1C6277">void</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">};</span></div><div class='line'> </div><div class='line'><span style="color: #1C6277">declare</span><span style="color: #000000"> </span><span style="color: #1C6277">function</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='function makeWatchedObject<T>(obj: T): T & PropEventSource<T>' >makeWatchedObject</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in makeWatchedObject<T>(obj: T): T & PropEventSource<T>' >T</data-lsp></span><span style="color: #000000">>(</span><span style="color: #001080"><data-lsp lsp='(parameter) obj: T' >obj</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in makeWatchedObject<T>(obj: T): T & PropEventSource<T>' >T</data-lsp></span><span style="color: #000000">): </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in makeWatchedObject<T>(obj: T): T & PropEventSource<T>' >T</data-lsp></span><span style="color: #000000"> & </span><span style="color: #1C6277"><data-lsp lsp='type PropEventSource<T> = { on<K extends string & keyof T>(eventName: `${K}Changed`, callback: (newValue: T[K]) => void): void; }' >PropEventSource</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in makeWatchedObject<T>(obj: T): T & PropEventSource<T>' >T</data-lsp></span><span style="color: #000000">>;</span></div><div class='line'> </div><div class='line'><span style="color: #1C6277">let</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='let person: { firstName: string; age: number; location: string; } & PropEventSource<{ firstName: string; age: number; location: string; }>' >person</data-lsp></span><span style="color: #000000"> = </span><span style="color: #1C6277"><data-lsp lsp='function makeWatchedObject<{ firstName: string; age: number; location: string; }>(obj: { firstName: string; age: number; location: string; }): { firstName: string; age: number; location: string; } & PropEventSource<{ firstName: string; age: number; location: string; }>' >makeWatchedObject</data-lsp></span><span style="color: #000000">({</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) firstName: string' >firstName</data-lsp></span><span style="color: #000000">: </span><span style="color: #A31515">"Homer"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) age: number' >age</data-lsp></span><span style="color: #000000">: </span><span style="color: #098658">42</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) location: string' >location</data-lsp></span><span style="color: #000000">: </span><span style="color: #A31515">"Springfield"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000">});</span></div><div class='line'> </div><div class='line'><span style="color: #008000">// works! 'newName' is typed as 'string'</span></div><div class='line'><span style="color: #1C6277"><data-lsp lsp='let person: { firstName: string; age: number; location: string; } & PropEventSource<{ firstName: string; age: number; location: string; }>' >person</data-lsp></span><span style="color: #000000">.</span><span style="color: #1C6277"><data-lsp lsp='(method) on<"firstName">(eventName: "firstNameChanged", callback: (newValue: string) => void): void' >on</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515">"firstNameChanged"</span><span style="color: #000000">, </span><span style="color: #1C6277"><data-lsp lsp='(parameter) newName: string' >newName</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// 'newName' has the type of 'firstName'</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='var console: Console' >console</data-lsp></span><span style="color: #000000">.</span><span style="color: #1C6277"><data-lsp lsp='(method) Console.log(...data: any[]): void' >log</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515">`new name is </span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='(parameter) newName: string' >newName</data-lsp></span><span style="color: #000000FF">.</span><span style="color: #1C6277"><data-lsp lsp='(method) String.toUpperCase(): string' >toUpperCase</data-lsp></span><span style="color: #000000FF">()</span><span style="color: #0000FF">}</span><span style="color: #A31515">`</span><span style="color: #000000">);</span></div><div class='line'><span style="color: #000000">});</span></div><div class='line'> </div><div class='line'><span style="color: #008000">// works! 'newAge' is typed as 'number'</span></div><div class='line'><span style="color: #1C6277"><data-lsp lsp='let person: { firstName: string; age: number; location: string; } & PropEventSource<{ firstName: string; age: number; location: string; }>' >person</data-lsp></span><span style="color: #000000">.</span><span style="color: #1C6277"><data-lsp lsp='(method) on<"age">(eventName: "ageChanged", callback: (newValue: number) => void): void' >on</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515">"ageChanged"</span><span style="color: #000000">, </span><span style="color: #1C6277"><data-lsp lsp='(parameter) newAge: number' >newAge</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">if</span><span style="color: #000000"> (</span><span style="color: #001080"><data-lsp lsp='(parameter) newAge: number' >newAge</data-lsp></span><span style="color: #000000"> < 0) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='var console: Console' >console</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Console.log(...data: any[]): void' >log</data-lsp></span><span style="color: #000000">(</span><span style="color: #A31515">"warning! negative age"</span><span style="color: #000000">);</span></div><div class='line'><span style="color: #000000"> }</span></div><div class='line'><span style="color: #000000">})</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/C4TwDgpgBACgTgezAUQG4QHbAMoIK5wDGEAPACoB8UAvFAN4BQUzUCGJA0lBAB7CYATAM5QhwOAEsMAcygAyKAGsIIBADMolJix0AKCOiwA5AIYBbCAC4oAAwAkdDgF8AwgAsTMiAJsAaKIQmADZBAEYmhIrWuhgQAO4AasF4VpoA2hwAugCUNFSoCBICUNnWBUUA3AxOVQwCEIRBJnDQangYhMASbFBmJsoA6ibAhG7eAPKhAFYNwOQUugjT1mSlmvKwiCiGOPhEpJS1QRDAUJBwQj20fYPDoxPTs7qMOmoSF8CmFtYARAASCAscB+vm0zBM0lSABYAEygnRBBCBLpsX7YMCSGRvCBBAQg6rZWoAeiJUDiCDgiiEAEIoAByWJxL4QOlQCQiUCQYomER0sSY6R0hjnS4YAB0bF0PzeH2Z7k8kLx-kZzLy9DBUBJ9JV5hZUA8HLGUE50HU9JlYmZQp0hDYl2OYsR0l0NkZUAwurZIgcOosYuACAAqmBzi4eRBdNknDZCQTiaTyZSadr4gBBSGs9nG8DeKA87V4MyhCBwIUitgSjBSiEQeVeJXutOQtUvFgSDQxJvQEhQAAMuVbOmYtow9ogjoQzp+cWaGCk0lpsWkwwk6DzkJ+sZ0TgJQA'>Try</a></div></pre> <p>Here we made <code>on</code> into a generic method. When a user calls with the string <code>"firstNameChanged'</code>, TypeScript will try to infer the right type for <code>K</code>. To do that, it will match <code>K</code> against the content prior to <code>"Changed"</code> and infer the string <code>"firstName"</code>. Once TypeScript figures that out, the <code>on</code> method can fetch the type of <code>firstName</code> on the original object, which is <code>string</code> in this case. Similarly, when we call with <code>"ageChanged"</code>, it finds the type for the property <code>age</code> which is <code>number</code>).</p> <p>Inference can be combined in different ways, often to deconstruct strings, and reconstruct them in different ways. In fact, to help with modifying these string literal types, we’ve added a few new utility type aliases for modifying casing in letters (i.e. converting to lowercase and uppercase characters).</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type EnthusiasticGreeting<T extends string> = `${Uppercase<T>}`' >EnthusiasticGreeting</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type EnthusiasticGreeting<T extends string>' >T</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">extends</span><span style="color: #000000"> </span><span style="color: #1C6277">string</span><span style="color: #000000">> = </span><span style="color: #A31515">`</span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='type Uppercase<S extends string> = intrinsic' >Uppercase</data-lsp></span><span style="color: #000000FF"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type EnthusiasticGreeting<T extends string>' >T</data-lsp></span><span style="color: #000000FF">></span><span style="color: #0000FF">}</span><span style="color: #A31515">`</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type HELLO = "HELLO"' style='border-bottom: solid 2px lightgrey;'>HELLO</data-lsp></span><span style="color: #000000"> = </span><span style="color: #1C6277"><data-lsp lsp='type EnthusiasticGreeting<T extends string> = `${Uppercase<T>}`' >EnthusiasticGreeting</data-lsp></span><span style="color: #000000"><</span><span style="color: #A31515">"hello"</span><span style="color: #000000">>;</span></div><div class='meta-line'><span class='popover-prefix'> </span><span class='popover'><div class='arrow'></div>type HELLO = "HELLO"</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/C4TwDgpgBAogdsAFgVwM4EsCGrjoMYDiAThBLnAOYA8AKlBAB7ARwAmqUOR6lAfFAF4oAAwAkAbwCqYSETzYItXgF9hAKDWhIUABIwAMvoDyg2AhQZsuQiTI9qAIkQQANi4D2D3gG41Aej8oIIA9AH4gA'>Try</a></div></pre> <p>The new type aliases are <code>Uppercase</code>, <code>Lowercase</code>, <code>Capitalize</code> and <code>Uncapitalize</code>. The first two transform every character in a string, and the latter two transform only the first character in a string.</p> <p>For more details, <a href="https://github.com/microsoft/TypeScript/pull/40336">see the original pull request</a> and <a href="https://github.com/microsoft/TypeScript/pull/40580">the in-progress pull request to switch to type alias helpers</a>.</p> <h2 id="key-remapping-in-mapped-types" style="position:relative;"><a href="#key-remapping-in-mapped-types" aria-label="key remapping in 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>Key Remapping in Mapped Types</h2> <p>Just as a refresher, a mapped type can create new object types based on arbitrary keys</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">Options</span><span style="color: #000000"> = {</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #1C6277">K</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #A31515">"noImplicitAny"</span><span style="color: #000000"> | </span><span style="color: #A31515">"strictNullChecks"</span><span style="color: #000000"> | </span><span style="color: #A31515">"strictFunctionTypes"</span><span style="color: #000000">]?: </span><span style="color: #1C6277">boolean</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">};</span></div><div class='line'><span style="color: #008000">// same as</span></div><div class='line'><span style="color: #008000">// type Options = {</span></div><div class='line'><span style="color: #008000">// noImplicitAny?: boolean,</span></div><div class='line'><span style="color: #008000">// strictNullChecks?: boolean,</span></div><div class='line'><span style="color: #008000">// strictFunctionTypes?: boolean</span></div><div class='line'><span style="color: #008000">// };</span></div></code></div></pre> <p>or new object types based on other object types.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #008000">/// 'Partial<T>' is the same as 'T', but with each property marked optional.</span></div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">Partial</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">> = {</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #1C6277">K</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #0000FF">keyof</span><span style="color: #000000"> </span><span style="color: #1C6277">T</span><span style="color: #000000">]?: </span><span style="color: #1C6277">T</span><span style="color: #000000">[</span><span style="color: #1C6277">K</span><span style="color: #000000">];</span></div><div class='line'><span style="color: #000000">};</span></div></code></div></pre> <p>Until now, mapped types could only produce new object types with keys that you provided them; however, lots of the time you want to be able to create new keys, or filter out keys, based on the inputs.</p> <p>That’s why TypeScript 4.1 allows you to re-map keys in mapped types with a new <code>as</code> clause.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">MappedTypeWithNewKeys</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">> = {</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #1C6277">K</span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #0000FF">keyof</span><span style="color: #000000"> </span><span style="color: #1C6277">T</span><span style="color: #000000"> </span><span style="color: #AF00DB">as</span><span style="color: #000000"> </span><span style="color: #1C6277">NewKeyType</span><span style="color: #000000">]: </span><span style="color: #1C6277">T</span><span style="color: #000000">[</span><span style="color: #1C6277">K</span><span style="color: #000000">]</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// ^^^^^^^^^^^^^</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// This is the new syntax!</span></div><div class='line'><span style="color: #000000">}</span></div></code></div></pre> <p>With this new <code>as</code> clause, you can leverage features like template literal types to easily create property names based off of old ones.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]; }' >Getters</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type Getters<T>' >T</data-lsp></span><span style="color: #000000">> = {</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K' >K</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #0000FF">keyof</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type Getters<T>' >T</data-lsp></span><span style="color: #000000"> </span><span style="color: #AF00DB">as</span><span style="color: #000000"> </span><span style="color: #A31515">`get</span><span style="color: #0000FF">${</span><span style="color: #1C6277"><data-lsp lsp='type Capitalize<S extends string> = intrinsic' >Capitalize</data-lsp></span><span style="color: #000000FF"><</span><span style="color: #1C6277">string</span><span style="color: #000000FF"> </span><span style="color: #000000">&</span><span style="color: #000000FF"> </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K' >K</data-lsp></span><span style="color: #000000FF">></span><span style="color: #0000FF">}</span><span style="color: #A31515">`</span><span style="color: #000000">]: () </span><span style="color: #0000FF">=></span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type Getters<T>' >T</data-lsp></span><span style="color: #000000">[</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K' >K</data-lsp></span><span style="color: #000000">]</span></div><div class='line'><span style="color: #000000">};</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">interface</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='interface Person' >Person</data-lsp></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Person.name: string' >name</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Person.age: number' >age</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">number</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Person.location: string' >location</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type LazyPerson = { getName: () => string; getAge: () => number; getLocation: () => string; }' style='border-bottom: solid 2px lightgrey;'>LazyPerson</data-lsp></span><span style="color: #000000"> = </span><span style="color: #1C6277"><data-lsp lsp='type Getters<T> = { [K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]; }' >Getters</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='interface Person' >Person</data-lsp></span><span style="color: #000000">>;</span></div><div class='meta-line'><span class='popover-prefix'> </span><span class='popover'><div class='arrow'></div>type LazyPerson = { getName: () => string; getAge: () => number; getLocation: () => string; }</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/C4TwDgpgBA4hzAgJwM4B4AqA+KBeKA3gFBSlQDaA0lAJYB2UA1hCAPYBmUGUAhilAAMA5vAAkBAMI8wNYDwA2NAF4Q0KYEnpCoAMiiUsAXwEBdAFxQAFAEo8ODFRNFDAbiJF6iJOx4BjaAAKyCisDMRkUHQ8ALYQFuqadEJuETwiFnQArtEARsgpZPKsvjzANKHxGlpuhu6gkFAAMjxKIEGooXiw8F7o7SF0WG4A9MNkAHoA-EA'>Try</a></div></pre> <p>and you can even filter out keys by producing <code>never</code>. That means you don’t have to use an extra <code>Omit</code> helper type in some cases.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #008000">// Remove the 'kind' property</span></div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type RemoveKindField<T> = { [K in keyof T as Exclude<K, "kind">]: T[K]; }' >RemoveKindField</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type RemoveKindField<T>' >T</data-lsp></span><span style="color: #000000">> = {</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K' >K</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">in</span><span style="color: #000000"> </span><span style="color: #0000FF">keyof</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type RemoveKindField<T>' >T</data-lsp></span><span style="color: #000000"> </span><span style="color: #AF00DB">as</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type Exclude<T, U> = T extends U ? never : T' >Exclude</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K' >K</data-lsp></span><span style="color: #000000">, </span><span style="color: #A31515">"kind"</span><span style="color: #000000">>]: </span><span style="color: #1C6277"><data-lsp lsp='(type parameter) T in type RemoveKindField<T>' >T</data-lsp></span><span style="color: #000000">[</span><span style="color: #1C6277"><data-lsp lsp='(type parameter) K' >K</data-lsp></span><span style="color: #000000">]</span></div><div class='line'><span style="color: #000000">};</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">interface</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='interface Circle' >Circle</data-lsp></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Circle.kind: "circle"' >kind</data-lsp></span><span style="color: #000000">: </span><span style="color: #A31515">"circle"</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Circle.radius: number' >radius</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">number</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='type KindlessCircle = { radius: number; }' style='border-bottom: solid 2px lightgrey;'>KindlessCircle</data-lsp></span><span style="color: #000000"> = </span><span style="color: #1C6277"><data-lsp lsp='type RemoveKindField<T> = { [K in keyof T as Exclude<K, "kind">]: T[K]; }' >RemoveKindField</data-lsp></span><span style="color: #000000"><</span><span style="color: #1C6277"><data-lsp lsp='interface Circle' >Circle</data-lsp></span><span style="color: #000000">>;</span></div><div class='meta-line'><span class='popover-prefix'> </span><span class='popover'><div class='arrow'></div>type KindlessCircle = { radius: number; }</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAECUFMFsHsDdKgC4AskHIDWBLAdgCYagAOATrCZGcgJ4BQdVEMCkA0vgQGI6QA2BADwAVAHygAvKADe9UAtABtdqHygskWrABmoEaACGAZ1ABRAB4BjfgFcCkIewA0oAES5CbsQF0AXPoqPvQAvgDc9PT4yNQ6hlZIAMI4ZDZIcooaXAFuVilpbhGZZIYEOLbGAXi20ABG1BEhkUxInIT8kMbGyakdUixwiG08fIJCPWliESCKAHoA-EA'>Try</a></div></pre> <p>For more information, take a look at <a href="https://github.com/microsoft/TypeScript/pull/40336">the original pull request over on GitHub</a>.</p> <h2 id="recursive-conditional-types" style="position:relative;"><a href="#recursive-conditional-types" aria-label="recursive 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>Recursive Conditional Types</h2> <p>In JavaScript it’s fairly common to see functions that can flatten and build up container types at arbitrary levels. For example, consider the <code>.then()</code> method on instances of <code>Promise</code>. <code>.then(...)</code> unwraps each promise until it finds a value that’s not “promise-like”, and passes that value to a callback. There’s also a relatively new <code>flat</code> method on <code>Array</code>s that can take a depth of how deep to flatten.</p> <p>Expressing this in TypeScript’s type system was, for all practical intents and purposes, not possible. While there were hacks to achieve this, the types ended up looking very unreasonable.</p> <p>That’s why TypeScript 4.1 eases some restrictions on conditional types - so that they can model these patterns. In TypeScript 4.1, conditional types can now immediately reference themselves within their branches, making it easier to write recursive type aliases.</p> <p>For example, if we wanted to write a type to get the element types of nested arrays, we could write the following <code>deepFlatten</code> type.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">ElementType</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">> = </span><span style="color: #1C6277">T</span><span style="color: #000000"> </span><span style="color: #0000FF">extends</span><span style="color: #000000"> </span><span style="color: #1C6277">ReadonlyArray</span><span style="color: #000000"><</span><span style="color: #0000FF">infer</span><span style="color: #000000"> </span><span style="color: #1C6277">U</span><span style="color: #000000">> ? </span><span style="color: #1C6277">ElementType</span><span style="color: #000000"><</span><span style="color: #1C6277">U</span><span style="color: #000000">> : </span><span style="color: #1C6277">T</span><span style="color: #000000">;</span></div><div class='line'></div><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">deepFlatten</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000"> </span><span style="color: #0000FF">extends</span><span style="color: #000000"> </span><span style="color: #0000FF">readonly</span><span style="color: #000000"> </span><span style="color: #1C6277">unknown</span><span style="color: #000000">[]>(</span><span style="color: #001080">x</span><span style="color: #000000">: </span><span style="color: #1C6277">T</span><span style="color: #000000">): </span><span style="color: #1C6277">ElementType</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">>[] {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">throw</span><span style="color: #000000"> </span><span style="color: #A31515">"not implemented"</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'></div><div class='line'><span style="color: #008000">// All of these return the type 'number[]':</span></div><div class='line'><span style="color: #795E26">deepFlatten</span><span style="color: #000000">([</span><span style="color: #098658">1</span><span style="color: #000000">, </span><span style="color: #098658">2</span><span style="color: #000000">, </span><span style="color: #098658">3</span><span style="color: #000000">]);</span></div><div class='line'><span style="color: #795E26">deepFlatten</span><span style="color: #000000">([[</span><span style="color: #098658">1</span><span style="color: #000000">], [</span><span style="color: #098658">2</span><span style="color: #000000">, </span><span style="color: #098658">3</span><span style="color: #000000">]]);</span></div><div class='line'><span style="color: #795E26">deepFlatten</span><span style="color: #000000">([[</span><span style="color: #098658">1</span><span style="color: #000000">], [[</span><span style="color: #098658">2</span><span style="color: #000000">]], [[[</span><span style="color: #098658">3</span><span style="color: #000000">]]]]);</span></div></code></div></pre> <p>Similarly, in TypeScript 4.1 we can write an <code>Awaited</code> type to deeply unwrap <code>Promise</code>s.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">type</span><span style="color: #000000"> </span><span style="color: #1C6277">Awaited</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">> = </span><span style="color: #1C6277">T</span><span style="color: #000000"> </span><span style="color: #0000FF">extends</span><span style="color: #000000"> </span><span style="color: #1C6277">PromiseLike</span><span style="color: #000000"><</span><span style="color: #0000FF">infer</span><span style="color: #000000"> </span><span style="color: #1C6277">U</span><span style="color: #000000">> ? </span><span style="color: #1C6277">Awaited</span><span style="color: #000000"><</span><span style="color: #1C6277">U</span><span style="color: #000000">> : </span><span style="color: #1C6277">T</span><span style="color: #000000">;</span></div><div class='line'></div><div class='line'><span style="color: #008000">/// Like `promise.then(...)`, but more accurate in types.</span></div><div class='line'><span style="color: #0000FF">declare</span><span style="color: #000000"> </span><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">customThen</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">, </span><span style="color: #1C6277">U</span><span style="color: #000000">>(</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">p</span><span style="color: #000000">: </span><span style="color: #1C6277">Promise</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">>,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">onFulfilled</span><span style="color: #000000">: (</span><span style="color: #001080">value</span><span style="color: #000000">: </span><span style="color: #1C6277">Awaited</span><span style="color: #000000"><</span><span style="color: #1C6277">T</span><span style="color: #000000">>) </span><span style="color: #0000FF">=></span><span style="color: #000000"> </span><span style="color: #1C6277">U</span></div><div class='line'><span style="color: #000000">): </span><span style="color: #1C6277">Promise</span><span style="color: #000000"><</span><span style="color: #1C6277">Awaited</span><span style="color: #000000"><</span><span style="color: #1C6277">U</span><span style="color: #000000">>>;</span></div></code></div></pre> <p>Keep in mind that while these recursive types are powerful, they should be used responsibly and sparingly.</p> <p>First off, these types can do a lot of work which means that they can increase type-checking time. Trying to model numbers in the Collatz conjecture or Fibonacci sequence might be fun, but don’t ship that in <code>.d.ts</code> files on npm.</p> <p>But apart from being computationally intensive, these types can hit an internal recursion depth limit on sufficiently-complex inputs. When that recursion limit is hit, that results in a compile-time error. In general, it’s better not to use these types at all than to write something that fails on more realistic examples.</p> <p>See more <a href="https://github.com/microsoft/TypeScript/pull/40002">at the implementation</a>.</p> <h2 id="checked-indexed-accesses---nouncheckedindexedaccess" style="position:relative;"><a href="#checked-indexed-accesses---nouncheckedindexedaccess" aria-label="checked indexed accesses nouncheckedindexedaccess 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>Checked Indexed Accesses (<code>--noUncheckedIndexedAccess</code>)</h2> <p>TypeScript has a feature called <em>index signatures</em>. These signatures are a way to signal to the type system that users can access arbitrarily-named properties.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">interface</span><span style="color: #000000"> </span><span style="color: #1C6277"><data-lsp lsp='interface Options' >Options</data-lsp></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Options.path: string' >path</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(property) Options.permissions: number' >permissions</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">number</span><span style="color: #000000">;</span></div><div class='line'> </div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// Extra properties are caught by this index signature.</span></div><div class='line'><span style="color: #000000"> [</span><span style="color: #001080"><data-lsp lsp='(parameter) propName: string' >propName</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">]: </span><span style="color: #1C6277">string</span><span style="color: #000000"> | </span><span style="color: #1C6277">number</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'> </div><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26"><data-lsp lsp='function checkOptions(opts: Options): void' >checkOptions</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277"><data-lsp lsp='interface Options' >Options</data-lsp></span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(property) Options.path: string' >path</data-lsp></span><span style="color: #000000">; </span><span style="color: #008000">// string</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(property) Options.permissions: number' >permissions</data-lsp></span><span style="color: #000000">; </span><span style="color: #008000">// number</span></div><div class='line'> </div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// These are all allowed too!</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// They have the type 'string | number'.</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(index) Options[string]: string | number' >yadda</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">[</span><span style="color: #A31515">"foo bar baz"</span><span style="color: #000000">].</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">[</span><span style="color: #1C6277"><data-lsp lsp='var Math: Math' >Math</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Math.random(): number' >random</data-lsp></span><span style="color: #000000">()].</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000">}</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgPIAczAPYgM7IDeAUMsunGABYBcyeYUoA5gNynnQC2weeO+OiACuXAEbR2HAPTTkAUQAejOOSjZ00LBAJwoKBHGHMqYZGICeyar2SgAJhEX1gzEJWH6AdBwDa6dXQAOTguCDoGJhBmAF0IxhZkAB9kEXFJYgBfYmIYYRAELFxkBCoIBABrDCL8AAoNMDw6aoE8AEoiDga8LwpqVmRZegTorswezSgePlaBobSJKByyIYAVMrwUPS2AGx3kOD3sAHcIe2tsbABCGTl1iCsqOAA3FGo3i01kAHJIxJSFtBvj4yN0vBY4PZ7HAvGBsABlEbMWptdig8a+ABEMEu5j0eIAXpiYrCEUiUWjkN1fABZShULxQOAgezYLgoklwxFRZGorJAA'>Try</a></div></pre> <p>In the above example, <code>Options</code> has an index signature that says any accessed property that’s not already listed should have the type <code>string | number</code>. This is often convenient for optimistic code that assumes you know what you’re doing, but the truth is that most values in JavaScript do not support every potential property name. Most types will not, for example, have a value for a property key created by <code>Math.random()</code> like in the previous example. For many users, this behavior was undesirable, and felt like it wasn’t leveraging the full strict-checking of <a href="/tsconfig#strictNullChecks"><code>strictNullChecks</code></a>.</p> <p>That’s why TypeScript 4.1 ships with a new flag called <a href="/tsconfig#noUncheckedIndexedAccess"><code>noUncheckedIndexedAccess</code></a>. Under this new mode, every property access (like <code>foo.bar</code>) or indexed access (like <code>foo["bar"]</code>) is considered potentially undefined. That means that in our last example, <code>opts.yadda</code> will have the type <code>string | number | undefined</code> as opposed to just <code>string | number</code>. If you need to access that property, you’ll either have to check for its existence first or use a non-null assertion operator (the postfix <code>!</code> character).</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26"><data-lsp lsp='function checkOptions(opts: Options): void' >checkOptions</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277"><data-lsp lsp='interface Options' >Options</data-lsp></span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(property) Options.path: string' >path</data-lsp></span><span style="color: #000000">; </span><span style="color: #008000">// string</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(property) Options.permissions: number' >permissions</data-lsp></span><span style="color: #000000">; </span><span style="color: #008000">// number</span></div><div class='line'> </div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// These are not allowed with noUncheckedIndexedAccess</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(index) Options[string]: string | number | undefined' >yadda</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><span class="error"><span>'opts.yadda' is possibly 'undefined'.</span><span class="code">18048</span></span><span class="error-behind">'opts.yadda' is possibly 'undefined'.</span><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">[</span><span style="color: #A31515">"foo bar baz"</span><span style="color: #000000">].</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><span class="error"><span>Object is possibly 'undefined'.</span><span class="code">2532</span></span><span class="error-behind">Object is possibly 'undefined'.</span><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">[</span><span style="color: #1C6277"><data-lsp lsp='var Math: Math' >Math</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Math.random(): number' >random</data-lsp></span><span style="color: #000000">()].</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><span class="error"><span>Object is possibly 'undefined'.</span><span class="code">2532</span></span><span class="error-behind">Object is possibly 'undefined'.</span><div class='line'> </div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// Checking if it's really there first.</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">if</span><span style="color: #000000"> (</span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(index) Options[string]: string | number | undefined' >yadda</data-lsp></span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='var console: Console' >console</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Console.log(...data: any[]): void' >log</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(index) Options[string]: string | number' >yadda</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">());</span></div><div class='line'><span style="color: #000000"> }</span></div><div class='line'> </div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// Basically saying "trust me I know what I'm doing"</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// with the '!' non-null assertion operator.</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) opts: Options' >opts</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(index) Options[string]: string | number | undefined' >yadda</data-lsp></span><span style="color: #000000">!.</span><span style="color: #795E26"><data-lsp lsp='(method) toString(): string (+1 overload)' >toString</data-lsp></span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000">}</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYDMbQEYAOABgBYCAoECAOzgFVqBjAC0kYGtIATASWq8gAPbgEFGjSIkTkAltQAuMAGYBDCaADyAB3ky41RKADe5UKC0r5zVInnQ5AcwDcp8zAC2MqXoOpqAV3cAIxgXVyoAUUE7FXN4LRhdSVAVaEhQRhV-B2Z5UCCAT1ArL1A5AUFQRBkHakt-NIA6VwBtLXiAORV3SBs7RwBdPvtqB1AAH1AA4NDyAF9KMABaFcZ-eRWl8iV-Jl19DNYObX2DAAo4HRRNHR9EAEpjV0v5REaLKydQKlsRh2eru8PF5qvpEF8qNMQtByOEwAAVViIdKpdK0PIqAA2mLgAHduKBcTIrFN6EwjpxePwhKJxJJpGYXm8CiouFwVI15HAAMr9UZne4uRlXFoAIiUcDg+VS0oAXqKBpyeXyHAKhaAmS0ALKWZiNaAqfhwdwCxVc3l-NWwsxUADCFMcZSUZXkAHJDGksZiilYYOklDIkPJmmYZM6LoCWWyVI8TGYzIwwXBMZBGjjVUzGlH2UqLY4BYLXAs4aAAEIqaqZbFFRAqAqO0V2fy2UA9UA8UDsWi4wnMSzt13uUBcOCOUUlokk32gV0AQldpOoSwC2JSUkSPg1CQNXOgIa3ryzrPZs9zKqtcyAA'>Try</a></div></pre> <p>One consequence of using <a href="/tsconfig#noUncheckedIndexedAccess"><code>noUncheckedIndexedAccess</code></a> is that indexing into an array is also more strictly checked, even in a bounds-checked loop.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26"><data-lsp lsp='function screamLines(strs: string[]): void' >screamLines</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) strs: string[]' >strs</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">[]) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// This will have issues</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">for</span><span style="color: #000000"> (</span><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='let i: number' >i</data-lsp></span><span style="color: #000000"> = </span><span style="color: #098658">0</span><span style="color: #000000">; </span><span style="color: #001080"><data-lsp lsp='let i: number' >i</data-lsp></span><span style="color: #000000"> < </span><span style="color: #001080"><data-lsp lsp='(parameter) strs: string[]' >strs</data-lsp></span><span style="color: #000000">.</span><span style="color: #001080"><data-lsp lsp='(property) Array<string>.length: number' >length</data-lsp></span><span style="color: #000000">; </span><span style="color: #001080"><data-lsp lsp='let i: number' >i</data-lsp></span><span style="color: #000000">++) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='var console: Console' >console</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Console.log(...data: any[]): void' >log</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) strs: string[]' >strs</data-lsp></span><span style="color: #000000">[</span><span style="color: #001080"><data-lsp lsp='let i: number' >i</data-lsp></span><span style="color: #000000">].</span><span style="color: #795E26"><data-lsp lsp='(method) String.toUpperCase(): string' >toUpperCase</data-lsp></span><span style="color: #000000">());</span></div><span class="error"><span>Object is possibly 'undefined'.</span><span class="code">2532</span></span><span class="error-behind">Object is possibly 'undefined'.</span><div class='line'><span style="color: #000000"> }</span></div><div class='line'><span style="color: #000000">}</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAEAEFMCdoe2gZwFygEwFYDMbQEYAOABgBYCAoECAOzgFVqBjAC0kYGtIATASWq8gAPbgEFGjSIkTkAZgFcmAFwCWcaqESNokAIYBbADLLqkgBSJFSVBejGA5gG0AugEpQAb3KhQVACrNlRFAAd2UAGzDQZh0AN0hQQMQ5SS9QGQRQUzDIRQTQAF5QIgBuPIAeDUtEADps6jtFZlLlAGoWt09vb0Y1RDhs2rg7cyqHZSdqxXoAB2mYAGEdREhTFxdi1IBfck2gA'>Try</a></div></pre> <p>If you don’t need the indexes, you can iterate over individual elements by using a <code>for</code>-<code>of</code> loop or a <code>forEach</code> call.</p> <pre class="shiki light-plus twoslash lsp" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26"><data-lsp lsp='function screamLines(strs: string[]): void' >screamLines</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) strs: string[]' >strs</data-lsp></span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">[]) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// This works fine</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">for</span><span style="color: #000000"> (</span><span style="color: #0000FF">const</span><span style="color: #000000"> </span><span style="color: #0070C1"><data-lsp lsp='const str: string' >str</data-lsp></span><span style="color: #000000"> </span><span style="color: #0000FF">of</span><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) strs: string[]' >strs</data-lsp></span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='var console: Console' >console</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Console.log(...data: any[]): void' >log</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='const str: string' >str</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) String.toUpperCase(): string' >toUpperCase</data-lsp></span><span style="color: #000000">());</span></div><div class='line'><span style="color: #000000"> }</span></div><div class='line'> </div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// This works fine</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='(parameter) strs: string[]' >strs</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Array<string>.forEach(callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any): void' >forEach</data-lsp></span><span style="color: #000000">((</span><span style="color: #001080"><data-lsp lsp='(parameter) str: string' >str</data-lsp></span><span style="color: #000000">) </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080"><data-lsp lsp='var console: Console' >console</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) Console.log(...data: any[]): void' >log</data-lsp></span><span style="color: #000000">(</span><span style="color: #001080"><data-lsp lsp='(parameter) str: string' >str</data-lsp></span><span style="color: #000000">.</span><span style="color: #795E26"><data-lsp lsp='(method) String.toUpperCase(): string' >toUpperCase</data-lsp></span><span style="color: #000000">());</span></div><div class='line'><span style="color: #000000"> });</span></div><div class='line'><span style="color: #000000">}</span></div></code><a class='playground-link' href='https://www.typescriptlang.org/play/#code/PTAEAEDsHsFVIMYAsCmCDWKAmBJSWUAPbAQQQRQGdKAoAMwFdEAXAS2klEoQCcUBDALYAZVpCoAKSsx6UAXFxliA5gG0AugEpQAbxqhQIUABUkrSqADu0Hugt0xKfaDo3QEhB2mKeoaHR9KbT0DA09ISmgAGxQAOijoZSkZWOY4AAd0lB4AYX5KFAlNTQBuZwBfGmcjU3MrGzsXR2dpWVjXHgBRfmQJZJ5tAF4APl1nMK9ouISk1tSMrNz8wuKyg3LSmnKgA'>Try</a></div></pre> <p>This flag can be handy for catching out-of-bounds errors, but it might be noisy for a lot of code, so it is not automatically enabled by the <a href="/tsconfig#strict"><code>strict</code></a> flag; however, if this feature is interesting to you, you should feel free to try it and determine whether it makes sense for your team’s codebase!</p> <p>You can learn more <a href="https://github.com/microsoft/TypeScript/pull/39560">at the implementing pull request</a>.</p> <h2 id="paths-without-baseurl" style="position:relative;"><a href="#paths-without-baseurl" aria-label="paths without baseurl 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>paths</code> without <code>baseUrl</code></h2> <p>Using path-mapping is fairly common - often it’s to have nicer imports, often it’s to simulate monorepo linking behavior.</p> <p>Unfortunately, specifying <a href="/tsconfig#paths"><code>paths</code></a> to enable path-mapping required also specifying an option called <a href="/tsconfig#baseUrl"><code>baseUrl</code></a>, which allows bare specifier paths to be reached relative to the <a href="/tsconfig#baseUrl"><code>baseUrl</code></a> too. This also often caused poor paths to be used by auto-imports.</p> <p>In TypeScript 4.1, the <a href="/tsconfig#paths"><code>paths</code></a> option can be used without <a href="/tsconfig#baseUrl"><code>baseUrl</code></a>. This helps avoid some of these issues.</p> <h2 id="checkjs-implies-allowjs" style="position:relative;"><a href="#checkjs-implies-allowjs" aria-label="checkjs implies allowjs 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>checkJs</code> Implies <code>allowJs</code></h2> <p>Previously if you were starting a checked JavaScript project, you had to set both <a href="/tsconfig#allowJs"><code>allowJs</code></a> and <a href="/tsconfig#checkJs"><code>checkJs</code></a>. This was a slightly annoying bit of friction in the experience, so <a href="/tsconfig#checkJs"><code>checkJs</code></a> now implies <a href="/tsconfig#allowJs"><code>allowJs</code></a> by default.</p> <p><a href="https://github.com/microsoft/TypeScript/pull/40275">See more details at the pull request</a>.</p> <h2 id="react-17-jsx-factories" style="position:relative;"><a href="#react-17-jsx-factories" aria-label="react 17 jsx factories 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>React 17 JSX Factories</h2> <p>TypeScript 4.1 supports React 17’s upcoming <code>jsx</code> and <code>jsxs</code> factory functions through two new options for the <a href="/tsconfig#jsx"><code>jsx</code></a> compiler option:</p> <ul> <li><code>react-jsx</code></li> <li><code>react-jsxdev</code></li> </ul> <p>These options are intended for production and development compiles respectively. Often, the options from one can extend from the other. For example, a <code>tsconfig.json</code> for production builds might look like the following:</p> <pre class="shiki light-plus tsconfig lsp" style="background-color: #FFFFFF; color: #000000" tsconfig="true"><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #008000">// ./src/tsconfig.json</span></div><div class='line'><span style="color: #000000">{</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#compilerOptions'><data-lsp lsp="The set of compiler options for your project">compilerOptions</data-lsp></a>"</span><span style="color: #000000">: {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#module'><data-lsp lsp="Specify what module code is generated.">module</data-lsp></a>"</span><span style="color: #000000">: </span><span style="color: #A31515">"esnext"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#target'><data-lsp lsp="Set the JavaScript language version for emitted JavaScript and include compatible library declarations.">target</data-lsp></a>"</span><span style="color: #000000">: </span><span style="color: #A31515">"es2015"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#jsx'><data-lsp lsp="Specify what JSX code is generated.">jsx</data-lsp></a>"</span><span style="color: #000000">: </span><span style="color: #A31515">"react-jsx"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#strict'><data-lsp lsp="Enable all strict type-checking options.">strict</data-lsp></a>"</span><span style="color: #000000">: </span><span style="color: #0000FF">true</span></div><div class='line'><span style="color: #000000"> },</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#include'><data-lsp lsp="Specify a list of glob patterns that match files to be included in compilation.">include</data-lsp></a>"</span><span style="color: #000000">: [</span><span style="color: #A31515">"./**/*"</span><span style="color: #000000">]</span></div><div class='line'><span style="color: #000000">}</span></div></code></div></pre> <p>and one for development builds might look like the following:</p> <pre class="shiki light-plus tsconfig lsp" style="background-color: #FFFFFF; color: #000000" tsconfig="true"><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #008000">// ./src/tsconfig.dev.json</span></div><div class='line'><span style="color: #000000">{</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#extends'><data-lsp lsp="Specify one or more path or node module references to base configuration files from which settings are inherited.">extends</data-lsp></a>"</span><span style="color: #000000">: </span><span style="color: #A31515">"./tsconfig.json"</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#compilerOptions'><data-lsp lsp="The set of compiler options for your project">compilerOptions</data-lsp></a>"</span><span style="color: #000000">: {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #0451A5">"<a aria-hidden=true tabindex="-1" href='https://www.typescriptlang.org/tsconfig#jsx'><data-lsp lsp="Specify what JSX code is generated.">jsx</data-lsp></a>"</span><span style="color: #000000">: </span><span style="color: #A31515">"react-jsxdev"</span></div><div class='line'><span style="color: #000000"> }</span></div><div class='line'><span style="color: #000000">}</span></div></code></div></pre> <p>For more information, <a href="https://github.com/microsoft/TypeScript/pull/39199">check out the corresponding PR</a>.</p> <h2 id="editor-support-for-the-jsdoc-see-tag" style="position:relative;"><a href="#editor-support-for-the-jsdoc-see-tag" aria-label="editor support for the jsdoc see tag 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>Editor Support for the JSDoc <code>@see</code> Tag</h2> <p>The JSDoc tag <code>@see</code> tag now has better support in editors for TypeScript and JavaScript. This allows you to use functionality like go-to-definition in a dotted name following the tag. For example, going to definition on <code>first</code> or <code>C</code> in the JSDoc comment just works in the following example:</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #008000">// @filename: first.ts</span></div><div class='line'><span style="color: #AF00DB">export</span><span style="color: #000000"> </span><span style="color: #0000FF">class</span><span style="color: #000000"> </span><span style="color: #1C6277">C</span><span style="color: #000000"> {}</span></div><div class='line'></div><div class='line'><span style="color: #008000">// @filename: main.ts</span></div><div class='line'><span style="color: #AF00DB">import</span><span style="color: #000000"> </span><span style="color: #0000FF">*</span><span style="color: #000000"> </span><span style="color: #AF00DB">as</span><span style="color: #000000"> </span><span style="color: #001080">first</span><span style="color: #000000"> </span><span style="color: #AF00DB">from</span><span style="color: #000000"> </span><span style="color: #A31515">"./first"</span><span style="color: #000000">;</span></div><div class='line'></div><div class='line'><span style="color: #008000">/**</span></div><div class='line'><span style="color: #008000"> * </span><span style="color: #0000FF">@see</span><span style="color: #008000"> </span><span style="color: #1C6277">first.C</span></div><div class='line'><span style="color: #008000"> */</span></div><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">related</span><span style="color: #000000">() {}</span></div></code></div></pre> <p>Thanks to frequent contributor <a href="https://github.com/Kingwl">Wenlu Wang</a> <a href="https://github.com/microsoft/TypeScript/pull/39760">for implementing this</a>!</p> <h2 id="breaking-changes" style="position:relative;"><a href="#breaking-changes" aria-label="breaking changes 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>Breaking Changes</h2> <h3 id="libdts-changes" style="position:relative;"><a href="#libdts-changes" aria-label="libdts changes 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>lib.d.ts</code> Changes</h3> <p><code>lib.d.ts</code> may have a set of changed APIs, potentially in part due to how the DOM types are automatically generated. One specific change is that <code>Reflect.enumerate</code> has been removed, as it was removed from ES2016.</p> <h3 id="abstract-members-cant-be-marked-async" style="position:relative;"><a href="#abstract-members-cant-be-marked-async" aria-label="abstract members cant be marked async 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>abstract</code> Members Can’t Be Marked <code>async</code></h3> <p>Members marked as <code>abstract</code> can no longer be marked as <code>async</code>. The fix here is to remove the <code>async</code> keyword, since callers are only concerned with the return type.</p> <h3 id="anyunknown-are-propagated-in-falsy-positions" style="position:relative;"><a href="#anyunknown-are-propagated-in-falsy-positions" aria-label="anyunknown are propagated in falsy positions 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>any</code>/<code>unknown</code> Are Propagated in Falsy Positions</h3> <p>Previously, for an expression like <code>foo && somethingElse</code>, the type of <code>foo</code> was <code>any</code> or <code>unknown</code>, the type of the whole that expression would be the type of <code>somethingElse</code>.</p> <p>For example, previously the type for <code>x</code> here was <code>{ someProp: string }</code>.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">declare</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #001080">foo</span><span style="color: #000000">: </span><span style="color: #1C6277">unknown</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #0000FF">declare</span><span style="color: #000000"> </span><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #001080">somethingElse</span><span style="color: #000000">: { </span><span style="color: #001080">someProp</span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000"> };</span></div><div class='line'></div><div class='line'><span style="color: #0000FF">let</span><span style="color: #000000"> </span><span style="color: #001080">x</span><span style="color: #000000"> = </span><span style="color: #001080">foo</span><span style="color: #000000"> && </span><span style="color: #001080">somethingElse</span><span style="color: #000000">;</span></div></code></div></pre> <p>However, in TypeScript 4.1, we are more careful about how we determine this type. Since nothing is known about the type on the left side of the <code>&&</code>, we propagate <code>any</code> and <code>unknown</code> outward instead of the type on the right side.</p> <p>The most common pattern we saw of this tended to be when checking compatibility with <code>boolean</code>s, especially in predicate functions.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">isThing</span><span style="color: #000000">(</span><span style="color: #001080">x</span><span style="color: #000000">: </span><span style="color: #1C6277">any</span><span style="color: #000000">): </span><span style="color: #1C6277">boolean</span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">return</span><span style="color: #000000"> </span><span style="color: #001080">x</span><span style="color: #000000"> && </span><span style="color: #0000FF">typeof</span><span style="color: #000000"> </span><span style="color: #001080">x</span><span style="color: #000000"> === </span><span style="color: #A31515">"object"</span><span style="color: #000000"> && </span><span style="color: #001080">x</span><span style="color: #000000">.</span><span style="color: #001080">blah</span><span style="color: #000000"> === </span><span style="color: #A31515">"foo"</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div></code></div></pre> <p>Often the appropriate fix is to switch from <code>foo && someExpression</code> to <code>!!foo && someExpression</code>.</p> <h3 id="resolves-parameters-are-no-longer-optional-in-promises" style="position:relative;"><a href="#resolves-parameters-are-no-longer-optional-in-promises" aria-label="resolves parameters are no longer optional in promises 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>resolve</code>’s Parameters Are No Longer Optional in <code>Promise</code>s</h3> <p>When writing code like the following</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">new</span><span style="color: #000000"> </span><span style="color: #1C6277">Promise</span><span style="color: #000000">((</span><span style="color: #001080">resolve</span><span style="color: #000000">) </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">doSomethingAsync</span><span style="color: #000000">(() </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">doSomething</span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">resolve</span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> });</span></div><div class='line'><span style="color: #000000">});</span></div></code></div></pre> <p>You may get an error like the following:</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class='code-container' tabindex='0'><code><div class='line'><span style="color: undefined"> resolve()</span></div><div class='line'><span style="color: undefined"> ~~~~~~~~~</span></div><div class='line'><span style="color: undefined">error TS2554: Expected 1 arguments, but got 0.</span></div><div class='line'><span style="color: undefined"> An argument for 'value' was not provided.</span></div></code></div></pre> <p>This is because <code>resolve</code> no longer has an optional parameter, so by default, it must now be passed a value. Often this catches legitimate bugs with using <code>Promise</code>s. The typical fix is to pass it the correct argument, and sometimes to add an explicit type argument.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">new</span><span style="color: #000000"> </span><span style="color: #1C6277">Promise</span><span style="color: #000000"><</span><span style="color: #1C6277">number</span><span style="color: #000000">>((</span><span style="color: #001080">resolve</span><span style="color: #000000">) </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// ^^^^^^^^</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">doSomethingAsync</span><span style="color: #000000">((</span><span style="color: #001080">value</span><span style="color: #000000">) </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">doSomething</span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">resolve</span><span style="color: #000000">(</span><span style="color: #001080">value</span><span style="color: #000000">);</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// ^^^^^</span></div><div class='line'><span style="color: #000000"> });</span></div><div class='line'><span style="color: #000000">});</span></div></code></div></pre> <p>However, sometimes <code>resolve()</code> really does need to be called without an argument. In these cases, we can give <code>Promise</code> an explicit <code>void</code> generic type argument (i.e. write it out as <code>Promise<void></code>). This leverages new functionality in TypeScript 4.1 where a potentially-<code>void</code> trailing parameter can become optional.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">new</span><span style="color: #000000"> </span><span style="color: #1C6277">Promise</span><span style="color: #000000"><</span><span style="color: #1C6277">void</span><span style="color: #000000">>((</span><span style="color: #001080">resolve</span><span style="color: #000000">) </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #008000">// ^^^^^^</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">doSomethingAsync</span><span style="color: #000000">(() </span><span style="color: #0000FF">=></span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">doSomething</span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #795E26">resolve</span><span style="color: #000000">();</span></div><div class='line'><span style="color: #000000"> });</span></div><div class='line'><span style="color: #000000">});</span></div></code></div></pre> <p>TypeScript 4.1 ships with a quick fix to help fix this break.</p> <h3 id="conditional-spreads-create-optional-properties" style="position:relative;"><a href="#conditional-spreads-create-optional-properties" aria-label="conditional spreads create optional 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>Conditional Spreads Create Optional Properties</h3> <p>In JavaScript, object spreads (like <code>{ ...foo }</code>) don’t operate over falsy values. So in code like <code>{ ...foo }</code>, <code>foo</code> will be skipped over if it’s <code>null</code> or <code>undefined</code>.</p> <p>Many users take advantage of this to spread properties “conditionally”.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class="language-id">ts</div><div class='code-container' tabindex='0'><code><div class='line'><span style="color: #0000FF">interface</span><span style="color: #000000"> </span><span style="color: #1C6277">Person</span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">name</span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">age</span><span style="color: #000000">: </span><span style="color: #1C6277">number</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">location</span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'></div><div class='line'><span style="color: #0000FF">interface</span><span style="color: #000000"> </span><span style="color: #1C6277">Animal</span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">name</span><span style="color: #000000">: </span><span style="color: #1C6277">string</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">owner</span><span style="color: #000000">: </span><span style="color: #1C6277">Person</span><span style="color: #000000">;</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'></div><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">copyOwner</span><span style="color: #000000">(</span><span style="color: #001080">pet</span><span style="color: #000000">?: </span><span style="color: #1C6277">Animal</span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">return</span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> ...(</span><span style="color: #001080">pet</span><span style="color: #000000"> && </span><span style="color: #001080">pet</span><span style="color: #000000">.</span><span style="color: #001080">owner</span><span style="color: #000000">),</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">otherStuff:</span><span style="color: #000000"> </span><span style="color: #098658">123</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> };</span></div><div class='line'><span style="color: #000000">}</span></div><div class='line'></div><div class='line'><span style="color: #008000">// We could also use optional chaining here:</span></div><div class='line'></div><div class='line'><span style="color: #0000FF">function</span><span style="color: #000000"> </span><span style="color: #795E26">copyOwner</span><span style="color: #000000">(</span><span style="color: #001080">pet</span><span style="color: #000000">?: </span><span style="color: #1C6277">Animal</span><span style="color: #000000">) {</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #AF00DB">return</span><span style="color: #000000"> {</span></div><div class='line'><span style="color: #000000"> ...</span><span style="color: #001080">pet</span><span style="color: #000000">?.</span><span style="color: #001080">owner</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> </span><span style="color: #001080">otherStuff:</span><span style="color: #000000"> </span><span style="color: #098658">123</span><span style="color: #000000">,</span></div><div class='line'><span style="color: #000000"> };</span></div><div class='line'><span style="color: #000000">}</span></div></code></div></pre> <p>Here, if <code>pet</code> is defined, the properties of <code>pet.owner</code> will be spread in - otherwise, no properties will be spread into the returned object.</p> <p>The return type of <code>copyOwner</code> was previously a union type based on each spread:</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class='code-container' tabindex='0'><code><div class='line'><span style="color: undefined">{ x: number } | { x: number, name: string, age: number, location: string }</span></div></code></div></pre> <p>This modeled exactly how the operation would occur: if <code>pet</code> was defined, all the properties from <code>Person</code> would be present; otherwise, none of them would be defined on the result. It was an all-or-nothing operation.</p> <p>However, we’ve seen this pattern taken to the extreme, with hundreds of spreads in a single object, each spread potentially adding in hundreds or thousands of properties. It turns out that for various reasons, this ends up being extremely expensive, and usually for not much benefit.</p> <p>In TypeScript 4.1, the returned type sometimes uses all-optional properties.</p> <pre class="shiki light-plus" style="background-color: #FFFFFF; color: #000000"><div class='code-container' tabindex='0'><code><div class='line'><span style="color: undefined">{</span></div><div class='line'><span style="color: undefined"> x: number;</span></div><div class='line'><span style="color: undefined"> name?: string;</span></div><div class='line'><span style="color: undefined"> age?: number;</span></div><div class='line'><span style="color: undefined"> location?: string;</span></div><div class='line'><span style="color: undefined">}</span></div></code></div></pre> <p>This ends up performing better and generally displaying better too.</p> <p>For more details, <a href="https://github.com/microsoft/TypeScript/pull/40778">see the original change</a>. While this behavior is not entirely consistent right now, we expect a future release will produce cleaner and more predictable results.</p> <h3 id="unmatched-parameters-are-no-longer-related" style="position:relative;"><a href="#unmatched-parameters-are-no-longer-related" aria-label="unmatched parameters are no longer related 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>Unmatched parameters are no longer related</h3> <p>TypeScript would previously relate parameters that didn’t correspond to each other by relating them to the type <code>any</code>. With <a href="https://github.com/microsoft/TypeScript/pull/41308">changes in TypeScript 4.1</a>, the language now skips this process entirely. This means that some cases of assignability will now fail, but it also means that some cases of overload resolution can fail as well. For example, overload resolution on <code>util.promisify</code> in Node.js may select a different overload in TypeScript 4.1, sometimes causing new or different errors downstream.</p> <p>As a workaround, you may be best using a type assertion to squelch errors.</p></div></div><aside class="handbook-toc"><nav class="" aria-label="table of contents"><h5>On this page</h5><ul class="handbook-on-this-page-section-list"><li><a href="#template-literal-types">Template Literal Types</a></li><li><a href="#key-remapping-in-mapped-types">Key Remapping in Mapped Types</a></li><li><a href="#recursive-conditional-types">Recursive Conditional Types</a></li><li><a href="#checked-indexed-accesses---nouncheckedindexedaccess">Checked Indexed Accesses (--noUncheckedIndexedAccess)</a></li><li><a href="#paths-without-baseurl">paths without baseUrl</a></li><li><a href="#checkjs-implies-allowjs">checkJs Implies allowJs</a></li><li><a href="#react-17-jsx-factories">React 17 JSX Factories</a></li><li><a href="#editor-support-for-the-jsdoc-see-tag">Editor Support for the JSDoc @see Tag</a></li><li><a href="#breaking-changes">Breaking Changes</a><ul><li><a href="#libdts-changes">lib.d.ts Changes</a></li><li><a href="#abstract-members-cant-be-marked-async">abstract Members Can’t Be Marked async</a></li><li><a href="#anyunknown-are-propagated-in-falsy-positions">any/unknown Are Propagated in Falsy Positions</a></li><li><a href="#resolves-parameters-are-no-longer-optional-in-promises">resolve’s Parameters Are No Longer Optional in Promises</a></li><li><a href="#conditional-spreads-create-optional-properties">Conditional Spreads Create Optional Properties</a></li><li><a href="#unmatched-parameters-are-no-longer-related">Unmatched parameters are no longer related</a></li></ul></li></ul><div id="like-dislike-subnav"><h5>Is this page helpful?</h5><div><button title="Like this page" id="like-button"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.052 2.29429C10.3913 1.31699 11.6841 0.866721 12.4829 1.70385C12.6455 1.87427 12.8081 2.05843 12.9176 2.22265C13.2379 2.70316 13.3725 3.33595 13.4218 3.95232C13.4721 4.58045 13.438 5.25457 13.3738 5.86484C13.3093 6.47746 13.2129 7.03959 13.1328 7.44777C13.1294 7.46547 13.1259 7.48288 13.1225 7.5H14.006C15.8777 7.5 17.2924 9.19514 16.9576 11.0367L16.2737 14.7984C15.8017 17.3943 13.2078 19.0291 10.6622 18.3348L5.06251 16.8076C4.14894 16.5585 3.45455 15.8145 3.26885 14.886L2.91581 13.1208C2.63809 11.7322 3.69991 10.5624 4.82905 10.1161C5.15163 9.98861 5.44337 9.82679 5.66974 9.62597C7.37583 8.11245 7.99442 6.90287 9.05406 4.77695C9.4084 4.06605 9.77205 3.10054 10.052 2.29429ZM12.0165 7.87862L12.0169 7.87707L12.0187 7.86973L12.0262 7.83863C12.0328 7.81079 12.0426 7.76903 12.0549 7.71494C12.0793 7.60669 12.1135 7.4493 12.1515 7.25536C12.2277 6.86666 12.3188 6.33504 12.3793 5.76016C12.4401 5.18293 12.4685 4.5758 12.425 4.03206C12.3806 3.47655 12.2652 3.04684 12.0855 2.77735C12.0264 2.6887 11.9138 2.55604 11.7594 2.39421C11.5605 2.18576 11.1314 2.23428 10.9967 2.62228C10.7141 3.43609 10.3334 4.45194 9.94904 5.22305C8.88216 7.36349 8.19326 8.72408 6.33336 10.374C5.99304 10.6759 5.58878 10.8911 5.19665 11.0461C4.31631 11.3941 3.75035 12.1945 3.89639 12.9247L4.24943 14.6899C4.36085 15.247 4.77748 15.6934 5.32562 15.8428L10.9254 17.3701C12.9052 17.91 14.9227 16.6385 15.2898 14.6195L15.9738 10.8578C16.197 9.63009 15.2538 8.5 14.006 8.5H12.5015C12.3476 8.5 12.2022 8.42906 12.1074 8.30771C12.0127 8.18638 11.9792 8.02796 12.0165 7.87862C12.0165 7.87858 12.0165 7.87866 12.0165 7.87862Z"></path></svg> <!-- -->Yes</button><button title="Dislike this page" id="dislike-button"><svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.052 17.7057C10.3913 18.683 11.6841 19.1333 12.4829 18.2962C12.6455 18.1257 12.8081 17.9416 12.9176 17.7773C13.2379 17.2968 13.3725 16.664 13.4218 16.0477C13.4721 15.4195 13.438 14.7454 13.3738 14.1352C13.3093 13.5225 13.2129 12.9604 13.1328 12.5522C13.1294 12.5345 13.1259 12.5171 13.1225 12.5H14.006C15.8777 12.5 17.2924 10.8049 16.9576 8.96334L16.2737 5.20164C15.8017 2.60569 13.2078 0.970948 10.6622 1.66518L5.06251 3.19238C4.14894 3.44154 3.45455 4.18546 3.26885 5.11401L2.91581 6.87918C2.63809 8.26779 3.69991 9.43756 4.82905 9.88388C5.15163 10.0114 5.44337 10.1732 5.66974 10.374C7.37583 11.8875 7.99442 13.0971 9.05406 15.223C9.4084 15.9339 9.77205 16.8995 10.052 17.7057ZM12.0165 12.1214L12.0169 12.1229L12.0187 12.1303L12.0262 12.1614C12.0328 12.1892 12.0426 12.231 12.0549 12.2851C12.0793 12.3933 12.1135 12.5507 12.1515 12.7446C12.2277 13.1333 12.3188 13.665 12.3793 14.2398C12.4401 14.8171 12.4685 15.4242 12.425 15.9679C12.3806 16.5234 12.2652 16.9532 12.0855 17.2226C12.0264 17.3113 11.9138 17.444 11.7594 17.6058C11.5605 17.8142 11.1314 17.7657 10.9967 17.3777C10.7141 16.5639 10.3334 15.5481 9.94904 14.777C8.88216 12.6365 8.19326 11.2759 6.33336 9.62597C5.99304 9.32406 5.58878 9.1089 5.19665 8.9539C4.31631 8.60592 3.75035 7.80549 3.89639 7.0753L4.24943 5.31012C4.36085 4.753 4.77748 4.30664 5.32562 4.15715L10.9254 2.62995C12.9052 2.08999 14.9227 3.36145 15.2898 5.38052L15.9738 9.14222C16.197 10.3699 15.2538 11.5 14.006 11.5H12.5015C12.3476 11.5 12.2022 11.5709 12.1074 11.6923C12.0127 11.8136 11.9792 11.972 12.0165 12.1214C12.0165 12.1214 12.0165 12.1213 12.0165 12.1214Z"></path></svg> <!-- -->No</button></div></div></nav></aside></article><div class="whitespace-tight raised" style="padding:0"><div class="row justify-between small-columns"><div class="bottom-section-content"><p>The TypeScript docs are an open source project. Help us improve these pages <a href="https://github.com/microsoft/TypeScript-Website/blob/v2/packages/documentation/copy/en/release-notes/TypeScript 4.1.md">by sending a Pull Request</a> ❤</p></div><div class="hide-small vertical-line" style="margin-top:1.5rem"></div><div class="bottom-section-content">Contributors to this page:<br/><div><div class="circle-bg">EI<img id="a65caef54cbaba95975117e96ca2d411668cedaea6e5bbc59287ed673c84751e" src="https://gravatar.com/avatar/a65caef54cbaba95975117e96ca2d411668cedaea6e5bbc59287ed673c84751e?s=32&&d=blank" alt="Eugene Ilyin (1)"/></div><div class="circle-bg">AB<img id="86ed396e4ffb41b052654b9f8ad4d1caaf732bc42985860b0cac8191a66e33df" src="https://gravatar.com/avatar/86ed396e4ffb41b052654b9f8ad4d1caaf732bc42985860b0cac8191a66e33df?s=32&&d=blank" alt="Andrew Branch (1)"/></div><div class="circle-bg">JB<img id="98326ec560d25aebd787245a6c457afd24ed35b0ba578c2a5e38da41ff657152" src="https://gravatar.com/avatar/98326ec560d25aebd787245a6c457afd24ed35b0ba578c2a5e38da41ff657152?s=32&&d=blank" alt="Jack Bates (1)"/></div><div class="circle-bg">H<img id="9983b66c13f37c6b49f24701f3cda81ef09b6c09592bd7f8ab4e283e3c602812" src="https://gravatar.com/avatar/9983b66c13f37c6b49f24701f3cda81ef09b6c09592bd7f8ab4e283e3c602812?s=32&&d=blank" alt="HumanEquivalentUnit (1)"/></div><div class="circle-bg">OT<img id="https://avatars.githubusercontent.com/u/49038?s=100&u=0b9ac5bf42a8ea2543a05191e150e0213456744e&v=4" src="https://avatars.githubusercontent.com/u/49038?s=100&u=0b9ac5bf42a8ea2543a05191e150e0213456744e&v=4" alt="Orta Therox (1)"/></div></div></div><div class="hide-small vertical-line" style="margin-top:1.5rem"></div><div class="bottom-section-content"><p>Last updated: Feb 17, 2025<br/><br/><span id="page-loaded-time"> </span></p></div></div></div></div></section></main><footer id="site-footer" role="contentinfo"><section id="customize"><article><h3>Customize</h3><label><p>Site Colours<!-- -->:</p><div class="switch-wrap"><select name="colours"><option value="system" selected="">System</option><option value="force-light">Always Light</option><option value="force-dark">Always Dark</option></select></div></label><label><p>Code Font<!-- -->:</p><div class="switch-wrap"><select name="font"><option value="cascadia" selected="">Cascadia</option><option value="cascadia-ligatures">Cascadia (ligatures)</option><option value="consolas">Consolas</option><option value="dank-mono">Dank Mono</option><option value="fira-code">Fira Code</option><option value="jetbrains-mono">JetBrains Mono</option><option value="open-dyslexic">OpenDyslexic</option><option value="sf-mono">SF Mono</option><option value="source-code-pro">Source Code Pro</option></select></div></label></article></section><section id="popular"><h3>Popular Documentation Pages</h3><ul><li><a href="/docs/handbook/2/everyday-types.html">Everyday Types</a><p>All of the common types in TypeScript</p></li><li><a href="/docs/handbook/2/types-from-types.html">Creating Types from Types</a><p>Techniques to make more elegant types</p></li><li><a href="/docs/handbook/2/functions.html">More on Functions</a><p>How to provide types to functions in JavaScript</p></li><li><a href="/docs/handbook/2/objects.html">More on Objects</a><p>How to provide a type shape to JavaScript objects</p></li><li><a href="/docs/handbook/2/narrowing.html">Narrowing</a><p>How TypeScript infers types based on runtime behavior</p></li><li><a href="/docs/handbook/variable-declarations.html">Variable Declarations</a><p>How to create and type JavaScript variables</p></li><li><a href="/docs/handbook/typescript-in-5-minutes.html">TypeScript in 5 minutes</a><p>An overview of building a TypeScript web app</p></li><li><a href="/tsconfig/">TSConfig Options</a><p>All the configuration options for a project</p></li><li><a href="/docs/handbook/2/classes.html">Classes</a><p>How to provide types to JavaScript ES6 classes</p></li></ul></section><section id="community"><article id="logos"><svg fill="none" height="26" viewBox="0 0 26 26" width="26" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m.975 0h24.05c.5385 0 .975.436522.975.975v24.05c0 .5385-.4365.975-.975.975h-24.05c-.538478 0-.975-.4365-.975-.975v-24.05c0-.538478.436522-.975.975-.975zm13.4782 13.8324v-2.1324h-9.2532v2.1324h3.30357v9.4946h2.62983v-9.4946zm1.0485 9.2439c.4241.2162.9257.3784 1.5048.4865.579.1081 1.1893.1622 1.8309.1622.6253 0 1.2193-.0595 1.782-.1784.5628-.1189 1.0562-.3149 1.4803-.5879s.7598-.6297 1.0072-1.0703.3711-.9852.3711-1.6339c0-.4703-.0707-.8824-.212-1.2365-.1414-.3541-.3453-.669-.6117-.9447s-.5859-.523-.9583-.7419c-.3725-.2189-.7925-.4257-1.2601-.6203-.3425-.1406-.6497-.2771-.9216-.4095-.2718-.1324-.5029-.2676-.6932-.4054-.1903-.1379-.3371-.2838-.4404-.4379-.1033-.154-.155-.3284-.155-.523 0-.1784.0463-.3392.1387-.4824.0924-.1433.2229-.2663.3915-.369.1685-.1027.3751-.1824.6198-.2392.2447-.0567.5165-.0851.8156-.0851.2174 0 .4472.0162.6891.0486.242.0325.4853.0825.7299.15.2447.0676.4826.1527.7137.2555.2311.1027.4445.2216.6402.3567v-2.4244c-.3969-.1514-.8305-.2636-1.3008-.3365-.4704-.073-1.01-.1095-1.6189-.1095-.6199 0-1.2071.0662-1.7617.1987-.5546.1324-1.0425.3392-1.4639.6203s-.7544.6392-.9991 1.0743c-.2447.4352-.367.9555-.367 1.5609 0 .7731.2243 1.4326.6729 1.9785.4485.546 1.1295 1.0082 2.043 1.3866.3588.146.6932.2892 1.0031.4298.3099.1405.5777.2865.8033.4378.2257.1514.4037.3162.5342.4946s.1958.3811.1958.6082c0 .1676-.0408.323-.1224.4662-.0815.1433-.2052.2676-.371.373-.1659.1054-.3725.1879-.6199.2473-.2474.0595-.5369.0892-.8686.0892-.5654 0-1.1254-.0986-1.68-.2959s-1.0684-.4933-1.5415-.8879z" fill="#fff" fill-rule="evenodd"></path></svg><svg class="typescript-long" fill="none" height="25" viewBox="0 0 105 25" width="105" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m52.8777 17.6304v-1.4159c1.2926.8186 2.6019 1.228 3.9281 1.228 1.41 0 2.4802-.2903 3.2104-.8709s1.0953-1.393 1.0953-2.4372c0-.9189-.2455-1.6519-.7365-2.1991-.4735-.5276-1.4796-1.2397-3.0184-2.13631l-.1732-.10038c-1.8297-1.06092-2.988-1.94849-3.4748-2.66273-.4868-.71425-.7302-1.53916-.7302-2.47478 0-1.26976.4952-2.34737 1.4856-3.23287.9904-.88549 2.3124-1.32823 3.9659-1.32823 1.0743 0 2.1486.179602 3.223.538812v1.303168c-1.0576-.47616-2.1865-.71423-3.3867-.71423-1.2254 0-2.197.30908-2.9146.92725-.7176.61818-1.0764 1.40341-1.0764 2.35574 0 .9189.2455 1.64984.7365 2.19283.491.543 1.5506 1.28229 3.1789 2.2179 1.6871.95233 2.8097 1.79813 3.3678 2.53743.5582.7393.8373 1.5893.8373 2.55 0 1.3783-.4805 2.5019-1.4416 3.3707-.961.8687-2.3186 1.3031-4.0728 1.3031-.6211 0-1.3366-.096-2.1466-.2882-.8099-.1921-1.4289-.4135-1.857-.6641zm-44.74534-14.7957h5.16264v-2.532528h-13.295v2.532528h5.15008v15.4459h2.98228zm9.92154 17.5014 5.8166-14.89726h-2.9461l-3.223 9.35466c-.0764.2868-.1363.5202-.1798.7005l-.0468.2024h-.0629c-.0672-.2867-.1206-.5105-.1604-.6715l-.0663-.2565-3.0719-9.32956h-3.2356l5.1241 12.81566-.8687 2.1067c-.5372 1.07-1.3513 1.6051-2.4425 1.6051-.3777 0-.7973-.0753-1.259-.2258v2.4202c.4113.1087.9233.163 1.536.163 2.1823 0 3.8777-1.3292 5.0863-3.9876zm10.5978-3.9583h-.0503v7.7948h-2.918v-18.73516h2.918v2.25574h.0503c.9978-1.70435 2.4567-2.55651 4.3769-2.55651 1.635 0 2.9095.57229 3.8235 1.71687.9139 1.14459 1.3709 2.68182 1.3709 4.61176 0 2.1388-.5157 3.8515-1.547 5.1381s-2.44 1.9299-4.226 1.9299c-1.6434 0-2.9095-.7185-3.7983-2.1555zm-.0978-3.4018v-1.583c0-1.0968.3163-2.0109.9488-2.74216.6325-.73125 1.4681-1.09688 2.5069-1.09688.9802 0 1.7572.35524 2.331 1.06572.5739.71049.8608 1.69312.8608 2.94792 0 1.4957-.3078 2.6611-.9236 3.4963-.6157.8351-1.4639 1.2527-2.5446 1.2527-.9215 0-1.6818-.3241-2.2808-.9723-.599-.6481-.8985-1.4376-.8985-2.3683zm22.813-.3261h-8.703c.0332 1.1874.3969 2.103 1.091 2.7469s1.6479.9658 2.8615.9658c1.3632 0 2.6142-.4097 3.753-1.2292v2.3455c-1.1637.7359-2.7015 1.1038-4.6133 1.1038-1.8786 0-3.352-.5832-4.4201-1.7497s-1.6022-2.8075-1.6022-4.9231c0-1.99856.5881-3.62703 1.7643-4.88552 1.1762-1.25848 2.6371-1.88771 4.3827-1.88771s3.0963.56443 4.0522 1.6933 1.4339 2.69672 1.4339 4.70363zm-3.4528-4.52311c.4806.58334.7251 1.39958.7334 2.44871h-5.8921c.1326-.99038.4869-1.79193 1.0628-2.40464.576-.61272 1.2783-.91907 2.107-.91907.8453 0 1.5082.29166 1.9889.875zm21.8704 10.45591c1.3315 0 2.4776-.2921 3.4383-.8764v-1.2018c-.9607.6844-2.0899 1.0266-3.3878 1.0266-1.4157 0-2.5555-.505-3.4193-1.5149s-1.2957-2.3453-1.2957-4.0063c0-1.7193.4719-3.11943 1.4158-4.2003.9438-1.08086 2.1742-1.62128 3.6911-1.62128 1.104 0 2.1195.28377 3.0465.85133v-1.30204c-.927-.40063-1.8835-.60094-2.8695-.60094-1.9046 0-3.4636.64893-4.6771 1.9468-1.2136 1.29787-1.8203 2.96503-1.8203 5.00153 0 1.9364.5393 3.5034 1.618 4.7012 1.0787 1.1977 2.4987 1.7965 4.26 1.7965zm11.0428-11.9856c-.3837-.27698-.8341-.41547-1.3512-.41547-1.0093 0-1.8559.52458-2.5399 1.57375-.684 1.04916-1.026 2.53892-1.026 4.46942v6.0558h-1.126v-12.89213h1.126v2.85791h.0501c.2919-.98202.7548-1.7458 1.3888-2.29136.6339-.54557 1.3679-.81835 2.202-.81835.4755 0 .9009.07554 1.2762.22662zm1.8042-4.61517c.1955.18952.4208.28427.6759.28427.2721 0 .5059-.09906.7014-.29719.1956-.19812.2934-.43501.2934-.71067 0-.292879-.0999-.525459-.2997-.697743s-.4315-.258425-.6951-.258425c-.2466 0-.4698.088294-.6696.264885-.1998.176592-.2997.407018-.2997.691283 0 .29289.0978.53408.2934.72359zm.0088 16.29867v-12.84176h1.2086v12.84176zm5.0798-2.2859h.0501c.9181 1.7283 2.337 2.5924 4.2566 2.5924 1.7194 0 3.1028-.6617 4.1502-1.985 1.0475-1.3234 1.5712-3.0579 1.5712-5.2036 0-1.92865-.4569-3.45443-1.3709-4.5774-.9139-1.12296-2.1846-1.68443-3.8121-1.68443-1.0266 0-1.9677.25673-2.8232.77021-.8555.51347-1.5127 1.24192-1.9718 2.18538h-.0501v-2.6425h-1.1517v18.72284h1.1517zm.0569-4.7728v1.6133c0 1.284.4088 2.3867 1.2264 3.308s1.8923 1.382 3.2241 1.382c1.3233 0 2.398-.5607 3.2241-1.6822.826-1.1214 1.239-2.5951 1.239-4.421 0-1.60088-.3793-2.87236-1.1379-3.81453-.7586-.94216-1.7701-1.41324-3.0344-1.41324-1.5088 0-2.6762.50026-3.5023 1.50079-.826 1.00053-1.239 2.17613-1.239 3.52688zm15.542 7.3608c.523 0 1.083-.1417 1.681-.4252v-1.0754c-.548.3084-1.058.4627-1.532.4627-.664 0-1.135-.198-1.413-.594s-.417-1.0359-.417-1.9196v-8.45368h3.362v-1.05046h-3.362v-3.71411c-.183.06669-.373.12922-.573.18758-.199.06669-.39.13339-.572.20009v3.32644h-2.2916v1.05046h2.2916v8.60378c0 2.2676.942 3.4014 2.826 3.4014z" fill="#fff" fill-rule="evenodd"></path></svg><p>Made with ♥ in Redmond, Boston, SF & Dublin</p><a href=""><img id="microsoft-logo" width="92" height="19" src="data:image/png;base64,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" alt="Microsoft Logo"/></a><p>© 2012-<!-- -->2025<!-- --> Microsoft<br/><a href="https://go.microsoft.com/fwlink/?LinkId=521839" title="Microsoft Privacy Policy">Privacy</a><a href="https://go.microsoft.com/fwlink/?LinkID=206977">Terms of Use</a></p></article><article id="using-typescript"><h3>Using TypeScript</h3><ul><li><a href="/docs/">Get Started</a></li><li><a href="/download/">Download</a></li><li><a href="/community/">Community</a></li><li><a to="/play/" href="/play/">Playground</a></li><li><a href="/tsconfig/">TSConfig Ref</a></li><li><a to="/play/#show-examples" href="/play/#show-examples">Code Samples</a></li><li><a href="/why-create-typescript/">Why TypeScript</a></li><li><a href="/branding/">Design</a></li></ul></article><article id="community-links"><h3>Community</h3><ul><li><a style="position:relative" href="/community">Get Help</a></li><li><a style="position:relative" href="https://devblogs.microsoft.com/typescript/">Blog</a></li><li><a style="position:relative" href="https://github.com/microsoft/TypeScript/#readme"><span class="link-prefix"><svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m6.03927.165405c-3.27055 0-5.922909 2.652005-5.922909 5.923645 0 2.61709 1.697089 4.83705 4.050909 5.62035.29636.0546.40436-.1284.40436-.2854 0-.1408-.00509-.5131-.008-1.0073-1.64763.3578-1.99527-.7942-1.99527-.7942-.26946-.68436-.65782-.86654-.65782-.86654-.53782-.36727.04073-.36001.04073-.36001.59454.04182.90727.61055.90727.61055.52836.90509 1.38655.64364 1.724.492.05382-.38254.20691-.64363.376-.79163-1.31527-.14946-2.69818-.65782-2.69818-2.92764 0-.64654.23091-1.17564.60982-1.58946-.06109-.14981-.26437-.75236.05818-1.56763 0 0 .49709-.15927 1.62872.60727.47237-.13163.97928-.19709 1.48291-.19964.50328.00255 1.00982.06801 1.48291.19964 1.13091-.76654 1.62727-.60727 1.62727-.60727.32328.81527.12001 1.41782.05928 1.56763.37964.41382.60873.94292.60873 1.58946 0 2.27564-1.38509 2.77636-2.70437 2.92291.21237.18291.40182.54436.40182 1.09672 0 .79204-.00727 1.43094-.00727 1.62514 0 .1585.10691.3429.40727.2851 2.35197-.7851 4.04767-3.00369 4.04767-5.62005 0-3.27164-2.6524-5.923645-5.92403-5.923645z" fill="#fffffe" fill-rule="evenodd"></path></svg></span>GitHub Repo</a></li><li><a style="position:relative" href="https://discord.gg/typescript"><span class="link-prefix"><svg fill="none" height="10" viewBox="0 0 11 10" width="11" xmlns="http://www.w3.org/2000/svg"><path d="m9.05511 0h-7.11021c-.59959 0-1.087753.46-1.087753 1.03v6.76c0 .57.488163 1.03 1.087753 1.03h6.01715l-.28123-.925.67918.595.64205.56 1.14085.95v-8.97c0-.57-.4882-1.03-1.08779-1.03zm-2.04817 6.53s-.19102-.215-.3502-.405c.6951-.185.96041-.595.96041-.595-.21755.135-.42449.23-.61021.295-.2653.105-.52.175-.76938.215-.50939.09-.97633.065-1.37429-.005-.30245-.055-.56245-.135-.78-.215-.12204-.045-.25469-.1-.38735-.17-.01592-.01-.03183-.015-.04775-.025-.01061-.005-.01592-.01-.02123-.015-.09551-.05-.14857-.085-.14857-.085s.2547.4.92857.59c-.15918.19-.35551.415-.35551.415-1.17265-.035-1.61836-.76-1.61836-.76 0-1.61.76408-2.915.76408-2.915.76408-.54 1.49102-.525 1.49102-.525l.05306.06c-.9551.26-1.39551.655-1.39551.655s.11673-.06.31306-.145c.56776-.235 1.01878-.3 1.20449-.315.03184-.005.05837-.01.0902-.01.32368-.04.6898-.05 1.07184-.01.50408.055 1.04531.195 1.59714.48 0 0-.41918-.375-1.32122-.635l.07428-.08s.72694-.015 1.49103.525c0 0 .76408 1.305.76408 2.915 0 0-.45102.725-1.62368.76z" fill="#fff"></path></svg></span>Community Chat</a></li><li><a style="position:relative" href="https://twitter.com/TypeScript"><span class="link-prefix"><svg fill="none" height="10" viewBox="0 0 13 10" width="13" xmlns="http://www.w3.org/2000/svg"><path d="m4.58519 10c4.62962 0 7.16291-3.83919 7.16291-7.16289 0-.10801 0-.21602-.0049-.32403.4909-.35348.918-.80024 1.2568-1.30591-.4517.20128-.9377.33384-1.4483.39766.5204-.30929.9181-.805148 1.1095-1.394284-.486.289658-1.026.495856-1.6004.608773-.4615-.490946-1.11448-.7953322-1.83617-.7953322-1.38938 0-2.51856 1.1291732-2.51856 2.5185532 0 .19638.02455.38785.06383.57441-2.09143-.1031-3.94721-1.10954-5.1893-2.631474-.21602.373119-.33876.805154-.33876 1.266644 0 .87388.44677 1.64467 1.11936 2.09634-.41239-.01473-.80024-.12765-1.13899-.31421v.03437c0 1.21754.86897 2.23871 2.01778 2.46946-.2111.05891-.43203.08837-.66277.08837-.16202 0-.31912-.01473-.47131-.04419.31911 1.00153 1.25191 1.72813 2.35163 1.74777-.86406.67751-1.94906 1.08008-3.12733 1.08008-.20128 0-.402571-.00982-.59895-.03436 1.10954.70696 2.43509 1.12425 3.85393 1.12425z" fill="#fff"></path></svg></span>@TypeScript</a></li><li><a style="position:relative" href="https://fosstodon.org/@TypeScript" rel="me"><span class="link-prefix"><svg fill="none" height="12" viewBox="0 0 74 79" width="12" xmlns="http://www.w3.org/2000/svg"><path d="M73.7014 17.4323C72.5616 9.05152 65.1774 2.4469 56.424 1.1671C54.9472 0.950843 49.3518 0.163818 36.3901 0.163818H36.2933C23.3281 0.163818 20.5465 0.950843 19.0697 1.1671C10.56 2.41145 2.78877 8.34604 0.903306 16.826C-0.00357854 21.0022 -0.100361 25.6322 0.068112 29.8793C0.308275 35.9699 0.354874 42.0498 0.91406 48.1156C1.30064 52.1448 1.97502 56.1419 2.93215 60.0769C4.72441 67.3445 11.9795 73.3925 19.0876 75.86C26.6979 78.4332 34.8821 78.8603 42.724 77.0937C43.5866 76.8952 44.4398 76.6647 45.2833 76.4024C47.1867 75.8033 49.4199 75.1332 51.0616 73.9562C51.0841 73.9397 51.1026 73.9184 51.1156 73.8938C51.1286 73.8693 51.1359 73.8421 51.1368 73.8144V67.9366C51.1364 67.9107 51.1302 67.8852 51.1186 67.862C51.1069 67.8388 51.0902 67.8184 51.0695 67.8025C51.0489 67.7865 51.0249 67.7753 50.9994 67.7696C50.9738 67.764 50.9473 67.7641 50.9218 67.7699C45.8976 68.9569 40.7491 69.5519 35.5836 69.5425C26.694 69.5425 24.3031 65.3699 23.6184 63.6327C23.0681 62.1314 22.7186 60.5654 22.5789 58.9744C22.5775 58.9477 22.5825 58.921 22.5934 58.8965C22.6043 58.8721 22.621 58.8505 22.6419 58.8336C22.6629 58.8167 22.6876 58.8049 22.714 58.7992C22.7404 58.7934 22.7678 58.794 22.794 58.8007C27.7345 59.9796 32.799 60.5746 37.8813 60.5733C39.1036 60.5733 40.3223 60.5733 41.5447 60.5414C46.6562 60.3996 52.0437 60.1408 57.0728 59.1694C57.1983 59.1446 57.3237 59.1233 57.4313 59.0914C65.3638 57.5847 72.9128 52.8555 73.6799 40.8799C73.7086 40.4084 73.7803 35.9415 73.7803 35.4523C73.7839 33.7896 74.3216 23.6576 73.7014 17.4323ZM61.4925 47.3144H53.1514V27.107C53.1514 22.8528 51.3591 20.6832 47.7136 20.6832C43.7061 20.6832 41.6988 23.2499 41.6988 28.3194V39.3803H33.4078V28.3194C33.4078 23.2499 31.3969 20.6832 27.3894 20.6832C23.7654 20.6832 21.9552 22.8528 21.9516 27.107V47.3144H13.6176V26.4937C13.6176 22.2395 14.7157 18.8598 16.9118 16.3545C19.1772 13.8552 22.1488 12.5719 25.8373 12.5719C30.1064 12.5719 33.3325 14.1955 35.4832 17.4394L37.5587 20.8853L39.6377 17.4394C41.7884 14.1955 45.0145 12.5719 49.2765 12.5719C52.9614 12.5719 55.9329 13.8552 58.2055 16.3545C60.4017 18.8574 61.4997 22.2371 61.4997 26.4937L61.4925 47.3144Z" fill="#fff"></path></svg></span>Mastodon</a></li><li><a style="position:relative" href="https://stackoverflow.com/questions/tagged/typescript"><span class="link-prefix"><svg fill="none" height="16" viewBox="0 0 12 16" width="12" xmlns="http://www.w3.org/2000/svg"><path d="m.375 15.1875v-6h1.09375l-.03125 4.8125h7.1875v-4.78125h1.125v5.96875zm1.75-3.1563h5.625v1.1876h-5.625zm.03125-.9374.09375-1.2188 5.65625.5312-.125 1.2188zm.28125-2.4688.34375-1.1875 5.46875 1.53125-.34375 1.18745zm1.03125-2.90625.625-1.0625 4.84375 2.9375-.65625 1.0625zm2.40625-2.9375 1-.71875 3.3125 4.625-1 .71875zm3.625-1.78125 1.1875-.1875.9375 5.59375-1.2188.1875z" fill="#fff"></path></svg></span>Stack Overflow</a></li><li><a style="position:relative" href="https://github.com/microsoft/TypeScript-Website"><span class="link-prefix"><svg fill="none" height="12" viewBox="0 0 12 12" width="12" xmlns="http://www.w3.org/2000/svg"><path clip-rule="evenodd" d="m6.03927.165405c-3.27055 0-5.922909 2.652005-5.922909 5.923645 0 2.61709 1.697089 4.83705 4.050909 5.62035.29636.0546.40436-.1284.40436-.2854 0-.1408-.00509-.5131-.008-1.0073-1.64763.3578-1.99527-.7942-1.99527-.7942-.26946-.68436-.65782-.86654-.65782-.86654-.53782-.36727.04073-.36001.04073-.36001.59454.04182.90727.61055.90727.61055.52836.90509 1.38655.64364 1.724.492.05382-.38254.20691-.64363.376-.79163-1.31527-.14946-2.69818-.65782-2.69818-2.92764 0-.64654.23091-1.17564.60982-1.58946-.06109-.14981-.26437-.75236.05818-1.56763 0 0 .49709-.15927 1.62872.60727.47237-.13163.97928-.19709 1.48291-.19964.50328.00255 1.00982.06801 1.48291.19964 1.13091-.76654 1.62727-.60727 1.62727-.60727.32328.81527.12001 1.41782.05928 1.56763.37964.41382.60873.94292.60873 1.58946 0 2.27564-1.38509 2.77636-2.70437 2.92291.21237.18291.40182.54436.40182 1.09672 0 .79204-.00727 1.43094-.00727 1.62514 0 .1585.10691.3429.40727.2851 2.35197-.7851 4.04767-3.00369 4.04767-5.62005 0-3.27164-2.6524-5.923645-5.92403-5.923645z" fill="#fffffe" fill-rule="evenodd"></path></svg></span>Web Repo</a></li></ul></article></section></footer><div class="page-popup" id="language-recommendation" style="display:none"><p id="language-recommendation-p">MSG</p><div><button class="first" id="language-recommendation-open"></button><button id="language-recommendation-no-more"></button></div></div></div></div><div id="gatsby-announcer" style="position:absolute;top:0;width:1px;height:1px;padding:0;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0" aria-live="assertive" aria-atomic="true"></div></div><script id="gatsby-script-loader">/*<![CDATA[*/window.pagePath="/docs/handbook/release-notes/typescript-4-1.html";/*]]>*/</script><!-- slice-start id="_gatsby-scripts-1" --> <script id="gatsby-chunk-mapping" > window.___chunkMapping="{\"app\":[\"/app-edf8c7e07661945feb25.js\"],\"component---src-pages-branding-tsx\":[\"/component---src-pages-branding-tsx-70fb0975cfae2007b7dd.js\"],\"component---src-pages-dev-bug-workbench-tsx\":[\"/component---src-pages-dev-bug-workbench-tsx-50e61789753c98eab349.js\"],\"component---src-pages-dev-playground-plugins-tsx\":[\"/component---src-pages-dev-playground-plugins-tsx-7f56014ac8fdffe5a07b.js\"],\"component---src-pages-dev-sandbox-tsx\":[\"/component---src-pages-dev-sandbox-tsx-8f04e4e41be05aceb4c9.js\"],\"component---src-pages-dev-twoslash-tsx\":[\"/component---src-pages-dev-twoslash-tsx-7b027c1a3f00ab5e69b1.js\"],\"component---src-pages-dev-typescript-vfs-tsx\":[\"/component---src-pages-dev-typescript-vfs-tsx-c0e869d1a2c68bba6b38.js\"],\"component---src-templates-documentation-tsx\":[\"/component---src-templates-documentation-tsx-e40b75c61b9730ac9857.js\"],\"component---src-templates-glossary-tsx\":[\"/component---src-templates-glossary-tsx-2432318b6b386a4eb710.js\"],\"component---src-templates-pages-cheatsheets-tsx\":[\"/component---src-templates-pages-cheatsheets-tsx-ea490f76867ffb2e61ed.js\"],\"component---src-templates-pages-community-tsx\":[\"/component---src-templates-pages-community-tsx-55d5b4cfda8af197f11f.js\"],\"component---src-templates-pages-docs-handbook-index-tsx\":[\"/component---src-templates-pages-docs-handbook-index-tsx-f37e927aa3506b4b569a.js\"],\"component---src-templates-pages-docs-index-tsx\":[\"/component---src-templates-pages-docs-index-tsx-0ee7a07c193c2a2aa88e.js\"],\"component---src-templates-pages-download-tsx\":[\"/component---src-templates-pages-download-tsx-79339437d944c47365b7.js\"],\"component---src-templates-pages-dt-search-tsx\":[\"/component---src-templates-pages-dt-search-tsx-3e8f89b32cbb914fb385.js\"],\"component---src-templates-pages-empty-tsx\":[\"/component---src-templates-pages-empty-tsx-aecc8dc483a68c649bb2.js\"],\"component---src-templates-pages-index-tsx\":[\"/component---src-templates-pages-index-tsx-ffacbbead9f54a935a30.js\"],\"component---src-templates-pages-tools-tsx\":[\"/component---src-templates-pages-tools-tsx-e3892f666965ceb7bc76.js\"],\"component---src-templates-pages-why-create-typescript-tsx\":[\"/component---src-templates-pages-why-create-typescript-tsx-fe1842e46889c557809d.js\"],\"component---src-templates-play-example-tsx\":[\"/component---src-templates-play-example-tsx-bb0065893ccfa8e76a13.js\"],\"component---src-templates-play-tsx\":[\"/component---src-templates-play-tsx-b1715b37d1f387064335.js\"],\"component---src-templates-playground-handbook-tsx\":[\"/component---src-templates-playground-handbook-tsx-3498f04736f1849b4747.js\"],\"component---src-templates-tsconfig-option-one-page-tsx\":[\"/component---src-templates-tsconfig-option-one-page-tsx-93a12f355f24302e0943.js\"],\"component---src-templates-tsconfig-reference-tsx\":[\"/component---src-templates-tsconfig-reference-tsx-c6ba2c24f25e37564212.js\"]}"; </script> <script>window.___webpackCompilationHash="46d66040c19da06bc17c";</script><script src="/webpack-runtime-254a39ddba85c1e6aa25.js" async></script><script src="/app-edf8c7e07661945feb25.js" async></script><!-- slice-end id="_gatsby-scripts-1" --></body></html>