Skip to content

Commit 6b8e1d3

Browse files
authored
Merge pull request #333 from lv-z-l/behavior-ts-support
feat: behavior ts type support
2 parents 0a76c78 + e940cb8 commit 6b8e1d3

File tree

7 files changed

+182
-25
lines changed

7 files changed

+182
-25
lines changed

test/behavior.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expectType } from 'tsd'
22

3-
expectType<string>(Behavior({}))
3+
expectType<string & {}>(Behavior({}))
44

55
Behavior({
66
behaviors: [],

test/component.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ Component({
418418
},
419419
})
420420

421-
Component<{}, {}, { fn(): void }>({
421+
Component<{}, {}, { fn(): void }, []>({
422422
methods: {
423423
fn() {
424424
expectError(this.notExists)
@@ -442,7 +442,8 @@ Component<{}, {}, { fn(): void }>({
442442
typeof data,
443443
typeof properties,
444444
/* methods= */{ fn(): string },
445-
/* customProperties= */{},
445+
/* behaviors= */ [],
446+
/* customProperties= */{},
446447
/* isPage= */true
447448
>({
448449
data,
@@ -496,7 +497,7 @@ Component<{}, {}, { fn(): void }>({
496497
type CustomProperties = {
497498
customProp: string
498499
}
499-
Component<{}, {}, {}, CustomProperties>({
500+
Component<{}, {}, {}, [], CustomProperties>({
500501
lifetimes: {
501502
created() {
502503
this.customProp = 'customProp'

test/computed.test.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ declare namespace WechatMiniprogram {
1414
M extends MethodOption,
1515
C extends ComputedOption,
1616
CustomProperty extends IAnyObject = Record<string, never>,
17-
> = Instance<D, P, M, CustomProperty> & { data: ComputedOptionToData<C> }
17+
> = Instance<D, P, M, [], CustomProperty> & { data: ComputedOptionToData<C> }
1818
type ComputedOptions<
1919
D extends DataOption,
2020
P extends PropertyOption,
@@ -23,7 +23,7 @@ declare namespace WechatMiniprogram {
2323
CustomProperty extends IAnyObject = Record<string, never>,
2424
> = Partial<Computed<C>> &
2525
ThisType<ComputedInstance<D, P, M, C, CustomProperty>> &
26-
Options<D, P, M>
26+
Options<D, P, M, []>
2727
interface ComputedConstructor {
2828
<
2929
D extends DataOption,

test/computed.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ ComputedComponent({
2525
})
2626

2727
type IMethods = {
28-
_setData: WechatMiniprogram.Component.InstanceMethods<{}>['setData'],
28+
_setData: WechatMiniprogram.Component.InstanceMethods<{}>['setData']
2929
}
3030
type ICustomProperty = {
31-
_originalSetData: WechatMiniprogram.Component.InstanceMethods<{}>['setData'],
31+
_originalSetData: WechatMiniprogram.Component.InstanceMethods<{}>['setData']
3232
}
33-
Behavior<{}, {}, IMethods, ICustomProperty>({
33+
Behavior<{}, {}, IMethods, [], ICustomProperty>({
3434
lifetimes: {
3535
created() {
3636
this._originalSetData = this.setData

test/issue.test.ts

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ wx.request({
174174
f?: () => string
175175
g: () => void
176176
}
177-
type Dialog = WechatMiniprogram.Component.Instance<{}, {}, IDialogMethod>
177+
type Dialog = WechatMiniprogram.Component.Instance<{}, {}, IDialogMethod, []>
178178
Page({
179179
f() {
180180
const comp = this.selectComponent('#comp') as Dialog
@@ -285,10 +285,11 @@ import WX = WechatMiniprogram
285285
type IMethod = {
286286
setJob(job: string): void
287287
}
288+
type IBehavior = []
288289
type ICustomInstanceProperty = {
289290
job: string
290291
}
291-
Component<IData, IProperty, IMethod, ICustomInstanceProperty>({
292+
Component<IData, IProperty, IMethod, IBehavior, ICustomInstanceProperty>({
292293
properties: {
293294
id: Number,
294295
},
@@ -458,6 +459,7 @@ import WX = WechatMiniprogram
458459
})
459460
}
460461

462+
// https://github.com/wechat-miniprogram/api-typings/issues/332
461463
{
462464
interface Foo {
463465
f: string
@@ -481,8 +483,119 @@ import WX = WechatMiniprogram
481483
},
482484
test() {
483485
expectType<Foo>(this.data.bar)
486+
expectType<Foo>(this.properties.bar)
484487
expectType<Foo[]>(this.getData())
485488
},
486489
}
487490
})
491+
}
492+
493+
// https://github.com/wechat-miniprogram/api-typings/issues/332
494+
{
495+
const bA = Behavior({
496+
properties: {
497+
pA: {
498+
type: String,
499+
value: '',
500+
},
501+
pA1: Boolean
502+
},
503+
data: {
504+
dataA: 'init data',
505+
},
506+
methods: {
507+
methodA() {
508+
return this.data.dataA
509+
},
510+
},
511+
})
512+
const bB = Behavior({
513+
properties: {
514+
pB: {
515+
type: Array,
516+
value: [] as string[],
517+
}
518+
},
519+
data: {
520+
dataB: [] as string[],
521+
},
522+
methods: {
523+
methodB() {
524+
return this.data.dataB
525+
},
526+
},
527+
})
528+
529+
Component({
530+
behaviors: [bA, bB],
531+
methods: {
532+
test() {
533+
expectType<string>(this.data.pA)
534+
expectType<boolean>(this.data.pA1)
535+
expectType<string>(this.data.dataA)
536+
expectType<string[]>(this.data.pB)
537+
expectType<string[]>(this.data.dataB)
538+
expectType<string>(this.methodA())
539+
expectType<string[]>(this.methodB())
540+
},
541+
}
542+
})
543+
}
544+
// https://github.com/wechat-miniprogram/api-typings/issues/332#issuecomment-2333434425
545+
{
546+
const b1 = Behavior({
547+
properties: {
548+
pA: {
549+
type: String,
550+
value: '',
551+
},
552+
pA1: Boolean
553+
},
554+
data: {
555+
dataA: 'init data',
556+
},
557+
methods: {
558+
methodA() {
559+
return this.data.dataA
560+
},
561+
},
562+
})
563+
const b2 = Behavior({
564+
behaviors: [b1],
565+
properties: {
566+
pB: {
567+
type: Array,
568+
value: [] as string[],
569+
}
570+
},
571+
data: {
572+
dataB: [] as string[],
573+
},
574+
methods: {
575+
methodB() {
576+
return this.data.dataB
577+
},
578+
test() {
579+
expectType<string>(this.data.pA)
580+
expectType<boolean>(this.data.pA1)
581+
expectType<string>(this.data.dataA)
582+
expectType<string>(this.methodA())
583+
},
584+
},
585+
})
586+
587+
Component({
588+
behaviors: [b2],
589+
methods: {
590+
test() {
591+
expectType<string>(this.data.pA)
592+
expectType<boolean>(this.data.pA1)
593+
expectType<string>(this.data.dataA)
594+
expectType<string[]>(this.data.pB)
595+
expectType<string[]>(this.data.dataB)
596+
expectType<string>(this.methodA())
597+
expectType<string[]>(this.methodB())
598+
},
599+
}
600+
})
488601
}

types/wx/lib.wx.behavior.d.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,47 +21,64 @@ SOFTWARE.
2121
***************************************************************************** */
2222

2323
declare namespace WechatMiniprogram.Behavior {
24-
type BehaviorIdentifier = string
24+
25+
type BehaviorIdentifier<
26+
TData extends DataOption = {},
27+
TProperty extends PropertyOption = {},
28+
TMethod extends MethodOption = {},
29+
TBehavior extends BehaviorOption = []
30+
> = string & {
31+
[key in 'BehaviorType']?: {
32+
data: TData & Component.MixinData<TBehavior>
33+
properties: TProperty & Component.MixinProperties<TBehavior, true>
34+
methods: TMethod & Component.MixinMethods<TBehavior>
35+
}
36+
}
2537
type Instance<
2638
TData extends DataOption,
2739
TProperty extends PropertyOption,
2840
TMethod extends MethodOption,
41+
TBehavior extends BehaviorOption,
2942
TCustomInstanceProperty extends IAnyObject = Record<string, never>
30-
> = Component.Instance<TData, TProperty, TMethod, TCustomInstanceProperty>
31-
type TrivialInstance = Instance<IAnyObject, IAnyObject, IAnyObject>
32-
type TrivialOption = Options<IAnyObject, IAnyObject, IAnyObject>
43+
> = Component.Instance<TData, TProperty, TMethod, TBehavior, TCustomInstanceProperty>
44+
type TrivialInstance = Instance<IAnyObject, IAnyObject, IAnyObject, Component.IEmptyArray>
45+
type TrivialOption = Options<IAnyObject, IAnyObject, IAnyObject, Component.IEmptyArray>
3346
type Options<
3447
TData extends DataOption,
3548
TProperty extends PropertyOption,
3649
TMethod extends MethodOption,
50+
TBehavior extends BehaviorOption,
3751
TCustomInstanceProperty extends IAnyObject = Record<string, never>
3852
> = Partial<Data<TData>> &
3953
Partial<Property<TProperty>> &
4054
Partial<Method<TMethod>> &
55+
Partial<Behavior<TBehavior>> &
4156
Partial<OtherOption> &
4257
Partial<Lifetimes> &
43-
ThisType<Instance<TData, TProperty, TMethod, TCustomInstanceProperty>>
58+
ThisType<Instance<TData, TProperty, TMethod, TBehavior, TCustomInstanceProperty>>
4459
interface Constructor {
4560
<
4661
TData extends DataOption,
4762
TProperty extends PropertyOption,
4863
TMethod extends MethodOption,
64+
TBehavior extends BehaviorOption,
4965
TCustomInstanceProperty extends IAnyObject = Record<string, never>
5066
>(
51-
options: Options<TData, TProperty, TMethod, TCustomInstanceProperty>
52-
): BehaviorIdentifier
67+
options: Options<TData, TProperty, TMethod, TBehavior, TCustomInstanceProperty>
68+
): BehaviorIdentifier<TData, TProperty, TMethod, TBehavior>
5369
}
5470

5571
type DataOption = Component.DataOption
5672
type PropertyOption = Component.PropertyOption
5773
type MethodOption = Component.MethodOption
74+
type BehaviorOption = Component.BehaviorOption
5875
type Data<D extends DataOption> = Component.Data<D>
5976
type Property<P extends PropertyOption> = Component.Property<P>
6077
type Method<M extends MethodOption> = Component.Method<M>
78+
type Behavior<B extends BehaviorOption> = Component.Behavior<B>
6179

6280
type DefinitionFilter = Component.DefinitionFilter
6381
type Lifetimes = Component.Lifetimes
64-
6582
type OtherOption = Omit<Component.OtherOption, 'options'>
6683
}
6784
/** 注册一个 `behavior`,接受一个 `Object` 类型的参数。*/

types/wx/lib.wx.component.d.ts

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,41 +26,51 @@ declare namespace WechatMiniprogram.Component {
2626
TData extends DataOption,
2727
TProperty extends PropertyOption,
2828
TMethod extends Partial<MethodOption>,
29+
TBehavior extends BehaviorOption,
2930
TCustomInstanceProperty extends IAnyObject = {},
3031
TIsPage extends boolean = false
3132
> = InstanceProperties &
3233
InstanceMethods<TData> &
3334
TMethod &
35+
MixinMethods<TBehavior> &
3436
(TIsPage extends true ? Page.ILifetime : {}) &
35-
TCustomInstanceProperty & {
37+
Omit<TCustomInstanceProperty, 'properties' | 'methods' | 'data'> & {
3638
/** 组件数据,**包括内部数据和属性值** */
37-
data: TData & PropertyOptionToData<FilterUnknownProperty<TProperty>>
39+
data: TData & MixinData<TBehavior> &
40+
MixinProperties<TBehavior> & PropertyOptionToData<FilterUnknownProperty<TProperty>>
3841
/** 组件数据,**包括内部数据和属性值**(与 `data` 一致) */
39-
properties: TData & PropertyOptionToData<FilterUnknownProperty<TProperty>>
42+
properties: TData & MixinData<TBehavior> &
43+
MixinProperties<TBehavior> & PropertyOptionToData<FilterUnknownProperty<TProperty>>
4044
}
45+
46+
type IEmptyArray = []
4147
type TrivialInstance = Instance<
4248
IAnyObject,
4349
IAnyObject,
4450
IAnyObject,
51+
IEmptyArray,
4552
IAnyObject
4653
>
47-
type TrivialOption = Options<IAnyObject, IAnyObject, IAnyObject, IAnyObject>
54+
type TrivialOption = Options<IAnyObject, IAnyObject, IAnyObject, IEmptyArray, IAnyObject>
4855
type Options<
4956
TData extends DataOption,
5057
TProperty extends PropertyOption,
5158
TMethod extends MethodOption,
59+
TBehavior extends BehaviorOption,
5260
TCustomInstanceProperty extends IAnyObject = {},
5361
TIsPage extends boolean = false
5462
> = Partial<Data<TData>> &
5563
Partial<Property<TProperty>> &
5664
Partial<Method<TMethod, TIsPage>> &
65+
Partial<Behavior<TBehavior>> &
5766
Partial<OtherOption> &
5867
Partial<Lifetimes> &
5968
ThisType<
6069
Instance<
6170
TData,
6271
TProperty,
6372
TMethod,
73+
TBehavior,
6474
TCustomInstanceProperty,
6575
TIsPage
6676
>
@@ -70,13 +80,15 @@ declare namespace WechatMiniprogram.Component {
7080
TData extends DataOption,
7181
TProperty extends PropertyOption,
7282
TMethod extends MethodOption,
83+
TBehavior extends BehaviorOption,
7384
TCustomInstanceProperty extends IAnyObject = {},
7485
TIsPage extends boolean = false
7586
>(
7687
options: Options<
7788
TData,
7889
TProperty,
7990
TMethod,
91+
TBehavior,
8092
TCustomInstanceProperty,
8193
TIsPage
8294
>
@@ -86,6 +98,22 @@ declare namespace WechatMiniprogram.Component {
8698
type PropertyOption = Record<string, AllProperty>
8799
type MethodOption = Record<string, Function>
88100

101+
type BehaviorOption = Behavior.BehaviorIdentifier[]
102+
type ExtractBehaviorType<T> = T extends { BehaviorType?: infer B } ? B : never
103+
type ExtractData<T> = T extends { data: infer D } ? D : never
104+
type ExtractProperties<T, TIsBehavior extends boolean = false> = T extends { properties: infer P } ?
105+
TIsBehavior extends true ? P : PropertyOptionToData<P extends PropertyOption ? P : {}> : never
106+
type ExtractMethods<T> = T extends { methods: infer M } ? M : never
107+
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never
108+
type MixinData<T extends any[]> = UnionToIntersection<ExtractData<ExtractBehaviorType<T[number]>>>
109+
type MixinProperties<T extends any[], TIsBehavior extends boolean = false> = UnionToIntersection<ExtractProperties<ExtractBehaviorType<T[number]>, TIsBehavior>>
110+
type MixinMethods<T extends any[]> = UnionToIntersection<ExtractMethods<ExtractBehaviorType<T[number]>>>
111+
112+
interface Behavior<B extends BehaviorOption> {
113+
/** 类似于mixins和traits的组件间代码复用机制,参见 [behaviors](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html) */
114+
behaviors?: B
115+
}
116+
89117
interface Data<D extends DataOption> {
90118
/** 组件的内部数据,和 `properties` 一同用于组件的模板渲染 */
91119
data?: D
@@ -524,8 +552,6 @@ declare namespace WechatMiniprogram.Component {
524552
}
525553

526554
interface OtherOption {
527-
/** 类似于mixins和traits的组件间代码复用机制,参见 [behaviors](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html) */
528-
behaviors: Behavior.BehaviorIdentifier[]
529555
/**
530556
* 组件数据字段监听器,用于监听 properties 和 data 的变化,参见 [数据监听器](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/observer.html)
531557
*

0 commit comments

Comments
 (0)