Skip to content

Commit

Permalink
ok finally both refs and selected properties for template type checki…
Browse files Browse the repository at this point in the history
…ng working as expected, by intersecting the custom element class with the DefineComponent type. Ugly, but it works.
  • Loading branch information
trusktr committed Oct 23, 2024
1 parent 544b404 commit e702757
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 13 deletions.
18 changes: 9 additions & 9 deletions examples/kitchen-sink-vue/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ import './KitchenSink.js'
import {useTemplateRef} from 'vue'
const sink = useTemplateRef('sink')
sink.value!.foo
sink.value!.someMethod()
sink.value!.foo = 123
</script>

<template>
<!-- There should be a type error here: -->
<kitchen-sink ref="sink" :foo="true"></kitchen-sink>
<!-- There should be no type errors: -->
<kitchen-sink ref="sink" :foo="123" :bar="true"></kitchen-sink>

<!-- There should be type errors: -->
<kitchen-sink ref="sink" :foo="true" :bar="123"></kitchen-sink>
</template>

<style scoped>
kitchen-sink#sink {
cursor: pointer;
user-select: none;
}
</style>
<style scoped></style>
23 changes: 19 additions & 4 deletions examples/kitchen-sink-vue/src/KitchenSink.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,29 @@
import type {DefineComponent} from 'vue'

// Select the properties to expose to template type checking.
type KitchenSinkAttributes = 'foo' | 'bar'

export class KitchenSink extends HTMLElement {
foo = 123
bar = false

// This is not exposed to template type checking.
someMethod() {
/* ... */
}
}

customElements.define('kitchen-sink', KitchenSink)

import type {Component} from 'vue'
type VueElementAttribtues<T extends HTMLElement, Attributes extends keyof T> =
// This is the type that is exposed to template type checking.
DefineComponent<Partial<Pick<T, Attributes>>> &
// Additionally intersect with a constructor type that returns the element type, for refs to work properly.
(new () => T)

declare module 'vue' {
interface GlobalComponents {
// Try toggling between these two lines
'kitchen-sink': typeof KitchenSink // not working (except ref works)
// 'kitchen-sink': Component<{foo: number}> // works (except ref not working)
// Use the helper to add any custom element to GlobalComponents.
'kitchen-sink': VueElementAttribtues<KitchenSink, KitchenSinkAttributes>
}
}

0 comments on commit e702757

Please sign in to comment.