我有这样一个函数:
function refactorQueryResult<D, E>(
name: string,
original: UseQueryResult<D, E>
) {
return {
[name]: original.data,
[`${name}UpdatedAt`]: original.dataUpdatedAt,
[`${name}Error`]: original.error,
[`${name}ErrorUpdatedAt`]: original.errorUpdatedAt,
[`${name}FailureCount`]: original.failureCount,
[`${name}HasError`]: original.isError,
[`${name}Fetched`]: original.isFetched,
[`${name}FetchedAfterMount`]: original.isFetchedAfterMount,
[`${name}Fetching`]: original.isFetching,
[`${name}Idle`]: original.isIdle,
[`${name}Loading`]: original.isLoading,
[`${name}HasLoadingError`]: original.isLoadingError,
[`${name}IsPlaceholder`]: original.isPlaceholderData,
[`${name}IsPrevious`]: original.isPreviousData,
[`${name}HasRefetchError`]: original.isRefetchError,
[`${name}Refetching`]: original.isRefetching,
[`${name}HasSuccess`]: original.isSuccess,
[`${name}IsStale`]: original.isStale,
[`fetch${name[0].toUpperCase()}${name.slice(1)}`]: original.refetch,
[`remove${name[0].toUpperCase()}${name.slice(1)}`]: original.remove,
[`${name}Status`]: original.status,
};
}
但令我沮丧的是,当我使用结果时:
const { cards } = refactorQueryResult("cards", useQuery(listCards(filters)))
Typescript抱怨卡片不存在,但它当然存在。
有没有办法键入提示返回值?
记住我知道我可以做到:
const { data: cards, isFetched: cardsFetched /*, etc */ } = useQuery(listCards(filters))
但是我既懒惰又好奇,所以我想知道是否有一种方法可以浪费几个处理器周期,这样我就可以少打字了。
对于一个简单得多的函数,我尝试过:
function renameData<D, E>(
name: string,
queryResult: UseQueryResult<D, E>
): { [name]: D } & UseQueryOptions<D, E> {
} & UseQueryResult<D, E> {
return { [name]: queryResult.data, ...queryResult }
}
可是这里 typescript 埋怨道:A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type
我认为不添加另一个类型参数是不可能的。所以类似于:
export function refactorQueryResult<T, D, E>(
name: string,
original: UseQueryResult<D, E>
): ComplicatedTemplateMapping<T, UseQueryResult<D, E>> {
// ...
}
// Then elsewhere
const { cards, cardsFetched } = refactorQueryResult<{ cards }>(
"cards", useQuery(listCards(filters))
)
但在这里,我甚至不知道如何开始ComplicatedTemplateMapping
中的检查和切片
2条答案
按热度按时间mwg9r5ms1#
请考虑Map方法:
Playground
f3temu5u2#
所以最后我自己解决了这个问题。事实证明,这是可能的!Typescript很神奇。诀窍是使用第三个类型参数。但实际上你根本不需要指定它。Typescript会检测到它。因此,尽管原始函数签名是:
它现在是:
Typescript很聪明,它可以检测到T应该等于作为参数传入的字符串文字,因此调用以下语句就足够了:
如果你提供一个字符串变量而不是一个文字作为name参数,它将不会工作。它不会显示错误,但结果类型将是一个泛型记录。如果变量的类型是一个字符串文字,它将工作,如果变量类型是一个字符串文字的并集,那么你将获得变量的每个可能值的键和原始类型的每个键。
型别本身的定义如下:
我了解到
infer
几乎是slice的类型等价物,尽管它可以通过更显式的类型完全避免。似乎没有像联合类型那样对条件应用同样的限制。所以实际上我在生产中使用显式版本。但我在这里提供了带有infer
子句的较短版本,以帮助具有不同用例的用户。下面是这段代码的一个练习场,它包括一个
UseQueryResult
类型的模拟,以及一个解构重构类型参数的函数,作为一种测试。