繁体   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