[英]Untyped function calls may not accept type arguments - Angular 5 http calls
[英]Typescript Generics wrapper: Untyped function calls may not accept type arguments
這個帶有泛型的代碼片段工作得很好( 鏈接到簡單和工作代碼)
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
是一個布爾值,而setIsPending
接收一個布爾值作為參數。 同樣適用於results
和setResults
作為字符串數組。
然后我用另一種方法useStore
包裝代碼( 鏈接到擴展損壞代碼)
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')
最后兩行給了我打字稿錯誤: Untyped function calls may not accept type arguments.
我懷疑useStore
接口有問題,但由於它的動態特性,我想不出更好的解決方案。
在使用 Generic 類型以獲得正確的類型提示和代碼完成時,如何擺脫錯誤?
由於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')
編輯 - 一個開放式的接口實現
您可以將State
定義為接口,因為接口是開放式的,您可以在需要時添加成員。 好處是如果其他人定義了一個名稱相同但類型不同的屬性,你會得到一個錯誤
接口狀態{
}
// 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')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.