JavaScript 组件转换为 TypeScript:props 的类型是什么
从JavaScript + Options API迁移Vuejs项目到打字稿 + Coption API,我逐渐发现了大多数内容的等效物。我正在努力的一件事是
v-Model
功能。我找到了一个
使用构图API
,其中作者创建了一个可复合功能,可以在要实现
v-model
的组件中重复使用。我现在正在尝试使用Typescript编写等效函数。
这是原始JS代码:
365698686
我的TS实现看起来像这样:< /p>
163269010
此编译罚款,但VUE对此并不满意。我得到
066492575
如果我在组件中使用此功能。
我的怀疑是
props props
的类型TS版本不正确,但是我无法弄清楚在那里应该使用哪种类型。我已经使用
对象
,
未知
和
任何
尝试过,但是它们都不允许我做
props [name]
在getter中(
任何
都这样做,但TS抱怨我不应该使用
任何
作为
props
的类型)。
编辑
这是完整的错误文本:
711750269
编辑2
这是我在组件中使用此功能的方式:
08888858623
看到您自己的回答后,我觉得这可能更加严格。
import { computed, WritableComputedRef } from '@vue/composition-api'
export function useModelWrapper<TProps, TKey extends keyof TProps> (
props: TProps,
emit: (event: string, value: TProps[TKey]) => void,
name: TKey = 'modelValue' as TKey
) : WritableComputedRef<TProps[TKey]> {
return computed<TProps[TKey]>({
get: () => props[name],
set: (value: TProps[TKey]) => emit('input', value)
})
}
我还没有专门用 Vue 测试过,但该函数应该限制您可以将哪个键作为第三个参数传递,并根据传递的
name
而不是所有
props
值的并集正确推断返回类型。
以防万一它能帮助到其他人,事实证明我在组件中使用了错误版本的
PropType
来定义我的
v-model
prop。真正的
PropType
类应该像这样导入:
import { PropType } from '@vue/composition-api'
而不是:
import Vue, { PropType } from 'vue'
编辑
如果它能帮助到任何人,下面是我最终使用 Composition API 和 TypeScript 实现强类型
v-model
的方法:
import { computed, WritableComputedRef } from '@vue/composition-api'
export interface IIndexable<T> { [key: string]: T }
export function useModelWrapper<T> (props: IIndexable<T>, emit: (event: string, value: T) => void, name = 'modelValue') : WritableComputedRef<T> {
return computed<T>({
get: () => props[name] as T,
set: (value: T) => emit('input', value as T)
})
}
然后,您可以像这样将其导入任何组件:
export default defineComponent({
name: 'ProjectsDropdown',
props: {
value: Object as PropType<Project>
},
setup (props, { emit }) {
const selectedProject = useModelWrapper<Project>(props, emit, 'value')
return { selectedProject }
}
}
并将其绑定到您想要在组件模板中绑定的任何内容。
请注意,这在 Vue 2.x 中有效。对于 Vue 3,您需要将
value
prop 的名称更改为
modelValue
,并将上述代码中的
emit('input', value as T)
更改为
emit('update:modelValue', value)
。
编辑 2
请参阅下面 @emeraldsanto 的回答。它提供了更好的实现。
这是 @emeraldsanto 答案的扩展,但类型推断是 Vue 3 组件发出的字符串
export function useModelWrapper<TProps extends Record<string, unknown> | { modelValue: unknown },
TKey extends keyof TProps & string = 'modelValue',
TEmit extends (event: `update:${TKey}`, value: TProps[TKey]) => void = (event: `update:${TKey}`, value: TProps[TKey]) => void > (
props: TProps,
emit: TEmit,
name: TKey = 'modelValue' as TKey
) : WritableComputedRef<TProps[TKey]> {
return computed<TProps[TKey]>({
get: () => props[name],
set: (value: TProps[TKey]) => emit(`update:${name}` as `update:${TKey}`, value)
})
}
类似使用
const props = defineProps<{
modelValue: string
foo?: number
}> ()
const emit = defineEmits<{
(e: 'update:modelValue', id: string): void
(e: 'update:foo', value: number | undefined): void
}> ()
const value = useModelWrapper(props, emit)
const fooValue = useModelWrapper(props, emit, 'foo')