You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为对象的this注入OtherProps,消除TypeScript的$watch属性报错?

解决TypeScript中注入扩展属性的类型提示问题

问题场景

我有一个返回对象的函数,后续该对象会被外部扩展$watch这类属性,但TypeScript会提示“Property '$watch' does not exist on type ...”的错误。代码示例如下:

export default () => {
  const myObject = {
    property1: 'string1',
    property2: 1,
    init() {
      console.log('property1', this.property1)

      this.$watch('property1', (value) => { 
        console.log('property1 changed', value)
      })
    },
  }

  return myObject
}

对应的扩展属性接口定义:

interface OtherProps<T> {
  $watch: <K extends keyof T | string, V extends K extends keyof T ? T[K] : any>(
        property: K,
        callback: (newValue: V, oldValue: V) => void,
    ) => void;
  // ... 其他扩展属性
}

我已经实现了一种类型定义方式,但需要单独编写对象类型,步骤繁琐:

type WithProps<T> = ThisType<T & OtherProps<T>>

type Test = WithProps<{
  property1: string
  property2: number
  init(): void
}>

export default () => {
  const myObject: Test = {
    property1: 'string1',
    property2: 1,
    init() {},
  }

  return myObject
}

优化方案

方案一:自动推导类型并交叉断言

直接利用typeof推导对象的原始类型,再与OtherProps交叉,不需要手动定义对象类型:

export default () => {
  const myObject = {
    property1: 'string1',
    property2: 1,
    init() {
      console.log('property1', this.property1)
      this.$watch('property1', (value) => { 
        console.log('property1 changed', value)
      })
    },
  }

  type MyObjectType = typeof myObject;
  // 断言为原始类型与扩展属性的交叉类型
  return myObject as MyObjectType & OtherProps<MyObjectType>;
}

方案二:利用Object.assign隐式合并类型

通过Object.assign先声明扩展属性的类型,再合并自身对象属性,TypeScript会自动处理交叉类型:

export default () => {
  const myObject = Object.assign({} as OtherProps<typeof myObject>, {
    property1: 'string1',
    property2: 1,
    init() {
      console.log('property1', this.property1)
      this.$watch('property1', (value) => { 
        console.log('property1 changed', value)
      })
    },
  })

  return myObject;
}

方案三:封装工具函数复用逻辑

把类型处理逻辑封装成工具函数,后续直接传入对象字面量即可,无需重复编写类型:

interface OtherProps<T> {
  $watch: <K extends keyof T | string, V extends K extends keyof T ? T[K] : any>(
        property: K,
        callback: (newValue: V, oldValue: V) => void,
    ) => void;
  // ... 其他扩展属性
}

// 封装工具函数,自动推导对象类型并绑定this上下文
const createWithProps = <T extends object>(obj: T & ThisType<T & OtherProps<T>>): T & OtherProps<T> => {
  return obj as T & OtherProps<T>;
}

export default () => {
  return createWithProps({
    property1: 'string1',
    property2: 1,
    init() {
      console.log('property1', this.property1)
      this.$watch('property1', (value) => { 
        console.log('property1 changed', value)
      })
    },
  })
}

这三种方案都可以避免手动编写对象类型,让TypeScript正确识别扩展的$watch属性,同时保持代码简洁。

内容的提问来源于stack exchange,提问作者Mickael Chanrion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 09:40:25