diff --git a/test/behavior.test.ts b/test/behavior.test.ts index 603ab83..34ba898 100644 --- a/test/behavior.test.ts +++ b/test/behavior.test.ts @@ -1,6 +1,6 @@ -import { expectType } from 'tsd' +import { expectAssignable, expectType } from 'tsd' -expectType(Behavior({})) +expectAssignable(Behavior({})) Behavior({ behaviors: [], diff --git a/test/component.test.ts b/test/component.test.ts index 226e722..01bfafd 100644 --- a/test/component.test.ts +++ b/test/component.test.ts @@ -1,6 +1,6 @@ -import { expectType, expectError, expectNotAssignable } from 'tsd' +import { expectType, expectError, expectNotAssignable, expectAssignable } from 'tsd' -expectType(Component({})) +expectAssignable(Component({})) Component({ behaviors: [''], @@ -511,3 +511,35 @@ Component<{}, {}, { fn(): void }, []>({ }) } +{ + const def = Component({ + properties: { + a: Boolean, + }, + data: { + b: 1, + }, + methods: { + c() {} + }, + }) + type FieldTypes = (typeof def)['_$fieldTypes'] + expectType(false as boolean) + expectType(false as boolean) + expectType(1 as number) + expectType(() => {}) +} + +{ + type CustomProperties = { + customProp: string + } + Component<{}, {}, {}, [], CustomProperties>({ + lifetimes: { + created() { + this.customProp = 'customProp' + } + } + }) +} + diff --git a/test/page.test.ts b/test/page.test.ts index 18080b6..015b313 100644 --- a/test/page.test.ts +++ b/test/page.test.ts @@ -1,6 +1,6 @@ -import { expectType, expectError, expectNotAssignable } from 'tsd' +import { expectType, expectError, expectNotAssignable, expectAssignable } from 'tsd' -expectType(Page({})) +expectAssignable(Page({})) expectType>(getCurrentPages()[0].data) @@ -241,4 +241,16 @@ Page({ onShareAppMessage(): WechatMiniprogram.Page.ICustomShareContent { return { title: this.data.a, imageUrl: '', path: '' } }, -}) \ No newline at end of file +}) + +{ + const def = Page({ + data: { + b: 1, + }, + c() {}, + }) + type FieldTypes = (typeof def)['_$fieldTypes'] + expectType(1 as number) + expectType(() => {}) +} diff --git a/types/wx/lib.wx.behavior.d.ts b/types/wx/lib.wx.behavior.d.ts index bbf5032..c9a25e4 100644 --- a/types/wx/lib.wx.behavior.d.ts +++ b/types/wx/lib.wx.behavior.d.ts @@ -27,13 +27,7 @@ declare namespace WechatMiniprogram.Behavior { TProperty extends PropertyOption = {}, TMethod extends MethodOption = {}, TBehavior extends BehaviorOption = [] - > = string & { - [key in 'BehaviorType']?: { - data: Component.FilterUnknownType & Component.MixinData - properties: Component.FilterUnknownType & Component.MixinProperties - methods: Component.FilterUnknownType & Component.MixinMethods - } - } + > = string & BehaviorTypeSignature type Instance< TData extends DataOption, TProperty extends PropertyOption, @@ -65,7 +59,7 @@ declare namespace WechatMiniprogram.Behavior { TCustomInstanceProperty extends IAnyObject = Record >( options: Options - ): BehaviorIdentifier + ): string & BehaviorTypeSignature } type DataOption = Component.DataOption @@ -80,6 +74,26 @@ declare namespace WechatMiniprogram.Behavior { type DefinitionFilter = Component.DefinitionFilter type Lifetimes = Component.Lifetimes type OtherOption = Omit + + /** 用于辅助识别 behavior 字段类型的虚拟字段 */ + class BehaviorTypeSignature< + TData extends DataOption, + TProperty extends PropertyOption, + TMethod extends MethodOption, + TBehavior extends BehaviorOption, + > { + protected readonly _$behaviorFieldTypes?: BehaviorTypeSignatureFields + } + type BehaviorTypeSignatureFields< + TData extends DataOption, + TProperty extends PropertyOption, + TMethod extends MethodOption, + TBehavior extends BehaviorOption, + > = { + data: Component.FilterUnknownType & Component.MixinData + properties: Component.FilterUnknownType & Component.MixinProperties + methods: Component.FilterUnknownType & Component.MixinMethods + } } /** 注册一个 `behavior`,接受一个 `Object` 类型的参数。*/ declare let Behavior: WechatMiniprogram.Behavior.Constructor diff --git a/types/wx/lib.wx.component.d.ts b/types/wx/lib.wx.component.d.ts index a3453cb..7028c26 100644 --- a/types/wx/lib.wx.component.d.ts +++ b/types/wx/lib.wx.component.d.ts @@ -94,14 +94,17 @@ declare namespace WechatMiniprogram.Component { TCustomInstanceProperty, TIsPage > - ): string + ): string & ComponentTypeSignature } type DataOption = Record type PropertyOption = Record type MethodOption = Record type BehaviorOption = Behavior.BehaviorIdentifier[] - type ExtractBehaviorType = T extends { BehaviorType?: infer B } ? B : never + type BehaviorFieldTypes = (T & Record)['_$behaviorFieldTypes'] + type ExtractBehaviorType = BehaviorFieldTypes extends Behavior.BehaviorTypeSignatureFields | undefined + ? BehaviorFieldTypes + : never type ExtractData = T extends { data: infer D } ? D : never type ExtractProperties = T extends { properties: infer P } ? TIsBehavior extends true ? P : PropertyOptionToData

: never @@ -111,6 +114,19 @@ declare namespace WechatMiniprogram.Component { type MixinProperties = UnionToIntersection, TIsBehavior>> type MixinMethods = UnionToIntersection>> + /** 用于辅助识别组件类型的虚拟字段(供 glass-easel-analyzer 等外部模块使用) */ + class ComponentTypeSignature< + TData extends DataOption, + TProperty extends PropertyOption, + TMethod extends MethodOption, + > { + protected readonly _$fieldTypes: { + propertyValues: PropertyOptionToData + dataWithProperties: TData & PropertyOptionToData + methods: TMethod + } + } + interface Behavior { /** 类似于mixins和traits的组件间代码复用机制,参见 [behaviors](https://developers.weixin.qq.com/miniprogram/dev/framework/custom-component/behaviors.html) */ behaviors?: B diff --git a/types/wx/lib.wx.page.d.ts b/types/wx/lib.wx.page.d.ts index dd9e5a8..08da4d4 100644 --- a/types/wx/lib.wx.page.d.ts +++ b/types/wx/lib.wx.page.d.ts @@ -42,7 +42,11 @@ declare namespace WechatMiniprogram.Page { interface Constructor { ( options: Options - ): void + ): void & Component.ComponentTypeSignature< + TData, + Record, + { [K in keyof TCustom as TCustom[K] extends Function ? K : never]: TCustom[K] } + > } interface ILifetime { /** 生命周期回调—监听页面加载