收藏
回答

使用typescript开发behavior,调用data 的数据过不了类型检测怎么办?

1、创建一个behavior,并在组件中引入这个behavior,调用behavior里的data和方法 都会报错不存在该属性或者方法;虽然是可以用as any 就可以调用到,但是有没有更好的解决方法呢?

2、在组件中引入这个behavior,调用behavior里的data和方法 都会报错不存在该属性或者方法;

回答关注问题邀请回答
收藏

9 个回答

  • niniyou
    niniyou
    2022-08-29
    declare namespace WechatMiniprogram.Page {
      interface ILifetime {
        test():void;
      }
    }
    declare namespace WechatMiniprogram.Component {
      interface InstanceMethods<D extends DataOption> {
        test(): void;
      }
    }
    

    可以尝试在类型声明中typings/index.d.ts进行声明类型扩展,应该会有用

    2022-08-29
    有用 2
    回复 1
    • Damon
      Damon
      2023-02-21
      不错
      2023-02-21
      回复
  • 尹joy
    尹joy
    02-01

    我有一个相对来说比较省力,校验完备,但不那么优雅的解决方案。

    废话少说,代码如下:

    // use.ts
    function useBehavior<TData extends WechatMiniprogram.Behavior.DataOption,
      TProperty extends WechatMiniprogram.Behavior.PropertyOption,
      TMethod extends WechatMiniprogram.Behavior.MethodOption,
      TCustomInstanceProperty extends WechatMiniprogram.IAnyObject = Record<string, never>>(opt: Partial<WechatMiniprogram.Component.Data<TData>> &
        Partial<WechatMiniprogram.Component.Property<TProperty>> &
        Partial<WechatMiniprogram.Component.Method<TMethod>> &
        Partial<WechatMiniprogram.Component.OtherOption> &
        Partial<WechatMiniprogram.Component.Lifetimes> &
        ThisType<WechatMiniprogram.Component.Instance<TData, TProperty, TMethod, TCustomInstanceProperty>>) {
      const behaviorID = Behavior(opt)
      return {
        behaviorID,
        // 仅仅为了方便获取内部变量类型故
        _optType: {} as typeof opt,
      }
    }
    export {
      useBehavior
    }
    
    // detailBehavior.ts
    import { useBehavior } from "@/utils/use"
    const {
      behaviorID,
      _optType,
    } = useBehavior({
      properties: {
        detailId: {
          type: String,
          value: ''
        },
      },
      data: {
        isDetailLoading: false as boolean,
        detailLoadError: '',
        isDetail: false as boolean,
      },
      observers: {
        'detailId': function (newDetailId) {
          if (!newDetailId || this.data.isDetailLoading) {
            return
          }
          this.setData({
            isDetailLoading: true,
            detailLoadError: '',
            isDetail: true
          })
          const needSetData = {}
          this.getDetailByDetailId?.(this.data.detailId)?.then()?.catch((err) => {
            Object.assign(needSetData, {
              detailLoadError: err.toString()
            })
          })?.finally(() => {
            Object.assign(needSetData, {
              isDetailLoading: false
            })
            this.setData(needSetData)
          })
        }
      },
      methods: {
        getDetailByDetailId(id: number | string) {
          return Promise.resolve('')
        }
      }
    })
    export default behaviorID
    // 此处已经把当前behavior特有的data(properties)和methods导出来了
    export type DetailBehavior = typeof _optType
    
    // detail.ts
    import detailBehavior, { DetailBehavior } from './detailBehavior'
    import ortherBehavior, { BehaviorOrthers } from './detailBehavior'
    Component({
      behaviors: [detailBehavior, ortherBehavior]
      data: {
        anyDataInThisComponent: {},
        ...{} as DetailBehavior['data'] & BehaviorOrthers['data']
      },
      methods: {
        ...{} as DetailBehavior['methods'] & BehaviorOrthers['methods']
        ortherSelfMethod(){ },
      }
    })
    
    02-01
    有用
    回复
  • Roger🌌
    Roger🌌
    2023-05-05

    我支持楼上不用behavior,而是自己手动展开。behavior这个是普通Object,随意发挥了。

    2023-05-05
    有用
    回复
  • 晴天
    晴天
    2023-03-15

    封装一个use方法

    export function useSmsBehavior(data: TData){
      const smsBehavior = Behavior({
        data: {
          useName: "",
        },
        methods: {
          test(){
            ...
          }
        },
        ...
      });
      return {
        data: data as TData & {
          // add data in behavior
          useName: string;
        },
        smsBehavior,
      };
    }
    


    使用Behavior

    const {smsBehavior, data} = useSmsBehavior({money: 100});
    
    Component({
      behaviors: [smsBehavior],
      properties: {},
      data,
      method: {
        getMoney(){
          console.log(this.data.money, this.data.userName);
          this.test();
        }
      }
    }
    
    


    方法

    declare namespace WechatMiniprogram.Page {
      interface ILifetime {
        test():void;
      }
    }
    declare namespace WechatMiniprogram.Component {
      interface InstanceMethods {
        test(): void;
      }
    }
    


    方法的处理可能会污染没有使用behavior的页面。如果不怕麻烦也可以把properties、methods丢进use方法里处理一下。

    2023-03-15
    有用
    回复
  • class.lfz
    class.lfz
    2022-10-19

    遇到同样的问题,我的解决方案是弃用了behavior这个功能,将data跟methods封装起来,在Page/Component函数被调用时再添加进去...为了语法上的声明,选择了不用behavior,有点无奈。

    // funcs/test.ts
    export const testData = {
      test:  ''
    }
    export const testMethods = {
      // 但是函数内如果要使用this,就要对this再加上声明
      test (this: WechatMiniprogram.Page.Instance<typeof testData, {}>) {
        // do something
        this.setData({
          test: 'hello world'
        })
      }
    }
    
    // components/x/x.ts
    import { testData, testMethods } from 'path/to/funcs/test'
    Component({
      data: {
        ...testData,
        // other component data
      },
      methods: {
        ...testMethods,
        // other component methods
      }
    })
    
    // pages/x/x.ts
    import { testData, testMethods } from 'path/to/funcs/test'
    Page({
      ...testMethods,
      data: {
        ...testData,
        // other page data
      },
      // other page methods
    })
    


    2022-10-19
    有用
    回复
  • wawuwaelo
    wawuwaelo
    2022-07-11

    最后怎么解决的??

    2022-07-11
    有用
    回复
  • 不吱
    不吱
    2021-05-27

    同求解……我每次都要 (this as any).test() ,但这样看起来很拉跨

    2021-05-27
    有用
    回复
  • 生不可无你
    生不可无你
    2021-03-30

    这个恐怕无解。

    behavior是通过一个识别符在运行时嵌入的, 然后这个identifier是个string。Typescript的类型推断不可能从这个string里推导出你需要的类型。

    能想到的唯一办法就是你自己写一个新的类Component的函数,把behavior的类型作为generic parameter传进去,然后用它来调用原来的Component的并更改相应的类型参数。

    还是不够雅致,但这个behavior就是这样设计的。。。

    如果不是通过string而是通过object嵌入,或者全部是类React Hooks的函数式编程好多类型推导会方便很多。

    2021-03-30
    有用
    回复
  • Sheep
    Sheep
    2020-07-15

    遇到同样的问题,求解(typescript)

    2020-07-15
    有用
    回复
登录 后发表内容
问题标签