有什么办法可以在打字稿中将泛型标记为强制性的?
function onSubmit<Result, Variables>({
foo,
bar
}: {
foo: Result
bar: Variables
}) {
console.log(foo, bar)
}
// this should not be possible without passing the Generics
onSubmit({ foo: 'foo', bar: 'bar' })
// this works as expected
onSubmit<number, number>({ foo: 'foo', bar: 'bar' })
该问题已得到回答,它就像一个咒语。为了更好地理解我为什么要使用此功能,这是一个示例。
onSubmit<UpdateUserMutation, UpdateUserMutationVariables>({
mutation: UpdateUserDocument,
variables: { id: user.id, user: formData },
refetchQueries: ['GetUserList'],
onSuccess: ({ data }) => history.push(`/users/${data.updateUser.id}`),
})
当我省略<UpdateUserMutation, UpdateUserMutationVariables>
时,我不知道data
函数中将有onSuccess
是什么。此外,我不知道必须将哪些变量传递给variables
键。更不用说IDE集成了:-)
可以肯定的是,我可以直接键入{ data }
,但是现在我觉得它更舒服了,因为我不能“忘记”键入,因此我永远不会在{{ 1}}对象和variables
函数。
对于好奇的人,这是我的onSuccess
函数现在的外观:
onSubmit
答案 0 :(得分:5)
故意使类型混乱的推断似乎很不幸,但是如果我愿意的话,这就是我可能要做的事情:
function onSubmit<
Result = [Error, "Please specify the Result type parameter"],
Variables = [Error, "Please specify the Variables type parameter"],
R extends Result = Result,
V extends Variables = Variables
>({
foo,
bar
}: {
foo: R
bar: V
}) {
console.log(foo, bar)
}
想法是使用generic type parameter defaults来使我们对非推断类型参数发生的事情有更多的控制,并添加一些额外的类型参数以从编译器中删除类型推断站点。类型Result
和Variables
不能从传递的foo
和bar
属性的值中推断出来。在类型签名中甚至都没有提到它们。这意味着,如果未手动指定Result
和Variables
,它们将默认为[Error, "error message"]
形式的怪异元组类型。对于TypeScript中缺少"invalid" type的情况,该奇怪的元组类型是一种解决方法。我本来可以选择never
,但是错误消息可能更含糊。
无论如何,foo
会推断R
,而bar
会推断V
,必须分别分配给Result
和Variables
。这意味着如果您不指定Result
和Variables
,它们将默认为某种错误类型,然后foo
和bar
将被限制为该错误。键入,您将得到一个错误:
onSubmit({ foo: 'foo', bar: 'bar' }) // error
// ~~~ ~~~
// 'string' not assignable to 'Error, "Please specify the Result type parameter"'
// 'string' not assignable to 'Error, "Please specify the Variables type parameter"'
如果您要做手动指定Result
和Variables
,则R
和V
将被限制在它们上(并且默认为它们),因此应与以前的版本相同:
onSubmit<string>({ foo: 'foo', bar: 'bar' }) // error
// ~~~
// 'string' not assignable to 'Error, "Please specify the Variables type parameter"'
onSubmit<number, number>({ foo: 3, bar: 4 }) // okay
onSubmit<number, number>({ foo: 'foo', bar: 'bar' }) // error
// ~~~ ~~~
// 'string' not assignable to 'number' x2
这很丑陋,因为该语言不希望您这样做...类型推断通常是一件好事。但这就是您要的,所以...是吗?希望能有所帮助。祝你好运!