[{"data":1,"prerenderedAt":3017},["ShallowReactive",2],{"navigation-en":3,"content-urls":13,"pagesContext-en-2":224,"pagesContext-en-3":251,"authorsContext-en-jeroenbach":271,"postsContext-en-1-undefined":288},[4,7,10],{"label":5,"to":6},"Blog","\u002Fposts",{"label":8,"to":9},"Portfolio","\u002Fcontent\u002F20-portfolio",{"label":11,"to":12},"About","\u002Fcontent\u002F30-about",{"page":14,"blogPost":101,"blog":223},{"1":15,"10":37,"20":51,"30":65,"404":82},{"en":16,"fr":25,"nl":28,"de":31,"es":34},{"title":17,"path":18,"stem":19,"contentId":20,"url":21,"dateModified":22,"locale":23,"type":24},"Home","\u002Fcontent\u002Fhome","content\u002F1.home",1,"","2025-11-02T18:00:00","en","page",{"title":17,"path":18,"stem":19,"contentId":20,"url":26,"dateModified":22,"locale":27,"type":24},"\u002Ffr","fr",{"title":17,"path":18,"stem":19,"contentId":20,"url":29,"dateModified":22,"locale":30,"type":24},"\u002Fnl","nl",{"title":17,"path":18,"stem":19,"contentId":20,"url":32,"dateModified":22,"locale":33,"type":24},"\u002Fde","de",{"title":17,"path":18,"stem":19,"contentId":20,"url":35,"dateModified":22,"locale":36,"type":24},"\u002Fes","es",{"en":38,"fr":43,"nl":45,"de":47,"es":49},{"title":5,"path":39,"stem":40,"contentId":41,"url":6,"dateModified":42,"locale":23,"type":24},"\u002Fcontent\u002Fposts","content\u002F10.posts",10,"2025-10-26T18:00:00",{"title":5,"path":39,"stem":40,"contentId":41,"url":44,"dateModified":42,"locale":27,"type":24},"\u002Ffr\u002Farticles",{"title":5,"path":39,"stem":40,"contentId":41,"url":46,"dateModified":42,"locale":30,"type":24},"\u002Fnl\u002Fposts",{"title":5,"path":39,"stem":40,"contentId":41,"url":48,"dateModified":42,"locale":33,"type":24},"\u002Fde\u002Fposts",{"title":5,"path":39,"stem":40,"contentId":41,"url":50,"dateModified":42,"locale":36,"type":24},"\u002Fes\u002Farticulos",{"en":52,"fr":56,"nl":58,"de":60,"es":62},{"title":8,"path":53,"stem":54,"contentId":55,"url":9,"dateModified":42,"locale":23,"type":24},"\u002Fcontent\u002Fportfolio","content\u002F20.portfolio",20,{"title":8,"path":53,"stem":54,"contentId":55,"url":57,"dateModified":42,"locale":27,"type":24},"\u002Ffr\u002Fcontent\u002F20-portfolio",{"title":8,"path":53,"stem":54,"contentId":55,"url":59,"dateModified":42,"locale":30,"type":24},"\u002Fnl\u002Fcontent\u002F20-portfolio",{"title":8,"path":53,"stem":54,"contentId":55,"url":61,"dateModified":42,"locale":33,"type":24},"\u002Fde\u002Fcontent\u002F20-portfolio",{"title":63,"path":53,"stem":54,"contentId":55,"url":64,"dateModified":42,"locale":36,"type":24},"Portafolio","\u002Fes\u002Fcontent\u002F20-portafolio",{"en":66,"fr":70,"nl":73,"de":76,"es":79},{"title":11,"path":67,"stem":68,"contentId":69,"url":12,"dateModified":42,"locale":23,"type":24},"\u002Fcontent\u002Fabout","content\u002F30.about",30,{"title":71,"path":67,"stem":68,"contentId":69,"url":72,"dateModified":42,"locale":27,"type":24},"À propos","\u002Ffr\u002Fcontent\u002F30-a-propos",{"title":74,"path":67,"stem":68,"contentId":69,"url":75,"dateModified":42,"locale":30,"type":24},"Over","\u002Fnl\u002Fcontent\u002F30-over",{"title":77,"path":67,"stem":68,"contentId":69,"url":78,"dateModified":42,"locale":33,"type":24},"Über mich","\u002Fde\u002Fcontent\u002F30-uber-mich",{"title":80,"path":67,"stem":68,"contentId":69,"url":81,"dateModified":42,"locale":36,"type":24},"Acerca de","\u002Fes\u002Fcontent\u002F30-acerca-de",{"en":83,"fr":89,"nl":92,"de":95,"es":98},{"title":84,"path":85,"stem":86,"contentId":87,"url":88,"dateModified":22,"locale":23,"type":24},"Page not found","\u002Fcontent\u002Fpage-not-found","content\u002F404.page-not-found",404,"\u002Fcontent\u002F404-page-not-found",{"title":90,"path":85,"stem":86,"contentId":87,"url":91,"dateModified":22,"locale":27,"type":24},"Page non trouvée","\u002Ffr\u002Fcontent\u002F404-page-non-trouvee",{"title":93,"path":85,"stem":86,"contentId":87,"url":94,"dateModified":22,"locale":30,"type":24},"Pagina niet gevonden","\u002Fnl\u002Fcontent\u002F404-pagina-niet-gevonden",{"title":96,"path":85,"stem":86,"contentId":87,"url":97,"dateModified":22,"locale":33,"type":24},"Seite nicht gefunden","\u002Fde\u002Fcontent\u002F404-seite-nicht-gefunden",{"title":99,"path":85,"stem":86,"contentId":87,"url":100,"dateModified":22,"locale":36,"type":24},"Página no encontrada","\u002Fes\u002Fcontent\u002F404-pagina-no-encontrada",{"1":102,"2":126,"3":150,"4":175,"5":199},{"en":103,"fr":110,"nl":115,"de":118,"es":121},{"title":104,"path":105,"stem":106,"contentId":20,"dateModified":107,"url":108,"locale":23,"type":109},"Mastering Conditional Property Types with Vue 3.3 Generics","\u002Fposts\u002F1","posts\u002F1","2025-05-27T11:30:00","\u002Fposts\u002F1-mastering-conditional-property-types-with-vue-3_3-generics","blogPost",{"title":111,"path":112,"stem":113,"contentId":20,"dateModified":107,"url":114,"locale":27,"type":109},"Maîtriser les types de propriétés conditionnelles avec les génériques de Vue 3.3","\u002Farticles\u002F1","articles\u002F1","\u002Ffr\u002Farticles\u002F1-maitriser-les-types-de-proprietes-conditionnelles-avec-les-generiques-de-vue-3_3",{"title":116,"path":105,"stem":106,"contentId":20,"dateModified":107,"url":117,"locale":30,"type":109},"Conditionele Property Types beheersen met Vue 3.3 Generics","\u002Fnl\u002Fposts\u002F1-conditionele-property-types-beheersen-met-vue-3_3-generics",{"title":119,"path":105,"stem":106,"contentId":20,"dateModified":107,"url":120,"locale":33,"type":109},"Bedingte Property-Typen mit Vue 3.3 Generics meistern","\u002Fde\u002Fposts\u002F1-bedingte-property-typen-mit-vue-3_3-generics-meistern",{"title":122,"path":123,"stem":124,"contentId":20,"dateModified":107,"url":125,"locale":36,"type":109},"Dominar los tipos de propiedades condicionales con genéricos de Vue 3.3","\u002Farticulos\u002F1","articulos\u002F1","\u002Fes\u002Farticulos\u002F1-dominar-los-tipos-de-propiedades-condicionales-con-genericos-de-vue-3_3",{"en":127,"fr":134,"nl":139,"de":142,"es":145},{"title":128,"path":129,"stem":130,"contentId":131,"dateModified":132,"url":133,"locale":23,"type":109},"Ditching the Cookie Banners: Run Plausible Analytics on Azure Kubernetes","\u002Fposts\u002F2","posts\u002F2",2,"2025-10-04T13:00:00","\u002Fposts\u002F2-ditching-the-cookie-banners:-run-plausible-analytics-on-azure-kubernetes",{"title":135,"path":136,"stem":137,"contentId":131,"dateModified":132,"url":138,"locale":27,"type":109},"Éliminer les bannières de cookies: Exécutez Plausible Analytics sur Azure Kubernetes","\u002Farticles\u002F2","articles\u002F2","\u002Ffr\u002Farticles\u002F2-eliminer-les-bannieres-de-cookies:-executez-plausible-analytics-sur-azure-kubernetes",{"title":140,"path":129,"stem":130,"contentId":131,"dateModified":132,"url":141,"locale":30,"type":109},"Afscheid van Cookie Banners: Draai Plausible Analytics op Azure Kubernetes","\u002Fnl\u002Fposts\u002F2-afscheid-van-cookie-banners:-draai-plausible-analytics-op-azure-kubernetes",{"title":143,"path":129,"stem":130,"contentId":131,"dateModified":132,"url":144,"locale":33,"type":109},"Abschied von Cookie-Bannern: Plausible Analytics auf Azure Kubernetes betreiben","\u002Fde\u002Fposts\u002F2-abschied-von-cookie-bannern:-plausible-analytics-auf-azure-kubernetes-betreiben",{"title":146,"path":147,"stem":148,"contentId":131,"dateModified":132,"url":149,"locale":36,"type":109},"Eliminar los banners de cookies: Ejecuta Plausible Analytics en Azure Kubernetes","\u002Farticulos\u002F2","articulos\u002F2","\u002Fes\u002Farticulos\u002F2-eliminar-los-banners-de-cookies:-ejecuta-plausible-analytics-en-azure-kubernetes",{"en":151,"fr":158,"nl":164,"de":167,"es":170},{"title":152,"path":153,"stem":154,"contentId":155,"dateModified":156,"url":157,"locale":23,"type":109},"Track how many people read your articles, using Plausible.io, Vue.js and Azure functions","\u002Fposts\u002F3","posts\u002F3",3,"2025-08-03T15:45:00","\u002Fposts\u002F3-track-how-many-people-read-your-articles-using-plausible_io-vue_js-and-azure-functions",{"title":159,"path":160,"stem":161,"contentId":155,"dateModified":162,"url":163,"locale":27,"type":109},"Suivez combien de personnes lisent vos articles, en utilisant Plausible.io, Vue.js et Azure Functions","\u002Farticles\u002F3","articles\u002F3","2025-08-15:45:00","\u002Ffr\u002Farticles\u002F3-suivez-combien-de-personnes-lisent-vos-articles-en-utilisant-plausible_io-vue_js-et-azure-functions",{"title":165,"path":153,"stem":154,"contentId":155,"dateModified":156,"url":166,"locale":30,"type":109},"Volg hoeveel mensen je artikelen lezen, met Plausible.io, Vue.js en Azure functions","\u002Fnl\u002Fposts\u002F3-volg-hoeveel-mensen-je-artikelen-lezen-met-plausible_io-vue_js-en-azure-functions",{"title":168,"path":153,"stem":154,"contentId":155,"dateModified":156,"url":169,"locale":33,"type":109},"Verfolgen Sie, wie viele Menschen Ihre Artikel lesen, mit Plausible.io, Vue.js und Azure Functions","\u002Fde\u002Fposts\u002F3-verfolgen-sie-wie-viele-menschen-ihre-artikel-lesen-mit-plausible_io-vue_js-und-azure-functions",{"title":171,"path":172,"stem":173,"contentId":155,"dateModified":156,"url":174,"locale":36,"type":109},"Rastrea cuántas personas leen tus artículos, usando Plausible.io, Vue.js y funciones de Azure","\u002Farticulos\u002F3","articulos\u002F3","\u002Fes\u002Farticulos\u002F3-rastrea-cuantas-personas-leen-tus-articulos-usando-plausible_io-vue_js-y-funciones-de-azure",{"en":176,"fr":183,"nl":188,"de":191,"es":194},{"title":177,"path":178,"stem":179,"contentId":180,"dateModified":181,"url":182,"locale":23,"type":109},"Deploy a production-ready Kubernetes Cluster on Azure with Terraform","\u002Fposts\u002F4","posts\u002F4",4,"2025-12-06T21:00:00","\u002Fposts\u002F4-deploy-a-production-ready-kubernetes-cluster-on-azure-with-terraform",{"title":184,"path":185,"stem":186,"contentId":180,"dateModified":181,"url":187,"locale":27,"type":109},"Déployer un cluster Kubernetes prêt pour la production sur Azure avec Terraform","\u002Farticles\u002F4","articles\u002F4","\u002Ffr\u002Farticles\u002F4-deployer-un-cluster-kubernetes-pret-pour-la-production-sur-azure-avec-terraform",{"title":189,"path":178,"stem":179,"contentId":180,"dateModified":181,"url":190,"locale":30,"type":109},"Implementeer een productie-klaar Kubernetes Cluster op Azure met Terraform","\u002Fnl\u002Fposts\u002F4-implementeer-een-productie-klaar-kubernetes-cluster-op-azure-met-terraform",{"title":192,"path":178,"stem":179,"contentId":180,"dateModified":181,"url":193,"locale":33,"type":109},"Einen produktionsreifen Kubernetes-Cluster auf Azure mit Terraform bereitstellen","\u002Fde\u002Fposts\u002F4-einen-produktionsreifen-kubernetes-cluster-auf-azure-mit-terraform-bereitstellen",{"title":195,"path":196,"stem":197,"contentId":180,"dateModified":181,"url":198,"locale":36,"type":109},"Despliega un clúster de Kubernetes listo para producción en Azure con Terraform","\u002Farticulos\u002F4","articulos\u002F4","\u002Fes\u002Farticulos\u002F4-despliega-un-cluster-de-kubernetes-listo-para-produccion-en-azure-con-terraform",{"en":200,"fr":207,"nl":212,"de":215,"es":218},{"title":201,"path":202,"stem":203,"contentId":204,"dateModified":205,"url":206,"locale":23,"type":109},"Array to Map conversion in Typescript, with type safety","\u002Fposts\u002F5","posts\u002F5",5,"2025-09-29T21:00:00","\u002Fposts\u002F5-array-to-map-conversion-in-typescript-with-type-safety",{"title":208,"path":209,"stem":210,"contentId":204,"dateModified":205,"url":211,"locale":27,"type":109},"Conversion de tableau en Map en Typescript, avec sécurité des types","\u002Farticles\u002F5","articles\u002F5","\u002Ffr\u002Farticles\u002F5-conversion-de-tableau-en-map-en-typescript-avec-securite-des-types",{"title":213,"path":202,"stem":203,"contentId":204,"dateModified":205,"url":214,"locale":30,"type":109},"Array naar Map conversie in Typescript, met type veiligheid","\u002Fnl\u002Fposts\u002F5-array-naar-map-conversie-in-typescript-met-type-veiligheid",{"title":216,"path":202,"stem":203,"contentId":204,"dateModified":205,"url":217,"locale":33,"type":109},"Array zu Map Konvertierung in TypeScript, mit Typsicherheit","\u002Fde\u002Fposts\u002F5-array-zu-map-konvertierung-in-typescript-mit-typsicherheit",{"title":219,"path":220,"stem":221,"contentId":204,"dateModified":205,"url":222,"locale":36,"type":109},"Conversión de Array a Map en Typescript, con seguridad de tipos","\u002Farticulos\u002F5","articulos\u002F5","\u002Fes\u002Farticulos\u002F5-conversion-de-array-a-map-en-typescript-con-seguridad-de-tipos",{},{"id":225,"title":226,"body":227,"canonicalUrl":236,"company":236,"contentId":131,"dateModified":236,"datePublished":236,"description":233,"draft":237,"enableProse":237,"excludeFromNavigation":237,"extension":238,"imageAlt":236,"imageUrl":236,"meta":239,"navigation":245,"partial":245,"path":246,"seo":247,"slug":236,"stem":248,"url":249,"__hash__":250},"pages_en\u002Fcontent\u002F_footer.md","About Jeroen Bach",{"type":228,"value":229,"toc":234},"minimark",[230],[231,232,233],"p",{},"Designed in Figma and built with Vue.js, Nuxt.js and Tailwind CSS.\nDeployed via Azure Static Web App and Azure Functions.\nWebsite analytics are powered by Plausible Analytics, deployed using Azure Kubernetes Service.",{"title":21,"searchDepth":131,"depth":131,"links":235},[],null,false,"md",{"readingTime":240},{"text":241,"minutes":242,"time":243,"words":244},"1 min read",0.16,9600,32,true,"\u002Fcontent\u002F_footer",{"title":226,"description":233},"content\u002F_footer","\u002Fcontent\u002F2-about-jeroen-bach","tgPfOB73xkNtsI3Ers_EH08FHEHR7ko45cqNiVgrM0s",{"id":252,"title":253,"body":254,"canonicalUrl":236,"company":236,"contentId":155,"dateModified":236,"datePublished":236,"description":258,"draft":237,"enableProse":237,"excludeFromNavigation":237,"extension":238,"imageAlt":236,"imageUrl":236,"meta":261,"navigation":245,"partial":245,"path":266,"seo":267,"slug":236,"stem":268,"url":269,"__hash__":270},"pages_en\u002Fcontent\u002F_footer-about.md","Footer About",{"type":228,"value":255,"toc":259},[256],[231,257,258],{},"I'm a Software Engineer and Team Lead with over 15 years of professional experience.\nI'm passionate about solving complex problems through simple, elegant solutions.\nThis blog is where I share techniques and insights for building great software, inspired by real-world projects.",{"title":21,"searchDepth":131,"depth":131,"links":260},[],{"readingTime":262},{"text":241,"minutes":263,"time":264,"words":265},0.205,12300,41,"\u002Fcontent\u002F_footer-about",{"description":258},"content\u002F_footer-about","\u002Fcontent\u002F3-footer-about","49ofD3QAU2eKgnsoCR9zQhGEP7EECAsjUJeOHSF1GJI",{"id":272,"company":273,"extension":277,"fullName":278,"github":279,"homePage":280,"imageUrl":276,"linkedIn":281,"meta":282,"role":283,"stem":284,"twitter":285,"userName":286,"__hash__":287},"authors_en\u002Fauthors\u002Fjeroenbach.yaml",{"name":274,"url":275,"imageUrl":276},"Bach.Software","https:\u002F\u002Fbach.software","\u002FJEROEN-_A7R5652-HD-SQUARE-zoom.jpg","yaml","Jeroen Bach","https:\u002F\u002Fgithub.com\u002Fjeroenbach","https:\u002F\u002Fbach.software\u002Fpages\u002Fabout","https:\u002F\u002Fwww.linkedin.com\u002Fin\u002Fjeroenbach\u002F",{},"Software Engineer \u002F Team Lead","authors\u002Fjeroenbach","https:\u002F\u002Fx.com\u002Fjeroenbach","jeroenbach","QjQ1vpL_EQbLZNaZdDNOjIkS-thm6oxHuAdoNIauNI8",{"id":289,"title":104,"authorName":286,"body":290,"canonicalUrl":236,"category":2985,"contentId":20,"dateModified":107,"datePublished":2986,"description":2987,"draft":237,"excerpt":2988,"extension":238,"imageAlt":2996,"imagePosition":236,"imageUrl":2997,"keywords":2998,"meta":3006,"navigation":245,"path":105,"readingTime":3007,"seo":3012,"slug":236,"stem":106,"url":108,"__hash__":3013,"author":3014},"posts_en\u002Fposts\u002F1.md",{"type":228,"value":291,"toc":2975},[292,303,309,315,318,323,326,330,333,336,340,457,478,655,665,668,704,707,923,945,949,959,1510,1518,1522,1528,1531,1534,2904,2907,2926,2930,2933,2944,2947,2957,2960,2963,2971],[231,293,294,295,299,300,302],{},"How can we change a property's type based on another property's value? For instance, return a single item by default, and an array of items when a ",[296,297,298],"code",{},"multiple"," property is set.\nTo demonstrate what I mean, see the recording below. Here, you can observe how the type changes based on the ",[296,301,298],{}," attribute.",[304,305],"post-image",{"alt":306,"css-class":307,"src":308},"Code example","aspect-[735\u002F520]","posts\u002F1\u002Fcode-example.gif",[231,310,311,312,314],{},"There are cases where you would like to reuse your component for both multi and single values. However, you don't want to introduce another property or emit event.\nFor example, with a Select\u002FMultiSelect component, you can make it smarter by allowing it to return an array of items when ",[296,313,298],{}," is specified and a single item when it is not.",[231,316,317],{},"Read further to see how I managed to achieve this by leveraging generics in Vue 3.3. Generics allowed me to dynamically change a property's type based on another property's value.",[319,320,322],"h2",{"id":321},"why-use-generics-in-vue-33","Why Use Generics in Vue 3.3?",[231,324,325],{},"Generics in Vue 3.3 allow for the creation of flexible and reusable components that can adapt to different scenarios. By using generics, you can conditionally modify the type of a property based on the provided parameters,\nreducing the need for redundant code or additional props. For example, think of a component that can handle both single and multiple values depending on a flag—this kind of flexibility, this makes components much more versatile and powerful.",[319,327,329],{"id":328},"understanding-the-concept","Understanding the Concept",[231,331,332],{},"TypeScript can automatically infer a generic type from a parameter in a generic function. This type can then be used to determine the type of another parameter or even the return type. By combining this with conditional typing, you can create a generic function that returns a different value based on the provided parameter.",[231,334,335],{},"Generics in components work similarly to those in regular functions. To understand this better, let's first work through an example using plain TypeScript before integrating it into our Vue component.",[319,337,339],{"id":338},"typescript-example","TypeScript Example",[341,342,346],"pre",{"className":343,"code":344,"language":345,"meta":21,"style":21},"language-typescript shiki shiki-themes github-light github-dark","\u002F\u002F We infer the return type from the argument type.\nfunction discovery\u003CT>(arg: T): T {\n  return arg;\n}\n\n\u002F\u002F String in, string out\nconst result = discovery('Hello, World!' as string);\n\u002F\u002F    ^ const result: string\n","typescript",[296,347,348,356,396,404,409,414,420,451],{"__ignoreMap":21},[349,350,352],"span",{"class":351,"line":20},"line",[349,353,355],{"class":354},"sJ8bj","\u002F\u002F We infer the return type from the argument type.\n",[349,357,358,362,366,370,373,376,380,383,386,389,391,393],{"class":351,"line":131},[349,359,361],{"class":360},"szBVR","function",[349,363,365],{"class":364},"sScJk"," discovery",[349,367,369],{"class":368},"sVt8B","\u003C",[349,371,372],{"class":364},"T",[349,374,375],{"class":368},">(",[349,377,379],{"class":378},"s4XuR","arg",[349,381,382],{"class":360},":",[349,384,385],{"class":364}," T",[349,387,388],{"class":368},")",[349,390,382],{"class":360},[349,392,385],{"class":364},[349,394,395],{"class":368}," {\n",[349,397,398,401],{"class":351,"line":155},[349,399,400],{"class":360},"  return",[349,402,403],{"class":368}," arg;\n",[349,405,406],{"class":351,"line":180},[349,407,408],{"class":368},"}\n",[349,410,411],{"class":351,"line":204},[349,412,413],{"emptyLinePlaceholder":245},"\n",[349,415,417],{"class":351,"line":416},6,[349,418,419],{"class":354},"\u002F\u002F String in, string out\n",[349,421,423,426,430,433,435,438,442,445,448],{"class":351,"line":422},7,[349,424,425],{"class":360},"const",[349,427,429],{"class":428},"sj4cs"," result",[349,431,432],{"class":360}," =",[349,434,365],{"class":364},[349,436,437],{"class":368},"(",[349,439,441],{"class":440},"sZZnC","'Hello, World!'",[349,443,444],{"class":360}," as",[349,446,447],{"class":428}," string",[349,449,450],{"class":368},");\n",[349,452,454],{"class":351,"line":453},8,[349,455,456],{"class":354},"\u002F\u002F    ^ const result: string\n",[231,458,459,460,463,464,467,468,471,472,474,475,477],{},"Now, we can narrow down the possibilities of this generic type by using ",[296,461,462],{},"extends",", which allows us to create a new conditional type based on specified options.\nIn the following example, I'm limiting the possibilities to just ",[296,465,466],{},"true"," and ",[296,469,470],{},"false",". As a result, it returns an array of values when ",[296,473,466],{}," and a single value when ",[296,476,470],{},".",[341,479,481],{"className":343,"code":480,"language":345,"meta":21,"style":21},"function discovery\u003CT extends boolean>(multiple: T) {\n  type ConditionalType = T extends false ? string : string[];\n  return (multiple ? ['item1', 'item2', 'item3'] : 'item1') as ConditionalType;\n}\n\n\u002F\u002F multiple = true\nconst multiple = discovery(true);\n\u002F\u002F    ^ const multiple: string[]\n\n\u002F\u002F multiple = false\nconst single = discovery(false);\n\u002F\u002F    ^ const single: string\n",[296,482,483,510,540,586,590,594,599,616,621,626,631,649],{"__ignoreMap":21},[349,484,485,487,489,491,493,496,499,501,503,505,507],{"class":351,"line":20},[349,486,361],{"class":360},[349,488,365],{"class":364},[349,490,369],{"class":368},[349,492,372],{"class":364},[349,494,495],{"class":360}," extends",[349,497,498],{"class":428}," boolean",[349,500,375],{"class":368},[349,502,298],{"class":378},[349,504,382],{"class":360},[349,506,385],{"class":364},[349,508,509],{"class":368},") {\n",[349,511,512,515,518,520,522,524,527,530,532,535,537],{"class":351,"line":131},[349,513,514],{"class":360},"  type",[349,516,517],{"class":364}," ConditionalType",[349,519,432],{"class":360},[349,521,385],{"class":364},[349,523,495],{"class":360},[349,525,526],{"class":428}," false",[349,528,529],{"class":360}," ?",[349,531,447],{"class":428},[349,533,534],{"class":360}," :",[349,536,447],{"class":428},[349,538,539],{"class":368},"[];\n",[349,541,542,544,547,550,553,556,559,562,564,567,570,572,575,578,581,583],{"class":351,"line":155},[349,543,400],{"class":360},[349,545,546],{"class":368}," (multiple ",[349,548,549],{"class":360},"?",[349,551,552],{"class":368}," [",[349,554,555],{"class":440},"'item1'",[349,557,558],{"class":368},", ",[349,560,561],{"class":440},"'item2'",[349,563,558],{"class":368},[349,565,566],{"class":440},"'item3'",[349,568,569],{"class":368},"] ",[349,571,382],{"class":360},[349,573,574],{"class":440}," 'item1'",[349,576,577],{"class":368},") ",[349,579,580],{"class":360},"as",[349,582,517],{"class":364},[349,584,585],{"class":368},";\n",[349,587,588],{"class":351,"line":180},[349,589,408],{"class":368},[349,591,592],{"class":351,"line":204},[349,593,413],{"emptyLinePlaceholder":245},[349,595,596],{"class":351,"line":416},[349,597,598],{"class":354},"\u002F\u002F multiple = true\n",[349,600,601,603,606,608,610,612,614],{"class":351,"line":422},[349,602,425],{"class":360},[349,604,605],{"class":428}," multiple",[349,607,432],{"class":360},[349,609,365],{"class":364},[349,611,437],{"class":368},[349,613,466],{"class":428},[349,615,450],{"class":368},[349,617,618],{"class":351,"line":453},[349,619,620],{"class":354},"\u002F\u002F    ^ const multiple: string[]\n",[349,622,624],{"class":351,"line":623},9,[349,625,413],{"emptyLinePlaceholder":245},[349,627,628],{"class":351,"line":41},[349,629,630],{"class":354},"\u002F\u002F multiple = false\n",[349,632,634,636,639,641,643,645,647],{"class":351,"line":633},11,[349,635,425],{"class":360},[349,637,638],{"class":428}," single",[349,640,432],{"class":360},[349,642,365],{"class":364},[349,644,437],{"class":368},[349,646,470],{"class":428},[349,648,450],{"class":368},[349,650,652],{"class":351,"line":651},12,[349,653,654],{"class":354},"\u002F\u002F    ^ const single: string\n",[231,656,657,658,661,662,664],{},"In this example, the ",[296,659,660],{},"discovery"," function takes a parameter ",[296,663,298],{},", which determines whether the return type is a single string or an array of strings.",[231,666,667],{},"This is great! When using this in a component however, we would also like the option to omit the parameter (attribute) completely. Like this:",[341,669,673],{"className":670,"code":671,"language":672,"meta":21,"style":21},"language-vue shiki shiki-themes github-light github-dark","\u003CMultiSelect ... \u002F>\n\n\u003CMultiSelect ... multiple \u002F>\n","vue",[296,674,675,686,690],{"__ignoreMap":21},[349,676,677,679,683],{"class":351,"line":20},[349,678,369],{"class":368},[349,680,682],{"class":681},"s9eBZ","MultiSelect",[349,684,685],{"class":368}," ... \u002F>\n",[349,687,688],{"class":351,"line":131},[349,689,413],{"emptyLinePlaceholder":245},[349,691,692,694,696,699,701],{"class":351,"line":155},[349,693,369],{"class":368},[349,695,682],{"class":681},[349,697,698],{"class":368}," ... ",[349,700,298],{"class":364},[349,702,703],{"class":368}," \u002F>\n",[231,705,706],{},"Let's enhance the usability of our function by allowing the argument to be omitted. To achieve this, we can mark the argument with a question mark (?) to denote that it is optional and add a third option to our conditional type: undefined.\nThis will ensure that if nothing is specified, the function returns a single item as well.",[341,708,710],{"className":343,"code":709,"language":345,"meta":21,"style":21},"function discovery\u003CT extends boolean | undefined>(multiple?: T) {\n  type ConditionalType = undefined extends T\n    ? string\n    : T extends false\n      ? string\n      : string[];\n  return (multiple ? ['item1', 'item2', 'item3'] : 'item1') as ConditionalType;\n}\n\n\u002F\u002F multiple = true\nconst multiple = discovery(true);\n\u002F\u002F    ^ const multiple: string[]\n\n\u002F\u002F multiple = false\nconst single = discovery(false);\n\u002F\u002F    ^ const single: string\n\n\u002F\u002F multiple not present\nconst defaultSingle = discovery();\n\u002F\u002F    ^ const defaultSingle: string\n",[296,711,712,743,758,766,778,785,794,828,832,836,840,856,860,865,870,887,892,897,903,918],{"__ignoreMap":21},[349,713,714,716,718,720,722,724,726,729,732,734,736,739,741],{"class":351,"line":20},[349,715,361],{"class":360},[349,717,365],{"class":364},[349,719,369],{"class":368},[349,721,372],{"class":364},[349,723,495],{"class":360},[349,725,498],{"class":428},[349,727,728],{"class":360}," |",[349,730,731],{"class":428}," undefined",[349,733,375],{"class":368},[349,735,298],{"class":378},[349,737,738],{"class":360},"?:",[349,740,385],{"class":364},[349,742,509],{"class":368},[349,744,745,747,749,751,753,755],{"class":351,"line":131},[349,746,514],{"class":360},[349,748,517],{"class":364},[349,750,432],{"class":360},[349,752,731],{"class":428},[349,754,495],{"class":360},[349,756,757],{"class":364}," T\n",[349,759,760,763],{"class":351,"line":155},[349,761,762],{"class":360},"    ?",[349,764,765],{"class":428}," string\n",[349,767,768,771,773,775],{"class":351,"line":180},[349,769,770],{"class":360},"    :",[349,772,385],{"class":364},[349,774,495],{"class":360},[349,776,777],{"class":428}," false\n",[349,779,780,783],{"class":351,"line":204},[349,781,782],{"class":360},"      ?",[349,784,765],{"class":428},[349,786,787,790,792],{"class":351,"line":416},[349,788,789],{"class":360},"      :",[349,791,447],{"class":428},[349,793,539],{"class":368},[349,795,796,798,800,802,804,806,808,810,812,814,816,818,820,822,824,826],{"class":351,"line":422},[349,797,400],{"class":360},[349,799,546],{"class":368},[349,801,549],{"class":360},[349,803,552],{"class":368},[349,805,555],{"class":440},[349,807,558],{"class":368},[349,809,561],{"class":440},[349,811,558],{"class":368},[349,813,566],{"class":440},[349,815,569],{"class":368},[349,817,382],{"class":360},[349,819,574],{"class":440},[349,821,577],{"class":368},[349,823,580],{"class":360},[349,825,517],{"class":364},[349,827,585],{"class":368},[349,829,830],{"class":351,"line":453},[349,831,408],{"class":368},[349,833,834],{"class":351,"line":623},[349,835,413],{"emptyLinePlaceholder":245},[349,837,838],{"class":351,"line":41},[349,839,598],{"class":354},[349,841,842,844,846,848,850,852,854],{"class":351,"line":633},[349,843,425],{"class":360},[349,845,605],{"class":428},[349,847,432],{"class":360},[349,849,365],{"class":364},[349,851,437],{"class":368},[349,853,466],{"class":428},[349,855,450],{"class":368},[349,857,858],{"class":351,"line":651},[349,859,620],{"class":354},[349,861,863],{"class":351,"line":862},13,[349,864,413],{"emptyLinePlaceholder":245},[349,866,868],{"class":351,"line":867},14,[349,869,630],{"class":354},[349,871,873,875,877,879,881,883,885],{"class":351,"line":872},15,[349,874,425],{"class":360},[349,876,638],{"class":428},[349,878,432],{"class":360},[349,880,365],{"class":364},[349,882,437],{"class":368},[349,884,470],{"class":428},[349,886,450],{"class":368},[349,888,890],{"class":351,"line":889},16,[349,891,654],{"class":354},[349,893,895],{"class":351,"line":894},17,[349,896,413],{"emptyLinePlaceholder":245},[349,898,900],{"class":351,"line":899},18,[349,901,902],{"class":354},"\u002F\u002F multiple not present\n",[349,904,906,908,911,913,915],{"class":351,"line":905},19,[349,907,425],{"class":360},[349,909,910],{"class":428}," defaultSingle",[349,912,432],{"class":360},[349,914,365],{"class":364},[349,916,917],{"class":368},"();\n",[349,919,920],{"class":351,"line":55},[349,921,922],{"class":354},"\u002F\u002F    ^ const defaultSingle: string\n",[231,924,925,926,929,930,933,934],{},"Note that we had to swap the check around when introducing undefined (",[296,927,928],{},"T extends undefined"," to ",[296,931,932],{},"undefined extends T","). To understand why, read: ",[935,936,939,940,942,943,549],"a",{":target":937,"href":938},"\\_blank","#why-swap-undefined-and-t-around","Extra: Why ",[296,941,932],{}," and not ",[296,944,928],{},[319,946,948],{"id":947},"applying-generics-in-vue-components","Applying Generics in Vue Components",[231,950,951,952,955,956,958],{},"Let's now apply this concept to a Vue component. We will create a ",[296,953,954],{},"VSelect"," component that can handle both single and multiple selections depending on a ",[296,957,298],{}," prop.",[960,961,962,1506],"code-group",{},[341,963,966],{"className":670,"code":964,"filename":965,"language":672,"meta":21,"style":21},"\u003Cscript lang=\"ts\" setup generic=\"TMultiple extends boolean | undefined\">\nimport { computed } from 'vue';\n\n\u002F\u002F Lets return the correct type based on the TMultiple value.\n\u002F\u002F - TMultiple === undefined => string\n\u002F\u002F - TMultiple === false => string\n\u002F\u002F - TMultiple === true => string[]\ntype TSingleOrMultiple = undefined extends TMultiple\n  ? string\n  : TMultiple extends false\n    ? string\n    : string[];\n\ninterface Props {\n  modelValue?: TSingleOrMultiple\n  options?: { key: string, value: string }[]\n  multiple?: TMultiple\n}\n\nconst props = defineProps\u003CProps>();\nconst emit = defineEmits\u003C{\n  (e: 'update:modelValue', value: TSingleOrMultiple): void\n}>();\n\n\u002F\u002F Note: an empty attribute will result in an empty string \"\" value, therefore we check for false and undefined explicitly\nconst isMultiple = computed(\n  () => props.multiple !== false && props.multiple !== undefined,\n);\n\nconst value = ref\u003Cany>(props.modelValue);\nwatch(value, v => emit('update:modelValue', v));\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cselect v-model=\"value\" :multiple=\"multiple\">\n    \u003Coption disabled value=\"\">\n      Please select {{ isMultiple ? \"multiple\" : \"one\" }}\n    \u003C\u002Foption>\n    \u003Coption v-for=\"{ key, value: optionValue } in options\" :key=\"key\" :value=\"key\">\n      {{ optionValue }}\n    \u003C\u002Foption>\n  \u003C\u002Fselect>\n\u003C\u002Ftemplate>\n","VSelect.vue",[296,967,968,1011,1027,1031,1036,1041,1046,1051,1068,1075,1087,1093,1101,1105,1115,1125,1154,1163,1167,1171,1191,1207,1236,1242,1247,1253,1269,1298,1303,1308,1328,1353,1362,1367,1377,1404,1425,1431,1441,1473,1479,1487,1497],{"__ignoreMap":21},[349,969,970,972,975,978,981,984,987,990,992,995,998,1000,1002,1004,1006,1008],{"class":351,"line":20},[349,971,369],{"class":368},[349,973,974],{"class":681},"script",[349,976,977],{"class":364}," lang",[349,979,980],{"class":368},"=",[349,982,983],{"class":440},"\"ts\"",[349,985,986],{"class":364}," setup",[349,988,989],{"class":364}," generic",[349,991,980],{"class":368},[349,993,994],{"class":440},"\"",[349,996,997],{"class":364},"TMultiple",[349,999,495],{"class":360},[349,1001,498],{"class":428},[349,1003,728],{"class":360},[349,1005,731],{"class":428},[349,1007,994],{"class":440},[349,1009,1010],{"class":368},">\n",[349,1012,1013,1016,1019,1022,1025],{"class":351,"line":131},[349,1014,1015],{"class":360},"import",[349,1017,1018],{"class":368}," { computed } ",[349,1020,1021],{"class":360},"from",[349,1023,1024],{"class":440}," 'vue'",[349,1026,585],{"class":368},[349,1028,1029],{"class":351,"line":155},[349,1030,413],{"emptyLinePlaceholder":245},[349,1032,1033],{"class":351,"line":180},[349,1034,1035],{"class":354},"\u002F\u002F Lets return the correct type based on the TMultiple value.\n",[349,1037,1038],{"class":351,"line":204},[349,1039,1040],{"class":354},"\u002F\u002F - TMultiple === undefined => string\n",[349,1042,1043],{"class":351,"line":416},[349,1044,1045],{"class":354},"\u002F\u002F - TMultiple === false => string\n",[349,1047,1048],{"class":351,"line":422},[349,1049,1050],{"class":354},"\u002F\u002F - TMultiple === true => string[]\n",[349,1052,1053,1056,1059,1061,1063,1065],{"class":351,"line":453},[349,1054,1055],{"class":360},"type",[349,1057,1058],{"class":364}," TSingleOrMultiple",[349,1060,432],{"class":360},[349,1062,731],{"class":428},[349,1064,495],{"class":360},[349,1066,1067],{"class":364}," TMultiple\n",[349,1069,1070,1073],{"class":351,"line":623},[349,1071,1072],{"class":360},"  ?",[349,1074,765],{"class":428},[349,1076,1077,1080,1083,1085],{"class":351,"line":41},[349,1078,1079],{"class":360},"  :",[349,1081,1082],{"class":364}," TMultiple",[349,1084,495],{"class":360},[349,1086,777],{"class":428},[349,1088,1089,1091],{"class":351,"line":633},[349,1090,762],{"class":360},[349,1092,765],{"class":428},[349,1094,1095,1097,1099],{"class":351,"line":651},[349,1096,770],{"class":360},[349,1098,447],{"class":428},[349,1100,539],{"class":368},[349,1102,1103],{"class":351,"line":862},[349,1104,413],{"emptyLinePlaceholder":245},[349,1106,1107,1110,1113],{"class":351,"line":867},[349,1108,1109],{"class":360},"interface",[349,1111,1112],{"class":364}," Props",[349,1114,395],{"class":368},[349,1116,1117,1120,1122],{"class":351,"line":872},[349,1118,1119],{"class":378},"  modelValue",[349,1121,738],{"class":360},[349,1123,1124],{"class":364}," TSingleOrMultiple\n",[349,1126,1127,1130,1132,1135,1138,1140,1142,1144,1147,1149,1151],{"class":351,"line":889},[349,1128,1129],{"class":378},"  options",[349,1131,738],{"class":360},[349,1133,1134],{"class":368}," { ",[349,1136,1137],{"class":378},"key",[349,1139,382],{"class":360},[349,1141,447],{"class":428},[349,1143,558],{"class":368},[349,1145,1146],{"class":378},"value",[349,1148,382],{"class":360},[349,1150,447],{"class":428},[349,1152,1153],{"class":368}," }[]\n",[349,1155,1156,1159,1161],{"class":351,"line":894},[349,1157,1158],{"class":378},"  multiple",[349,1160,738],{"class":360},[349,1162,1067],{"class":364},[349,1164,1165],{"class":351,"line":899},[349,1166,408],{"class":368},[349,1168,1169],{"class":351,"line":905},[349,1170,413],{"emptyLinePlaceholder":245},[349,1172,1173,1175,1178,1180,1183,1185,1188],{"class":351,"line":55},[349,1174,425],{"class":360},[349,1176,1177],{"class":428}," props",[349,1179,432],{"class":360},[349,1181,1182],{"class":364}," defineProps",[349,1184,369],{"class":368},[349,1186,1187],{"class":364},"Props",[349,1189,1190],{"class":368},">();\n",[349,1192,1194,1196,1199,1201,1204],{"class":351,"line":1193},21,[349,1195,425],{"class":360},[349,1197,1198],{"class":428}," emit",[349,1200,432],{"class":360},[349,1202,1203],{"class":364}," defineEmits",[349,1205,1206],{"class":368},"\u003C{\n",[349,1208,1210,1213,1216,1218,1221,1223,1225,1227,1229,1231,1233],{"class":351,"line":1209},22,[349,1211,1212],{"class":368},"  (",[349,1214,1215],{"class":378},"e",[349,1217,382],{"class":360},[349,1219,1220],{"class":440}," 'update:modelValue'",[349,1222,558],{"class":368},[349,1224,1146],{"class":378},[349,1226,382],{"class":360},[349,1228,1058],{"class":364},[349,1230,388],{"class":368},[349,1232,382],{"class":360},[349,1234,1235],{"class":428}," void\n",[349,1237,1239],{"class":351,"line":1238},23,[349,1240,1241],{"class":368},"}>();\n",[349,1243,1245],{"class":351,"line":1244},24,[349,1246,413],{"emptyLinePlaceholder":245},[349,1248,1250],{"class":351,"line":1249},25,[349,1251,1252],{"class":354},"\u002F\u002F Note: an empty attribute will result in an empty string \"\" value, therefore we check for false and undefined explicitly\n",[349,1254,1256,1258,1261,1263,1266],{"class":351,"line":1255},26,[349,1257,425],{"class":360},[349,1259,1260],{"class":428}," isMultiple",[349,1262,432],{"class":360},[349,1264,1265],{"class":364}," computed",[349,1267,1268],{"class":368},"(\n",[349,1270,1272,1275,1278,1281,1284,1286,1289,1291,1293,1295],{"class":351,"line":1271},27,[349,1273,1274],{"class":368},"  () ",[349,1276,1277],{"class":360},"=>",[349,1279,1280],{"class":368}," props.multiple ",[349,1282,1283],{"class":360},"!==",[349,1285,526],{"class":428},[349,1287,1288],{"class":360}," &&",[349,1290,1280],{"class":368},[349,1292,1283],{"class":360},[349,1294,731],{"class":428},[349,1296,1297],{"class":368},",\n",[349,1299,1301],{"class":351,"line":1300},28,[349,1302,450],{"class":368},[349,1304,1306],{"class":351,"line":1305},29,[349,1307,413],{"emptyLinePlaceholder":245},[349,1309,1310,1312,1315,1317,1320,1322,1325],{"class":351,"line":69},[349,1311,425],{"class":360},[349,1313,1314],{"class":428}," value",[349,1316,432],{"class":360},[349,1318,1319],{"class":364}," ref",[349,1321,369],{"class":368},[349,1323,1324],{"class":428},"any",[349,1326,1327],{"class":368},">(props.modelValue);\n",[349,1329,1331,1334,1337,1340,1343,1345,1347,1350],{"class":351,"line":1330},31,[349,1332,1333],{"class":364},"watch",[349,1335,1336],{"class":368},"(value, ",[349,1338,1339],{"class":378},"v",[349,1341,1342],{"class":360}," =>",[349,1344,1198],{"class":364},[349,1346,437],{"class":368},[349,1348,1349],{"class":440},"'update:modelValue'",[349,1351,1352],{"class":368},", v));\n",[349,1354,1355,1358,1360],{"class":351,"line":244},[349,1356,1357],{"class":368},"\u003C\u002F",[349,1359,974],{"class":681},[349,1361,1010],{"class":368},[349,1363,1365],{"class":351,"line":1364},33,[349,1366,413],{"emptyLinePlaceholder":245},[349,1368,1370,1372,1375],{"class":351,"line":1369},34,[349,1371,369],{"class":368},[349,1373,1374],{"class":681},"template",[349,1376,1010],{"class":368},[349,1378,1380,1383,1386,1389,1391,1394,1397,1399,1402],{"class":351,"line":1379},35,[349,1381,1382],{"class":368},"  \u003C",[349,1384,1385],{"class":681},"select",[349,1387,1388],{"class":364}," v-model",[349,1390,980],{"class":368},[349,1392,1393],{"class":440},"\"value\"",[349,1395,1396],{"class":364}," :multiple",[349,1398,980],{"class":368},[349,1400,1401],{"class":440},"\"multiple\"",[349,1403,1010],{"class":368},[349,1405,1407,1410,1413,1416,1418,1420,1423],{"class":351,"line":1406},36,[349,1408,1409],{"class":368},"    \u003C",[349,1411,1412],{"class":681},"option",[349,1414,1415],{"class":364}," disabled",[349,1417,1314],{"class":364},[349,1419,980],{"class":368},[349,1421,1422],{"class":440},"\"\"",[349,1424,1010],{"class":368},[349,1426,1428],{"class":351,"line":1427},37,[349,1429,1430],{"class":368},"      Please select {{ isMultiple ? \"multiple\" : \"one\" }}\n",[349,1432,1434,1437,1439],{"class":351,"line":1433},38,[349,1435,1436],{"class":368},"    \u003C\u002F",[349,1438,1412],{"class":681},[349,1440,1010],{"class":368},[349,1442,1444,1446,1448,1451,1453,1456,1459,1461,1464,1467,1469,1471],{"class":351,"line":1443},39,[349,1445,1409],{"class":368},[349,1447,1412],{"class":681},[349,1449,1450],{"class":364}," v-for",[349,1452,980],{"class":368},[349,1454,1455],{"class":440},"\"{ key, value: optionValue } in options\"",[349,1457,1458],{"class":364}," :key",[349,1460,980],{"class":368},[349,1462,1463],{"class":440},"\"key\"",[349,1465,1466],{"class":364}," :value",[349,1468,980],{"class":368},[349,1470,1463],{"class":440},[349,1472,1010],{"class":368},[349,1474,1476],{"class":351,"line":1475},40,[349,1477,1478],{"class":368},"      {{ optionValue }}\n",[349,1480,1481,1483,1485],{"class":351,"line":265},[349,1482,1436],{"class":368},[349,1484,1412],{"class":681},[349,1486,1010],{"class":368},[349,1488,1490,1493,1495],{"class":351,"line":1489},42,[349,1491,1492],{"class":368},"  \u003C\u002F",[349,1494,1385],{"class":681},[349,1496,1010],{"class":368},[349,1498,1500,1502,1504],{"class":351,"line":1499},43,[349,1501,1357],{"class":368},[349,1503,1374],{"class":681},[349,1505,1010],{"class":368},[1507,1508],"post1-example1",{"label":1509},"Preview",[231,1511,657,1512,1514,1515,1517],{},[296,1513,954],{}," component adapts its behavior depending on the value of the ",[296,1516,298],{}," prop, thanks to the use of generics and conditional types.",[319,1519,1521],{"id":1520},"practical-example-using-elementplus","Practical Example using ElementPlus",[231,1523,1524,1525,1527],{},"The UI library ElementPlus provides a Select component with a ",[296,1526,298],{}," prop. Let's use what we've learned so far to make this component type safe. Additionally, this component allows specifying any type of object array as the options.\nTo enable this behavior, they've made their modelValue of type any. Let's improve that as well and add some extra assistance with choosing the optionValue property.",[231,1529,1530],{},"Here's an example of what we would like to achieve:",[304,1532],{"alt":306,"css-class":307,"src":1533},"posts\u002F1\u002Fcode-example-2.gif",[960,1535,1536,2272,2901],{},[341,1537,1539],{"className":670,"code":1538,"filename":965,"language":672,"meta":21,"style":21},"\u003Cscript\n  lang=\"ts\"\n  setup\n  generic=\"\n    TMultiple extends boolean | undefined,\n    TOptionType,\n    \u002F\u002F As we cannot use undefined as a keyof type, we use\n    \u002F\u002F a workaround to just specify any and then check it\n    \u002F\u002F for undefined\n    TOptionValue extends keyof TOptionType = any\n  \"\n>\nimport { computed } from 'vue';\n\n\u002F\u002F Check whether we need to return the entire option object\n\u002F\u002F or just a property of that object\ntype TReturnType = undefined extends TOptionValue\n  ? TOptionType\n  : TOptionType[TOptionValue];\n\n\u002F\u002F Then we check whether we need to return a single value\n\u002F\u002F or an array of values\ntype TSingleOrMultiple = undefined extends TMultiple\n  ? TReturnType\n  : TMultiple extends false\n    ? TReturnType\n    : TReturnType[];\n\ninterface Props {\n  modelValue?: TSingleOrMultiple\n  optionValue?: TOptionValue\n  optionLabel?: keyof TOptionType\n  options?: TOptionType[]\n  multiple?: TMultiple\n  placeholder?: string\n  disabled?: boolean\n  clearable?: boolean\n  filterable?: boolean\n}\n\nconst props = defineProps\u003CProps>();\nconst emit = defineEmits\u003C{\n  (e: 'update:modelValue', value: TSingleOrMultiple): void\n}>();\n\n\u002F\u002F Note: an empty attribute will result in an empty string \"\" value,\n\u002F\u002F therefore we check for false and undefined explicitly\nconst isMultiple = computed(\n  () => props.multiple !== false && props.multiple !== undefined,\n);\n\nfunction update(value: unknown) {\n  emit('update:modelValue', value as TSingleOrMultiple);\n}\n\n\u002F\u002F Function to help work with ElementPlus\nfunction getAsString(value: unknown): string {\n  return value as string;\n}\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CElSelect\n    :modelValue=\"(modelValue as any)\"\n    :multiple=\"isMultiple\"\n    :placeholder=\"placeholder\"\n    :disabled=\"disabled\"\n    :clearable=\"clearable\"\n    :filterable=\"filterable\"\n    @update:modelValue=\"update\"\n  >\n    \u003CElOption\n      v-for=\"(option, index) in options\"\n      :key=\"index\"\n      :label=\"getAsString(props.optionLabel ? option[props.optionLabel!] : option)\"\n      :value=\"getAsString(props.optionValue ? option[props.optionValue!] : option)\"\n    \u002F>\n  \u003C\u002FElSelect>\n\u003C\u002Ftemplate>\n",[296,1540,1541,1548,1558,1563,1573,1588,1595,1600,1605,1610,1628,1633,1637,1649,1653,1658,1663,1679,1686,1701,1705,1710,1715,1729,1736,1746,1752,1760,1764,1772,1780,1789,1800,1811,1819,1828,1838,1847,1856,1860,1864,1880,1892,1916,1921,1926,1932,1938,1951,1974,1979,1984,2003,2022,2027,2032,2038,2062,2076,2081,2090,2095,2104,2112,2123,2134,2145,2156,2167,2178,2189,2195,2203,2214,2225,2236,2247,2253,2263],{"__ignoreMap":21},[349,1542,1543,1545],{"class":351,"line":20},[349,1544,369],{"class":368},[349,1546,1547],{"class":681},"script\n",[349,1549,1550,1553,1555],{"class":351,"line":131},[349,1551,1552],{"class":364},"  lang",[349,1554,980],{"class":368},[349,1556,1557],{"class":440},"\"ts\"\n",[349,1559,1560],{"class":351,"line":155},[349,1561,1562],{"class":364},"  setup\n",[349,1564,1565,1568,1570],{"class":351,"line":180},[349,1566,1567],{"class":364},"  generic",[349,1569,980],{"class":368},[349,1571,1572],{"class":440},"\"\n",[349,1574,1575,1578,1580,1582,1584,1586],{"class":351,"line":204},[349,1576,1577],{"class":364},"    TMultiple",[349,1579,495],{"class":360},[349,1581,498],{"class":428},[349,1583,728],{"class":360},[349,1585,731],{"class":428},[349,1587,1297],{"class":368},[349,1589,1590,1593],{"class":351,"line":416},[349,1591,1592],{"class":364},"    TOptionType",[349,1594,1297],{"class":368},[349,1596,1597],{"class":351,"line":422},[349,1598,1599],{"class":354},"    \u002F\u002F As we cannot use undefined as a keyof type, we use\n",[349,1601,1602],{"class":351,"line":453},[349,1603,1604],{"class":354},"    \u002F\u002F a workaround to just specify any and then check it\n",[349,1606,1607],{"class":351,"line":623},[349,1608,1609],{"class":354},"    \u002F\u002F for undefined\n",[349,1611,1612,1615,1617,1620,1623,1625],{"class":351,"line":41},[349,1613,1614],{"class":364},"    TOptionValue",[349,1616,495],{"class":360},[349,1618,1619],{"class":360}," keyof",[349,1621,1622],{"class":364}," TOptionType",[349,1624,432],{"class":360},[349,1626,1627],{"class":428}," any\n",[349,1629,1630],{"class":351,"line":633},[349,1631,1632],{"class":440},"  \"\n",[349,1634,1635],{"class":351,"line":651},[349,1636,1010],{"class":368},[349,1638,1639,1641,1643,1645,1647],{"class":351,"line":862},[349,1640,1015],{"class":360},[349,1642,1018],{"class":368},[349,1644,1021],{"class":360},[349,1646,1024],{"class":440},[349,1648,585],{"class":368},[349,1650,1651],{"class":351,"line":867},[349,1652,413],{"emptyLinePlaceholder":245},[349,1654,1655],{"class":351,"line":872},[349,1656,1657],{"class":354},"\u002F\u002F Check whether we need to return the entire option object\n",[349,1659,1660],{"class":351,"line":889},[349,1661,1662],{"class":354},"\u002F\u002F or just a property of that object\n",[349,1664,1665,1667,1670,1672,1674,1676],{"class":351,"line":894},[349,1666,1055],{"class":360},[349,1668,1669],{"class":364}," TReturnType",[349,1671,432],{"class":360},[349,1673,731],{"class":428},[349,1675,495],{"class":360},[349,1677,1678],{"class":364}," TOptionValue\n",[349,1680,1681,1683],{"class":351,"line":899},[349,1682,1072],{"class":360},[349,1684,1685],{"class":364}," TOptionType\n",[349,1687,1688,1690,1692,1695,1698],{"class":351,"line":905},[349,1689,1079],{"class":360},[349,1691,1622],{"class":364},[349,1693,1694],{"class":368},"[",[349,1696,1697],{"class":364},"TOptionValue",[349,1699,1700],{"class":368},"];\n",[349,1702,1703],{"class":351,"line":55},[349,1704,413],{"emptyLinePlaceholder":245},[349,1706,1707],{"class":351,"line":1193},[349,1708,1709],{"class":354},"\u002F\u002F Then we check whether we need to return a single value\n",[349,1711,1712],{"class":351,"line":1209},[349,1713,1714],{"class":354},"\u002F\u002F or an array of values\n",[349,1716,1717,1719,1721,1723,1725,1727],{"class":351,"line":1238},[349,1718,1055],{"class":360},[349,1720,1058],{"class":364},[349,1722,432],{"class":360},[349,1724,731],{"class":428},[349,1726,495],{"class":360},[349,1728,1067],{"class":364},[349,1730,1731,1733],{"class":351,"line":1244},[349,1732,1072],{"class":360},[349,1734,1735],{"class":364}," TReturnType\n",[349,1737,1738,1740,1742,1744],{"class":351,"line":1249},[349,1739,1079],{"class":360},[349,1741,1082],{"class":364},[349,1743,495],{"class":360},[349,1745,777],{"class":428},[349,1747,1748,1750],{"class":351,"line":1255},[349,1749,762],{"class":360},[349,1751,1735],{"class":364},[349,1753,1754,1756,1758],{"class":351,"line":1271},[349,1755,770],{"class":360},[349,1757,1669],{"class":364},[349,1759,539],{"class":368},[349,1761,1762],{"class":351,"line":1300},[349,1763,413],{"emptyLinePlaceholder":245},[349,1765,1766,1768,1770],{"class":351,"line":1305},[349,1767,1109],{"class":360},[349,1769,1112],{"class":364},[349,1771,395],{"class":368},[349,1773,1774,1776,1778],{"class":351,"line":69},[349,1775,1119],{"class":378},[349,1777,738],{"class":360},[349,1779,1124],{"class":364},[349,1781,1782,1785,1787],{"class":351,"line":1330},[349,1783,1784],{"class":378},"  optionValue",[349,1786,738],{"class":360},[349,1788,1678],{"class":364},[349,1790,1791,1794,1796,1798],{"class":351,"line":244},[349,1792,1793],{"class":378},"  optionLabel",[349,1795,738],{"class":360},[349,1797,1619],{"class":360},[349,1799,1685],{"class":364},[349,1801,1802,1804,1806,1808],{"class":351,"line":1364},[349,1803,1129],{"class":378},[349,1805,738],{"class":360},[349,1807,1622],{"class":364},[349,1809,1810],{"class":368},"[]\n",[349,1812,1813,1815,1817],{"class":351,"line":1369},[349,1814,1158],{"class":378},[349,1816,738],{"class":360},[349,1818,1067],{"class":364},[349,1820,1821,1824,1826],{"class":351,"line":1379},[349,1822,1823],{"class":378},"  placeholder",[349,1825,738],{"class":360},[349,1827,765],{"class":428},[349,1829,1830,1833,1835],{"class":351,"line":1406},[349,1831,1832],{"class":378},"  disabled",[349,1834,738],{"class":360},[349,1836,1837],{"class":428}," boolean\n",[349,1839,1840,1843,1845],{"class":351,"line":1427},[349,1841,1842],{"class":378},"  clearable",[349,1844,738],{"class":360},[349,1846,1837],{"class":428},[349,1848,1849,1852,1854],{"class":351,"line":1433},[349,1850,1851],{"class":378},"  filterable",[349,1853,738],{"class":360},[349,1855,1837],{"class":428},[349,1857,1858],{"class":351,"line":1443},[349,1859,408],{"class":368},[349,1861,1862],{"class":351,"line":1475},[349,1863,413],{"emptyLinePlaceholder":245},[349,1865,1866,1868,1870,1872,1874,1876,1878],{"class":351,"line":265},[349,1867,425],{"class":360},[349,1869,1177],{"class":428},[349,1871,432],{"class":360},[349,1873,1182],{"class":364},[349,1875,369],{"class":368},[349,1877,1187],{"class":364},[349,1879,1190],{"class":368},[349,1881,1882,1884,1886,1888,1890],{"class":351,"line":1489},[349,1883,425],{"class":360},[349,1885,1198],{"class":428},[349,1887,432],{"class":360},[349,1889,1203],{"class":364},[349,1891,1206],{"class":368},[349,1893,1894,1896,1898,1900,1902,1904,1906,1908,1910,1912,1914],{"class":351,"line":1499},[349,1895,1212],{"class":368},[349,1897,1215],{"class":378},[349,1899,382],{"class":360},[349,1901,1220],{"class":440},[349,1903,558],{"class":368},[349,1905,1146],{"class":378},[349,1907,382],{"class":360},[349,1909,1058],{"class":364},[349,1911,388],{"class":368},[349,1913,382],{"class":360},[349,1915,1235],{"class":428},[349,1917,1919],{"class":351,"line":1918},44,[349,1920,1241],{"class":368},[349,1922,1924],{"class":351,"line":1923},45,[349,1925,413],{"emptyLinePlaceholder":245},[349,1927,1929],{"class":351,"line":1928},46,[349,1930,1931],{"class":354},"\u002F\u002F Note: an empty attribute will result in an empty string \"\" value,\n",[349,1933,1935],{"class":351,"line":1934},47,[349,1936,1937],{"class":354},"\u002F\u002F therefore we check for false and undefined explicitly\n",[349,1939,1941,1943,1945,1947,1949],{"class":351,"line":1940},48,[349,1942,425],{"class":360},[349,1944,1260],{"class":428},[349,1946,432],{"class":360},[349,1948,1265],{"class":364},[349,1950,1268],{"class":368},[349,1952,1954,1956,1958,1960,1962,1964,1966,1968,1970,1972],{"class":351,"line":1953},49,[349,1955,1274],{"class":368},[349,1957,1277],{"class":360},[349,1959,1280],{"class":368},[349,1961,1283],{"class":360},[349,1963,526],{"class":428},[349,1965,1288],{"class":360},[349,1967,1280],{"class":368},[349,1969,1283],{"class":360},[349,1971,731],{"class":428},[349,1973,1297],{"class":368},[349,1975,1977],{"class":351,"line":1976},50,[349,1978,450],{"class":368},[349,1980,1982],{"class":351,"line":1981},51,[349,1983,413],{"emptyLinePlaceholder":245},[349,1985,1987,1989,1992,1994,1996,1998,2001],{"class":351,"line":1986},52,[349,1988,361],{"class":360},[349,1990,1991],{"class":364}," update",[349,1993,437],{"class":368},[349,1995,1146],{"class":378},[349,1997,382],{"class":360},[349,1999,2000],{"class":428}," unknown",[349,2002,509],{"class":368},[349,2004,2006,2009,2011,2013,2016,2018,2020],{"class":351,"line":2005},53,[349,2007,2008],{"class":364},"  emit",[349,2010,437],{"class":368},[349,2012,1349],{"class":440},[349,2014,2015],{"class":368},", value ",[349,2017,580],{"class":360},[349,2019,1058],{"class":364},[349,2021,450],{"class":368},[349,2023,2025],{"class":351,"line":2024},54,[349,2026,408],{"class":368},[349,2028,2030],{"class":351,"line":2029},55,[349,2031,413],{"emptyLinePlaceholder":245},[349,2033,2035],{"class":351,"line":2034},56,[349,2036,2037],{"class":354},"\u002F\u002F Function to help work with ElementPlus\n",[349,2039,2041,2043,2046,2048,2050,2052,2054,2056,2058,2060],{"class":351,"line":2040},57,[349,2042,361],{"class":360},[349,2044,2045],{"class":364}," getAsString",[349,2047,437],{"class":368},[349,2049,1146],{"class":378},[349,2051,382],{"class":360},[349,2053,2000],{"class":428},[349,2055,388],{"class":368},[349,2057,382],{"class":360},[349,2059,447],{"class":428},[349,2061,395],{"class":368},[349,2063,2065,2067,2070,2072,2074],{"class":351,"line":2064},58,[349,2066,400],{"class":360},[349,2068,2069],{"class":368}," value ",[349,2071,580],{"class":360},[349,2073,447],{"class":428},[349,2075,585],{"class":368},[349,2077,2079],{"class":351,"line":2078},59,[349,2080,408],{"class":368},[349,2082,2084,2086,2088],{"class":351,"line":2083},60,[349,2085,1357],{"class":368},[349,2087,974],{"class":681},[349,2089,1010],{"class":368},[349,2091,2093],{"class":351,"line":2092},61,[349,2094,413],{"emptyLinePlaceholder":245},[349,2096,2098,2100,2102],{"class":351,"line":2097},62,[349,2099,369],{"class":368},[349,2101,1374],{"class":681},[349,2103,1010],{"class":368},[349,2105,2107,2109],{"class":351,"line":2106},63,[349,2108,1382],{"class":368},[349,2110,2111],{"class":681},"ElSelect\n",[349,2113,2115,2118,2120],{"class":351,"line":2114},64,[349,2116,2117],{"class":364},"    :modelValue",[349,2119,980],{"class":368},[349,2121,2122],{"class":440},"\"(modelValue as any)\"\n",[349,2124,2126,2129,2131],{"class":351,"line":2125},65,[349,2127,2128],{"class":364},"    :multiple",[349,2130,980],{"class":368},[349,2132,2133],{"class":440},"\"isMultiple\"\n",[349,2135,2137,2140,2142],{"class":351,"line":2136},66,[349,2138,2139],{"class":364},"    :placeholder",[349,2141,980],{"class":368},[349,2143,2144],{"class":440},"\"placeholder\"\n",[349,2146,2148,2151,2153],{"class":351,"line":2147},67,[349,2149,2150],{"class":364},"    :disabled",[349,2152,980],{"class":368},[349,2154,2155],{"class":440},"\"disabled\"\n",[349,2157,2159,2162,2164],{"class":351,"line":2158},68,[349,2160,2161],{"class":364},"    :clearable",[349,2163,980],{"class":368},[349,2165,2166],{"class":440},"\"clearable\"\n",[349,2168,2170,2173,2175],{"class":351,"line":2169},69,[349,2171,2172],{"class":364},"    :filterable",[349,2174,980],{"class":368},[349,2176,2177],{"class":440},"\"filterable\"\n",[349,2179,2181,2184,2186],{"class":351,"line":2180},70,[349,2182,2183],{"class":364},"    @update:modelValue",[349,2185,980],{"class":368},[349,2187,2188],{"class":440},"\"update\"\n",[349,2190,2192],{"class":351,"line":2191},71,[349,2193,2194],{"class":368},"  >\n",[349,2196,2198,2200],{"class":351,"line":2197},72,[349,2199,1409],{"class":368},[349,2201,2202],{"class":681},"ElOption\n",[349,2204,2206,2209,2211],{"class":351,"line":2205},73,[349,2207,2208],{"class":364},"      v-for",[349,2210,980],{"class":368},[349,2212,2213],{"class":440},"\"(option, index) in options\"\n",[349,2215,2217,2220,2222],{"class":351,"line":2216},74,[349,2218,2219],{"class":364},"      :key",[349,2221,980],{"class":368},[349,2223,2224],{"class":440},"\"index\"\n",[349,2226,2228,2231,2233],{"class":351,"line":2227},75,[349,2229,2230],{"class":364},"      :label",[349,2232,980],{"class":368},[349,2234,2235],{"class":440},"\"getAsString(props.optionLabel ? option[props.optionLabel!] : option)\"\n",[349,2237,2239,2242,2244],{"class":351,"line":2238},76,[349,2240,2241],{"class":364},"      :value",[349,2243,980],{"class":368},[349,2245,2246],{"class":440},"\"getAsString(props.optionValue ? option[props.optionValue!] : option)\"\n",[349,2248,2250],{"class":351,"line":2249},77,[349,2251,2252],{"class":368},"    \u002F>\n",[349,2254,2256,2258,2261],{"class":351,"line":2255},78,[349,2257,1492],{"class":368},[349,2259,2260],{"class":681},"ElSelect",[349,2262,1010],{"class":368},[349,2264,2266,2268,2270],{"class":351,"line":2265},79,[349,2267,1357],{"class":368},[349,2269,1374],{"class":681},[349,2271,1010],{"class":368},[341,2273,2276],{"className":670,"code":2274,"filename":2275,"language":672,"meta":21,"style":21},"\u003Cscript lang=\"ts\" setup>\nimport VSelect from '.\u002FVSelect.vue';\n\ninterface Country { id: number, name: string, code: string }\nconst countries: Country[] = [\n  { id: 1, name: 'United States', code: 'US' },\n  { id: 2, name: 'Canada', code: 'CA' },\n  { id: 3, name: 'United Kingdom', code: 'GB' },\n  { id: 4, name: 'Australia', code: 'AU' },\n  { id: 5, name: 'Germany', code: 'DE' },\n  { id: 6, name: 'France', code: 'FR' },\n  { id: 7, name: 'Japan', code: 'JP' },\n  { id: 8, name: 'China', code: 'CN' },\n  { id: 9, name: 'India', code: 'IN' },\n  { id: 10, name: 'Brazil', code: 'BR' },\n  { id: 11, name: 'Netherlands', code: 'NL' },\n];\n\nconst selectedCountry = ref\u003Cstring | undefined>();\nconst selectedCountries = ref\u003Cnumber[]>([]);\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003Cdiv class=\"form-field\">\n    \u003Clabel>Single select\u003C\u002Flabel>\n    \u003CVSelect\n      v-model=\"selectedCountry\"\n      :options=\"countries\"\n      optionLabel=\"name\"\n      optionValue=\"code\"\n    \u002F>\n    \u003Cspan>\n      Selected country:\n      \u003Cpre>{{ selectedCountry }}\u003C\u002Fpre>\n    \u003C\u002Fspan>\n  \u003C\u002Fdiv>\n  \u003Cdiv class=\"form-field\">\n    \u003Clabel>Multiple select\u003C\u002Flabel>\n    \u003CVSelect\n      v-model=\"selectedCountries\"\n      :options=\"countries\"\n      optionLabel=\"name\"\n      optionValue=\"id\"\n      multiple\n    \u002F>\n    \u003Cspan>\n      Selected countries:\n      \u003Cpre>{{ selectedCountries.join(\", \") }}\u003C\u002Fpre>\n    \u003C\u002Fspan>\n  \u003C\u002Fdiv>\n\u003C\u002Ftemplate>\n","Example.vue",[296,2277,2278,2294,2308,2312,2349,2368,2391,2410,2429,2448,2467,2486,2505,2524,2543,2562,2581,2585,2589,2611,2630,2638,2642,2650,2667,2681,2688,2698,2708,2718,2728,2732,2740,2745,2759,2767,2775,2789,2802,2808,2817,2825,2833,2842,2847,2851,2859,2864,2877,2885,2893],{"__ignoreMap":21},[349,2279,2280,2282,2284,2286,2288,2290,2292],{"class":351,"line":20},[349,2281,369],{"class":368},[349,2283,974],{"class":681},[349,2285,977],{"class":364},[349,2287,980],{"class":368},[349,2289,983],{"class":440},[349,2291,986],{"class":364},[349,2293,1010],{"class":368},[349,2295,2296,2298,2301,2303,2306],{"class":351,"line":131},[349,2297,1015],{"class":360},[349,2299,2300],{"class":368}," VSelect ",[349,2302,1021],{"class":360},[349,2304,2305],{"class":440}," '.\u002FVSelect.vue'",[349,2307,585],{"class":368},[349,2309,2310],{"class":351,"line":155},[349,2311,413],{"emptyLinePlaceholder":245},[349,2313,2314,2316,2319,2321,2324,2326,2329,2331,2334,2336,2338,2340,2342,2344,2346],{"class":351,"line":180},[349,2315,1109],{"class":360},[349,2317,2318],{"class":364}," Country",[349,2320,1134],{"class":368},[349,2322,2323],{"class":378},"id",[349,2325,382],{"class":360},[349,2327,2328],{"class":428}," number",[349,2330,558],{"class":368},[349,2332,2333],{"class":378},"name",[349,2335,382],{"class":360},[349,2337,447],{"class":428},[349,2339,558],{"class":368},[349,2341,296],{"class":378},[349,2343,382],{"class":360},[349,2345,447],{"class":428},[349,2347,2348],{"class":368}," }\n",[349,2350,2351,2353,2356,2358,2360,2363,2365],{"class":351,"line":204},[349,2352,425],{"class":360},[349,2354,2355],{"class":428}," countries",[349,2357,382],{"class":360},[349,2359,2318],{"class":364},[349,2361,2362],{"class":368},"[] ",[349,2364,980],{"class":360},[349,2366,2367],{"class":368}," [\n",[349,2369,2370,2373,2376,2379,2382,2385,2388],{"class":351,"line":416},[349,2371,2372],{"class":368},"  { id: ",[349,2374,2375],{"class":428},"1",[349,2377,2378],{"class":368},", name: ",[349,2380,2381],{"class":440},"'United States'",[349,2383,2384],{"class":368},", code: ",[349,2386,2387],{"class":440},"'US'",[349,2389,2390],{"class":368}," },\n",[349,2392,2393,2395,2398,2400,2403,2405,2408],{"class":351,"line":422},[349,2394,2372],{"class":368},[349,2396,2397],{"class":428},"2",[349,2399,2378],{"class":368},[349,2401,2402],{"class":440},"'Canada'",[349,2404,2384],{"class":368},[349,2406,2407],{"class":440},"'CA'",[349,2409,2390],{"class":368},[349,2411,2412,2414,2417,2419,2422,2424,2427],{"class":351,"line":453},[349,2413,2372],{"class":368},[349,2415,2416],{"class":428},"3",[349,2418,2378],{"class":368},[349,2420,2421],{"class":440},"'United Kingdom'",[349,2423,2384],{"class":368},[349,2425,2426],{"class":440},"'GB'",[349,2428,2390],{"class":368},[349,2430,2431,2433,2436,2438,2441,2443,2446],{"class":351,"line":623},[349,2432,2372],{"class":368},[349,2434,2435],{"class":428},"4",[349,2437,2378],{"class":368},[349,2439,2440],{"class":440},"'Australia'",[349,2442,2384],{"class":368},[349,2444,2445],{"class":440},"'AU'",[349,2447,2390],{"class":368},[349,2449,2450,2452,2455,2457,2460,2462,2465],{"class":351,"line":41},[349,2451,2372],{"class":368},[349,2453,2454],{"class":428},"5",[349,2456,2378],{"class":368},[349,2458,2459],{"class":440},"'Germany'",[349,2461,2384],{"class":368},[349,2463,2464],{"class":440},"'DE'",[349,2466,2390],{"class":368},[349,2468,2469,2471,2474,2476,2479,2481,2484],{"class":351,"line":633},[349,2470,2372],{"class":368},[349,2472,2473],{"class":428},"6",[349,2475,2378],{"class":368},[349,2477,2478],{"class":440},"'France'",[349,2480,2384],{"class":368},[349,2482,2483],{"class":440},"'FR'",[349,2485,2390],{"class":368},[349,2487,2488,2490,2493,2495,2498,2500,2503],{"class":351,"line":651},[349,2489,2372],{"class":368},[349,2491,2492],{"class":428},"7",[349,2494,2378],{"class":368},[349,2496,2497],{"class":440},"'Japan'",[349,2499,2384],{"class":368},[349,2501,2502],{"class":440},"'JP'",[349,2504,2390],{"class":368},[349,2506,2507,2509,2512,2514,2517,2519,2522],{"class":351,"line":862},[349,2508,2372],{"class":368},[349,2510,2511],{"class":428},"8",[349,2513,2378],{"class":368},[349,2515,2516],{"class":440},"'China'",[349,2518,2384],{"class":368},[349,2520,2521],{"class":440},"'CN'",[349,2523,2390],{"class":368},[349,2525,2526,2528,2531,2533,2536,2538,2541],{"class":351,"line":867},[349,2527,2372],{"class":368},[349,2529,2530],{"class":428},"9",[349,2532,2378],{"class":368},[349,2534,2535],{"class":440},"'India'",[349,2537,2384],{"class":368},[349,2539,2540],{"class":440},"'IN'",[349,2542,2390],{"class":368},[349,2544,2545,2547,2550,2552,2555,2557,2560],{"class":351,"line":872},[349,2546,2372],{"class":368},[349,2548,2549],{"class":428},"10",[349,2551,2378],{"class":368},[349,2553,2554],{"class":440},"'Brazil'",[349,2556,2384],{"class":368},[349,2558,2559],{"class":440},"'BR'",[349,2561,2390],{"class":368},[349,2563,2564,2566,2569,2571,2574,2576,2579],{"class":351,"line":889},[349,2565,2372],{"class":368},[349,2567,2568],{"class":428},"11",[349,2570,2378],{"class":368},[349,2572,2573],{"class":440},"'Netherlands'",[349,2575,2384],{"class":368},[349,2577,2578],{"class":440},"'NL'",[349,2580,2390],{"class":368},[349,2582,2583],{"class":351,"line":894},[349,2584,1700],{"class":368},[349,2586,2587],{"class":351,"line":899},[349,2588,413],{"emptyLinePlaceholder":245},[349,2590,2591,2593,2596,2598,2600,2602,2605,2607,2609],{"class":351,"line":905},[349,2592,425],{"class":360},[349,2594,2595],{"class":428}," selectedCountry",[349,2597,432],{"class":360},[349,2599,1319],{"class":364},[349,2601,369],{"class":368},[349,2603,2604],{"class":428},"string",[349,2606,728],{"class":360},[349,2608,731],{"class":428},[349,2610,1190],{"class":368},[349,2612,2613,2615,2618,2620,2622,2624,2627],{"class":351,"line":55},[349,2614,425],{"class":360},[349,2616,2617],{"class":428}," selectedCountries",[349,2619,432],{"class":360},[349,2621,1319],{"class":364},[349,2623,369],{"class":368},[349,2625,2626],{"class":428},"number",[349,2628,2629],{"class":368},"[]>([]);\n",[349,2631,2632,2634,2636],{"class":351,"line":1193},[349,2633,1357],{"class":368},[349,2635,974],{"class":681},[349,2637,1010],{"class":368},[349,2639,2640],{"class":351,"line":1209},[349,2641,413],{"emptyLinePlaceholder":245},[349,2643,2644,2646,2648],{"class":351,"line":1238},[349,2645,369],{"class":368},[349,2647,1374],{"class":681},[349,2649,1010],{"class":368},[349,2651,2652,2654,2657,2660,2662,2665],{"class":351,"line":1244},[349,2653,1382],{"class":368},[349,2655,2656],{"class":681},"div",[349,2658,2659],{"class":364}," class",[349,2661,980],{"class":368},[349,2663,2664],{"class":440},"\"form-field\"",[349,2666,1010],{"class":368},[349,2668,2669,2671,2674,2677,2679],{"class":351,"line":1249},[349,2670,1409],{"class":368},[349,2672,2673],{"class":681},"label",[349,2675,2676],{"class":368},">Single select\u003C\u002F",[349,2678,2673],{"class":681},[349,2680,1010],{"class":368},[349,2682,2683,2685],{"class":351,"line":1255},[349,2684,1409],{"class":368},[349,2686,2687],{"class":681},"VSelect\n",[349,2689,2690,2693,2695],{"class":351,"line":1271},[349,2691,2692],{"class":364},"      v-model",[349,2694,980],{"class":368},[349,2696,2697],{"class":440},"\"selectedCountry\"\n",[349,2699,2700,2703,2705],{"class":351,"line":1300},[349,2701,2702],{"class":364},"      :options",[349,2704,980],{"class":368},[349,2706,2707],{"class":440},"\"countries\"\n",[349,2709,2710,2713,2715],{"class":351,"line":1305},[349,2711,2712],{"class":364},"      optionLabel",[349,2714,980],{"class":368},[349,2716,2717],{"class":440},"\"name\"\n",[349,2719,2720,2723,2725],{"class":351,"line":69},[349,2721,2722],{"class":364},"      optionValue",[349,2724,980],{"class":368},[349,2726,2727],{"class":440},"\"code\"\n",[349,2729,2730],{"class":351,"line":1330},[349,2731,2252],{"class":368},[349,2733,2734,2736,2738],{"class":351,"line":244},[349,2735,1409],{"class":368},[349,2737,349],{"class":681},[349,2739,1010],{"class":368},[349,2741,2742],{"class":351,"line":1364},[349,2743,2744],{"class":368},"      Selected country:\n",[349,2746,2747,2750,2752,2755,2757],{"class":351,"line":1369},[349,2748,2749],{"class":368},"      \u003C",[349,2751,341],{"class":681},[349,2753,2754],{"class":368},">{{ selectedCountry }}\u003C\u002F",[349,2756,341],{"class":681},[349,2758,1010],{"class":368},[349,2760,2761,2763,2765],{"class":351,"line":1379},[349,2762,1436],{"class":368},[349,2764,349],{"class":681},[349,2766,1010],{"class":368},[349,2768,2769,2771,2773],{"class":351,"line":1406},[349,2770,1492],{"class":368},[349,2772,2656],{"class":681},[349,2774,1010],{"class":368},[349,2776,2777,2779,2781,2783,2785,2787],{"class":351,"line":1427},[349,2778,1382],{"class":368},[349,2780,2656],{"class":681},[349,2782,2659],{"class":364},[349,2784,980],{"class":368},[349,2786,2664],{"class":440},[349,2788,1010],{"class":368},[349,2790,2791,2793,2795,2798,2800],{"class":351,"line":1433},[349,2792,1409],{"class":368},[349,2794,2673],{"class":681},[349,2796,2797],{"class":368},">Multiple select\u003C\u002F",[349,2799,2673],{"class":681},[349,2801,1010],{"class":368},[349,2803,2804,2806],{"class":351,"line":1443},[349,2805,1409],{"class":368},[349,2807,2687],{"class":681},[349,2809,2810,2812,2814],{"class":351,"line":1475},[349,2811,2692],{"class":364},[349,2813,980],{"class":368},[349,2815,2816],{"class":440},"\"selectedCountries\"\n",[349,2818,2819,2821,2823],{"class":351,"line":265},[349,2820,2702],{"class":364},[349,2822,980],{"class":368},[349,2824,2707],{"class":440},[349,2826,2827,2829,2831],{"class":351,"line":1489},[349,2828,2712],{"class":364},[349,2830,980],{"class":368},[349,2832,2717],{"class":440},[349,2834,2835,2837,2839],{"class":351,"line":1499},[349,2836,2722],{"class":364},[349,2838,980],{"class":368},[349,2840,2841],{"class":440},"\"id\"\n",[349,2843,2844],{"class":351,"line":1918},[349,2845,2846],{"class":364},"      multiple\n",[349,2848,2849],{"class":351,"line":1923},[349,2850,2252],{"class":368},[349,2852,2853,2855,2857],{"class":351,"line":1928},[349,2854,1409],{"class":368},[349,2856,349],{"class":681},[349,2858,1010],{"class":368},[349,2860,2861],{"class":351,"line":1934},[349,2862,2863],{"class":368},"      Selected countries:\n",[349,2865,2866,2868,2870,2873,2875],{"class":351,"line":1940},[349,2867,2749],{"class":368},[349,2869,341],{"class":681},[349,2871,2872],{"class":368},">{{ selectedCountries.join(\", \") }}\u003C\u002F",[349,2874,341],{"class":681},[349,2876,1010],{"class":368},[349,2878,2879,2881,2883],{"class":351,"line":1953},[349,2880,1436],{"class":368},[349,2882,349],{"class":681},[349,2884,1010],{"class":368},[349,2886,2887,2889,2891],{"class":351,"line":1976},[349,2888,1492],{"class":368},[349,2890,2656],{"class":681},[349,2892,1010],{"class":368},[349,2894,2895,2897,2899],{"class":351,"line":1981},[349,2896,1357],{"class":368},[349,2898,1374],{"class":681},[349,2900,1010],{"class":368},[2902,2903],"post1-example2",{"label":1509},[231,2905,2906],{},"To accomplish this, we performed the following steps:",[2908,2909,2910,2914,2917,2920,2923],"ul",{},[2911,2912,2913],"li",{},"Import ElementPlus Components: We imported both ElementPlus components and displayed them based on the multiple property.",[2911,2915,2916],{},"Create a Generic Type: We created a generic type for TOptionValue, which is a keyof the TOptionType.",[2911,2918,2919],{},"Define TReturnType: We then created a TReturnType that returns either TOptionType or one of its properties.",[2911,2921,2922],{},"Develop TSingleOrMultiple Type: This TReturnType is utilized to create a TSingleOrMultiple type based on the multiple property.",[2911,2924,2925],{},"Utilize Types in Props and Emit: Finally, all these types are used in the props and emit functions to provide additional assistance.",[319,2927,2929],{"id":2928},"conclusion","Conclusion",[231,2931,2932],{},"Using generics and conditional types in Vue 3.3 allows you to create flexible, reusable components that adapt to different use cases without adding unnecessary props or complexity. This approach provides several benefits:",[2908,2934,2935,2938,2941],{},[2911,2936,2937],{},"Makes your code cleaner and more maintainable.",[2911,2939,2940],{},"Improves type safety, reducing potential runtime errors.",[2911,2942,2943],{},"Enhances the overall developer experience by providing clearer and more predictable behavior.",[231,2945,2946],{},"If you want to explore more about Vue 3.3 and generics, check out the official documentation or try implementing similar patterns in your own projects.",[319,2948,2950],{"id":2949},"extra-why-undefined-extends-t-and-not-t-extends-undefined",[349,2951,939,2953,942,2955,549],{"id":2952},"why-swap-undefined-and-t-around",[296,2954,932],{},[296,2956,928],{},[231,2958,2959],{},"When you want to perform a conditional type check involving undefined, it's helpful to think in terms of whether T includes undefined. This is what undefined extends T checks—it asks whether undefined is a possible subtype of T.",[231,2961,2962],{},"If you were to use T extends undefined, it would only return true if T itself is exactly undefined. This is not the same as checking whether undefined could be part of T.",[2908,2964,2965,2968],{},[2911,2966,2967],{},"undefined extends T: This checks if undefined is part of the possible values of T. In other words, it will return true if T could be undefined (e.g., T is true | false | undefined).",[2911,2969,2970],{},"T extends undefined: This checks if T is precisely undefined. If T has other values, like true or false, this condition would evaluate to false.",[2972,2973,2974],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":21,"searchDepth":131,"depth":131,"links":2976},[2977,2978,2979,2980,2981,2982,2983],{"id":321,"depth":131,"text":322},{"id":328,"depth":131,"text":329},{"id":338,"depth":131,"text":339},{"id":947,"depth":131,"text":948},{"id":1520,"depth":131,"text":1521},{"id":2928,"depth":131,"text":2929},{"id":2949,"depth":131,"text":2984},"Extra: Why undefined extends T and not T extends undefined?","Vue.js","2024-11-04T21:30:00","Learn how to leverage Vue 3.3 generics to dynamically adjust property types based on other property values, making components more flexible and reusable.",{"type":228,"value":2989},[2990],[231,2991,294,2992,299,2994,302],{},[296,2993,298],{},[296,2995,298],{},"Vue.js logo with computerized elements","\u002Fposts\u002F1\u002Fcover.jpeg",[2985,2999,3000,3001,3002,3003,3004,3005],"Vue 3.3","TypeScript","Generics","Reusable components","Conditional types","MultiSelect component","Frontend development",{},{"text":3008,"minutes":3009,"time":3010,"words":3011},"9 min read",8.23,493800,1646,{"title":104,"description":2987},"XV1x74uulUyblxhNcm6KC7L8Nq22BuR7aw9RczH-IoQ",{"id":272,"company":3015,"extension":277,"fullName":278,"github":279,"homePage":280,"imageUrl":276,"linkedIn":281,"meta":3016,"role":283,"stem":284,"twitter":285,"userName":286,"__hash__":287},{"name":274,"url":275,"imageUrl":276},{},1781641709303]