gpt4 book ai didi

javascript - typescript 泛型包装器 : Untyped function calls may not accept type arguments

转载 作者:行者123 更新时间:2023-11-30 19:37:24 50 4
gpt4 key购买 nike

这段带有泛型的代码片段工作得很好( Link to Simple and Working Code )

const state: Record<string, any> = {
isPending: false,
results: ['a', 'b', 'c']
}

const useValue = <T extends {}>(name: string): [T, Function] => {
const value: T = state[name]
const setValue: Function = (value: T): void => {
state[name] = value
}
return [value, setValue]
}

const [isPending, setIsPending] = useValue<boolean>('isPending')
const [results, setResults] = useValue<string[]>('results')

在这里我可以确定 isPending 是一个 bool 值并且 setIsPending 接收一个 bool 值作为参数。同样适用于 resultssetResults 作为字符串数组。

然后我用另一种方法包装代码 useStore ( Link to Extended Broken Code )

interface UseStore {
state: Record<string, any>
useValue: Function
}

const state: Record<string, any> = {
isPending: false,
results: ['a', 'b', 'c']
}

const useStore = (): UseStore => {
const useValue = <T extends {}>(name: string): [T, Function] => {
const value: T = state[name]
const setValue: Function = (value: T): void => {
state[name] = value
}
return [value, setValue]
}

return { state, useValue }
}

const { useValue } = useStore()
const [isPending, setIsPending] = useValue<boolean>('isPending')
const [results, setResults] = useValue<string[]>('results')

最后两行给我 typescript 错误:Untyped function calls may not accept type arguments.

我怀疑 useStore 接口(interface)有问题,但由于它的动态特性,我想不出更好的解决方案。

如何在使用泛型类型时消除错误以获得正确的类型提示和代码完成?

最佳答案

由于useValue 的类型是Function,所以传递泛型参数是没有意义的。他们对谁有利?运行时没有得到它们,它们在编译时被删除。编译器无法使用它们,因为 Function 只是一个未类型化的函数,因此没有任何好处。传递类型参数是无用的,并且可以说是一个错误(即用户不期望这是 Function 并且认为它们有一些效果而传递了类型参数)。

删除类型参数并放弃以任何方式键入的假装:

const { useValue } = useStore()
const [isPending, setIsPending] = useValue('isPending')
const [results, setResults] = useValue('results')

更有趣的问题是你为什么要写这样的代码,因为有一种方法可以完全键入这段代码中的所有内容:

const state = {
isPending: false,
results: ['a', 'b', 'c']
}
type State = typeof state;

const useStore = () => {
const useValue = <K extends keyof State>(name: K) => {
const value = state[name]
const setValue = (value: State[K]): void => {
state[name] = value
}
return [value, setValue] as const
}

return { state, useValue }
}
type UseStore = ReturnType<typeof useStore>;

const { useValue } = useStore()
const [isPending, setIsPending] = useValue('isPending')
const [results, setResults] = useValue('results')

上面的版本是完全类型安全的,不需要任何重复的名称或类型(您当然可以将其拆分为多个文件,但根据您的要求,可能需要进行一些重复)。如果这不适用于您的情况,我很想知道原因。

编辑

如果您只想让类型在最后几行运行并在那里有一些类型安全性,您只需要使用泛型指定函数的签名:

interface UseStore {
state: Record<string, any>
useValue: <T,>(name: string) => [T, (value: T)=> void]
}

const state: Record<string, any> = {
isPending: false,
results: ['a', 'b', 'c']
}

const useStore = (): UseStore => {
const useValue = <T,>(name: string): [T, (value: T)=> void] => {
const value: T = state[name]
const setValue = (value: T): void => {
state[name] = value
}
return [value, setValue]
}

return { state, useValue }
}

const { useValue } = useStore()
const [isPending, setIsPending] = useValue<boolean>('isPending')
const [results, setResults] = useValue<string[]>('results')

编辑 - 接口(interface)实现的开放式

您可以将State 定义为接口(interface),因为接口(interface)是开放式的,您可以在需要时添加成员。好处是如果其他人定义了一个名称相同但类型不同的属性,你会得到一个错误

界面状态{

}
// Don't know what is in here, empty object for starters
const state : State = {
} as State


const useStore = () => {
const useValue = <K extends keyof State>(name: K) => {
const value = state[name]
const setValue = (value: State[K]): void => {
state[name] = value
}
return [value, setValue] as const
}

return { state, useValue }
}
type UseStore = ReturnType<typeof useStore>;

const { useValue } = useStore()

interface State { isPending: boolean }
state.isPending = false; // no guarantee people actually intialize, maybe initial value can be passed to useValue ?
const [isPending, setIsPending] = useValue('isPending')

interface State { results: string[] }
state.results = ['a', 'b', 'c'];
const [results, setResults] = useValue('results')


interface State { results: number[] } // some else wants to use results for something else, err
const [results2, setResults2] = useValue('results')

关于javascript - typescript 泛型包装器 : Untyped function calls may not accept type arguments,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55790728/

50 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com