Typescript:使用推断的对象类型用于泛型

问题描述 投票:0回答:1

背景

我正在尝试将 Alpine.js 与 TypeScript 一起使用。为此,我使用社区维护的类型包 @types/alpinejs (GitHub) 以及此处描述的可重用组件设计模式。这是一个使用类型 AlpineComponent<T>

 的简单示例:

// This is the type for alpine components from definitely typed import { AlpineComponent } from "alpinejs"; /** * I have to declare the T-part of the AlpineComponent<T> beforehand, * to be able to use it later. Otherwise, all my custom properties * will have the type "any" */ type Component = AlpineComponent<{ foo: string; greet: (to: string) => string; // The list goes on and on and on in real-world code }> export default (): Component => { return { foo: "foo", // type "string", as defined in the type `Component` bar: "bar", // inconveniently has the type "any", since I didn't declare it inside my type `Component`...will have to do it manually... 😩 greet(to) { return `Hello ${to}!`; }, /** * init() is being invoked automatically by Alpine.js when the component is mounted */ async init() { console.log(this.greet("World")); // greet correctly has the return type "string" await this.$nextTick(); // this is a "magic" method from Alpine.js. It's defined in the type `AlpineComponent`. }, } }
正如您在上面的示例中所看到的,现在我首先使用我将使用的所有属性定义我的类型 

Component = AlpineComponent{...}

。然后在实际构建我的组件时我必须再次
输入它们。 我当前方法的缺点

像我现在一样将所有内容输入两次非常麻烦并且感觉非常混乱。
  1. 按住 Alt 键单击任何属性时,我的 IDE(VS Code)现在总是跳转到自定义类型
  2. Component
  3. 中的 definition,而不是跳转到实际代码中的
    implementation
    。但实际上我总是对实现而不是定义更感兴趣。
  4. 实际问题

有没有更好的方法来组织这个,减少重复输入属性?也许类似于为

AlpineComponent<T>

的动态部分推断从我的组件返回的对象的类型?

    

typescript design-patterns alpine.js definitelytyped
1个回答
0
投票

https://github.com/alpinejs/alpine/issues/2199#issuecomment-1809892127

使用辅助函数来增强 Alpine.js 内部提供的功能就像一个魅力:

utils.ts

import type { AlpineComponent } from 'alpinejs'

export const defineComponent = <P, T>(fn: (params: P) => AlpineComponent<T>) => fn

component.ts

import { defineComponent } from '~/utils/define-component'

export default defineComponent(() => ({
  isOpen: false,
  init() {
    this.$watch('isOpen', (value) => {
      this.onIsOpenChange(value)
    })
  },
  onIsOpenChange(value: boolean) {
    console.log('isOpen changed to ', value)
  }
}))

使用它我现在可以同时使用

使用 Alpine.js 内部结构而不会出现 TypeScript 错误
  1. 从组件本身
  2. 内部
  3. 推断实现(自定义功能)
© www.soinside.com 2019 - 2024. All rights reserved.