簡體   English   中英

打字稿:如何為泛型類型定義對象鍵的類型

[英]Typescript: How to defined type of object key for generic type

我有一些像下面這樣的代碼。 我編寫了帶有泛型類型的自定義鈎子,用於定義我的鈎子的自定義類型返回。

type Return<T> = [T, (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void, Record<keyof T, boolean>, () => void]


function useInput<T>(): Return<T> {
    const [input, setInput] = useState<T>({} as T);
    const [isDirty, setDirty] = useState({} as Record<keyof T, boolean>);

    const handleInputChange = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
        setInput({
            ...input,
            [e.target.name]: e.target.value
        });
        setDirty({
            ...isDirty,
            [e.target.name]: true
        });
    };

    const resetInput = () => {
        Object.keys(input).forEach((v) => input[v] = ''); //this line i get error
        setInput({...input});
    };


    return [input, handleInputChange, isDirty, resetInput]
}

export default useInput;

我的通用類型T是對象。 但是當我遍歷這個時,我得到這個錯誤Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'. 如何為泛型類型T定義鍵類型? 請幫我。

所以Object.keys函數不是通用參數化的,因此 forEach 中的v始終是字符串。 這是推理原因 - 為什么 Object.keys 不返回 TypeScript 中的 keyof 類型? .

那就是說你不能縮小v類型,它只是字符串。 你可以做的是類型斷言:

 Object.keys(input).forEach((v) => input[v as keyof T] = '')

但是您將收到下一個錯誤,因為您沒有將T所有值定義為字符串,並且您將空字符串分配給它。 這實際上是正確的錯誤。 您不能為未知對象的每個字段分配一個字符串。

為了修復第二個我們需要縮小T的值類型

function useInput<T extends Record<string, string>>(): Return<T>

我們說現在T有鑰匙的,哪些是值string或亞型string 因為它們可以是字符串的子類型,所以我們需要在之后進行第二個斷言。 為什么 - 子類型可以是例如'a' | 'b' 'a' | 'b'等類型不能取空字符串值。

Object.keys(input).forEach((v) => (input[v as keyof T] as string) = '')

但是如果不說明T extends Record<string, string>我們將無法將此類的屬性類型斷言為string

正如我之前所說,這樣的實現有問題,它有風險,如果你有對象,例如type A { a: 'x' | 'y'} type A { a: 'x' | 'y'}並將其傳遞給這樣的構造,然后您可以在屬性a獲得空字符串,這是A類型A無效成員。 但是如果你使用只有string值的類型,我假設你這樣做了,那么它完全沒問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM