Skip to content

Commit 3c9b0c3

Browse files
committed
Identity and tsx types
1 parent bc6063c commit 3c9b0c3

File tree

7 files changed

+100
-46
lines changed

7 files changed

+100
-46
lines changed

src/identity.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
export const IdentitySymbol: unique symbol = Symbol('vue-facing-decorator-identity')
2+
3+
export type IdentityType = {
4+
props: Record<string, any>
5+
events: Record<string, any>
6+
}
7+
8+
type AssertIs<O, T extends O> = T
9+
10+
export interface Identity<T extends IdentityType = IdentityType> {
11+
[IdentitySymbol]: T
12+
}
13+
14+
type MergeRecord<N extends Record<string, any>, O extends Record<string, any>> = {
15+
[I in (keyof N) | (keyof O)]: I extends keyof N ? N[I] : I extends keyof O ? O[I] : never
16+
}
17+
18+
export type MergeIdentityType<N extends IdentityType, O extends IdentityType> = AssertIs<
19+
IdentityType,
20+
{
21+
props: MergeRecord<N['props'], O['props']>
22+
events: MergeRecord<N['events'], O['events']>
23+
}
24+
>
25+

src/index.ts

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,10 @@ export { mixins } from './mixins'
1414
import type { ComponentPublicInstance } from 'vue'
1515
import type { OptionBuilder } from './optionBuilder'
1616
export { TSX } from './tsx/type'
17-
const IdentifySymbol = Symbol('vue-facing-decorator-identify')
18-
export interface BaseTypeIdentify {
19-
[IdentifySymbol]: undefined
20-
}
21-
// export function TSX<Properties extends {} = {}, Events extends {} = {}>() {
22-
// type TEvents = { [index in keyof Events as `on${Capitalize<index & string>}`]: Events[index] extends Function ? Events[index] : { (param: Events[index]): any } }
23-
// return function <C extends VueCons>(cons: C) {
24-
// return cons as unknown as {
25-
// new(): ComponentPublicInstance<Properties & TEvents> & InstanceType<C>//& ComponentPublicInstance & BaseTypeIdentify
26-
// }
27-
// }
28-
// }
17+
import type { IdentityType, Identity, IdentitySymbol } from './identity'
2918

30-
export type VueCons<T = {}> = {
31-
new(optionBuilder: OptionBuilder, vueInstance: any): ComponentPublicInstance & BaseTypeIdentify & T
19+
export type VueCons<RawInstance extends Identity = Identity, IT extends IdentityType = { props:{} , events: {} }, Bundle = IT['props'] & { [index in keyof IT['events']as `on${Capitalize<index & string>}`]?: IT['events'][index] extends Function ? IT['events'][index] : { (param: IT['events'][index]): any } }> = {
20+
new(optionBuilder: OptionBuilder, vueInstance: any): ComponentPublicInstance<Bundle> & Identity<IT> & Omit<RawInstance, typeof IdentitySymbol>
3221
}
3322

3423
export const Base = class {

src/mixins.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@ import { ComponentBase } from './component'
22
import { obtainSlot } from './utils'
33
import type { VueCons } from './index'
44
import { Vue } from './index'
5-
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
6-
type MixedClass<Mixins extends VueCons[]> = UnionToIntersection<{ [index in keyof Mixins]: InstanceType<Mixins[index]> }[number]>
5+
import type { MergeIdentityType, IdentitySymbol } from './identity'
6+
type MixedClass<Mixins extends VueCons[], Base extends VueCons = VueCons> =
7+
Mixins extends [infer T extends VueCons, ...infer E extends VueCons[]] ?
8+
MixedClass<E,
9+
VueCons<InstanceType<Base> & InstanceType<T>,
10+
MergeIdentityType<InstanceType<T>[typeof IdentitySymbol], InstanceType<Base>[typeof IdentitySymbol]>
11+
>
12+
> :
13+
Base
714
export function mixins<T extends VueCons[]>(...conses: T) {
815
class MixinsClass extends Vue {
916

1017
}
1118
ComponentBase({
1219
mixins: conses.map((cons => obtainSlot(cons.prototype).cachedVueComponent))
1320
})(MixinsClass)
14-
return MixinsClass as any as VueCons<MixedClass<T>>
15-
}
16-
17-
1821

22+
return MixinsClass as any as MixedClass<T>
23+
}
1924

2025

2126

src/tsx/type.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
import type { ComponentPublicInstance } from 'vue'
1+
import type { IdentityType, MergeIdentityType, IdentitySymbol } from '../identity'
22
import type { VueCons } from '../index'
3-
export function TSX<Properties extends {} = {}, Events extends {} = {}>() {
4-
type TEvents = { [index in keyof Events as `on${Capitalize<index & string>}`]: Events[index] extends Function ? Events[index] : { (param: Events[index]): any } }
5-
return function <C extends VueCons>(cons: C) {
6-
return cons as unknown as {
7-
new(): ComponentPublicInstance<Properties & TEvents> & InstanceType<C>
8-
}
3+
4+
export function TSX<Properties extends IdentityType['props'] = {}, Events extends IdentityType['events'] = {}, IT extends IdentityType = {
5+
props: Properties
6+
events: Events
7+
}>() {
8+
return function <C extends VueCons>(cons: C): VueCons<InstanceType<C>, MergeIdentityType<IT, InstanceType<C>[typeof IdentitySymbol]>> {
9+
return cons as any
910
}
10-
}
11+
}

src/utils.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Metadata } from 'facing-metadata'
22
import { Base } from './index'
3-
import type { BaseTypeIdentify } from './index'
3+
import type { Identity } from './identity'
44
import type { InjectConfig } from "./option/inject";
55
import type { EmitConfig } from "./option/emit";
66
import type { PropsConfig } from "./option/props";
@@ -153,9 +153,9 @@ export function getValidNames(obj: any, filter: (des: PropertyDescriptor, name:
153153

154154
export function optionNullableMemberDecorator<T>(handler: { (proto: any, name: string, option?: T): any }) {
155155
function decorator(option?: T): any
156-
function decorator(proto: BaseTypeIdentify, name: any): any
156+
function decorator(proto: Identity, name: any): any
157157
function decorator(value: any, ctx: ClassMemberDecoratorContext): any //deco stage 3
158-
function decorator(optionOrProto?: T | BaseTypeIdentify | any, name?: string | ClassMemberDecoratorContext): any {
158+
function decorator(optionOrProto?: T | Identity | any, name?: string | ClassMemberDecoratorContext): any {
159159
if (name) {
160160
compatibleMemberDecorator(function (proto: any, name: any) {
161161
handler(proto, name)

test/feature/mixinsFunction.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,14 @@ class B extends Vue {
2020

2121
@Component
2222
class Comp extends mixins(A, B) {
23-
23+
checkType() {
24+
this.methodA()
25+
this.methodB()
26+
}
2427
}
2528

2629
const CompContext = toNative(Comp) as any
2730

28-
29-
3031
describe('mixins function',
3132
() => {
3233
it('default', () => {

test/tsx/attributeTypes.tsx

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,52 @@
1-
import { Component, TSX, Prop, Base } from '../../dist/esm'
2-
interface Props {
3-
p: string
1+
import { Component, TSX, Base, mixins } from '../../dist/esm'
2+
3+
@Component
4+
class A extends TSX<{
5+
pA: number
6+
}, {
7+
eA: () => void
8+
}>()(Base) {
9+
410
}
5-
interface Events {
6-
e: Function
7-
e2: string
11+
12+
@Component
13+
class B extends TSX<{
14+
pB: number
15+
}, {
16+
eB: () => void
17+
}>()(A) {
18+
819
}
20+
921
@Component
10-
class TsxAttributeTypes extends TSX<Props, Events>()(Base) implements Props {
11-
@Prop({
12-
required: true
13-
})
14-
p!: string
22+
class C extends TSX<{
23+
pC: number
24+
}, {
25+
eC: () => void
26+
}>()(Base) {
27+
28+
}
29+
30+
@Component
31+
class D extends TSX<{
32+
pD:number
33+
}, {
34+
eD: () => void
35+
}>()(mixins(B, C)) {
36+
checkType() {
37+
this.pA
38+
this.onEA
39+
this.pB
40+
this.onEB
41+
this.pC
42+
this.onEC
43+
this.pD
44+
this.onED
45+
46+
}
1547
}
1648

1749
export default {}
1850

19-
// const template = <TsxAttributeTypes p="" onE={() => { }} onE2={() => { }}></TsxAttributeTypes>
51+
52+
// const template = <D q-a={1} kk={1}></D>

0 commit comments

Comments
 (0)